summaryrefslogtreecommitdiff
path: root/ace/OS_NS_Thread.h
diff options
context:
space:
mode:
authordhinton <dhinton@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2003-11-01 11:15:26 +0000
committerdhinton <dhinton@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2003-11-01 11:15:26 +0000
commit746f4ee6169d6cd8d8e5f8d6b3b368d3ac128ac6 (patch)
tree9a2cd7fff6f9e796968703bf3bb2cb7ca5c5bf82 /ace/OS_NS_Thread.h
parenta288d4fc55907205181362fee9979dc5cd9b9d07 (diff)
downloadATCD-746f4ee6169d6cd8d8e5f8d6b3b368d3ac128ac6.tar.gz
ChangeLogTag:Sat Nov 1 05:40:21 UTC 2003 Don Hinton <dhinton@dresystems.com>
Diffstat (limited to 'ace/OS_NS_Thread.h')
-rw-r--r--ace/OS_NS_Thread.h1709
1 files changed, 1707 insertions, 2 deletions
diff --git a/ace/OS_NS_Thread.h b/ace/OS_NS_Thread.h
index fc532b41367..530fafd662d 100644
--- a/ace/OS_NS_Thread.h
+++ b/ace/OS_NS_Thread.h
@@ -1,4 +1,1709 @@
// -*- C++ -*-
-// $Id$
-// This is a placeholder.
+//=============================================================================
+/**
+ * @file OS_NS_Thread.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ * @author Jesper S. M|ller<stophph@diku.dk>
+ * @author and a cast of thousands...
+ *
+ * Originally in OS.h.
+ */
+//=============================================================================
+
+#ifndef ACE_OS_NS_THREAD_H
+# define ACE_OS_NS_THREAD_H
+
+# include /**/ "ace/pre.h"
+
+# include "ace/config-all.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+# include "ace/Global_Macros.h"
+# include "ace/Basic_Types.h"
+# include "ace/Default_Constants.h"
+# include "ace/os_include/os_pthread.h"
+# include "ace/Base_Thread_Adapter.h"
+# include "ace/os_include/sys/os_sem.h"
+# include "ace/os_include/os_semaphore.h"
+# include "ace/OS_Memory.h"
+# include "ace/OS_NS_signal.h"
+
+# if defined (ACE_HAS_PRIOCNTL)
+ // Need to #include thread.h before #defining THR_BOUND, etc.,
+ // when building without threads on SunOS 5.x.
+# if defined (sun)
+# include /**/ <thread.h>
+# endif /* sun */
+
+ // Need to #include these before #defining USYNC_PROCESS on SunOS 5.x.
+# include /**/ <sys/rtpriocntl.h>
+# include /**/ <sys/tspriocntl.h>
+# endif /* ACE_HAS_PRIOCNTL */
+
+# if defined (ACE_PSOS)
+// Use pSOS semaphores, wrapped . . .
+typedef struct
+{
+ /// Semaphore handle. This is allocated by pSOS.
+ u_long sema_;
+
+ /// Name of the semaphore: really a 32 bit number to pSOS
+ char name_[4];
+} ACE_sema_t;
+# endif /* ACE_PSOS */
+
+# if defined (ACE_PSOS)
+
+// Wrapper for NT events on pSOS.
+class ACE_OS_Export ACE_event_t
+{
+protected:
+
+ /// Protect critical section.
+ ACE_mutex_t lock_;
+
+ /// Keeps track of waiters.
+ ACE_cond_t condition_;
+
+ /// Specifies if this is an auto- or manual-reset event.
+ int manual_reset_;
+
+ /// "True" if signaled.
+ int is_signaled_;
+
+ /// Number of waiting threads.
+ u_long waiting_threads_;
+};
+
+# endif /* ACE_PSOS */
+
+# if defined (ACE_WIN32)
+typedef DWORD ACE_thread_t;
+typedef HANDLE ACE_hthread_t;
+# if defined (ACE_HAS_TSS_EMULATION)
+ typedef DWORD ACE_OS_thread_key_t;
+ typedef u_int ACE_thread_key_t;
+# else /* ! ACE_HAS_TSS_EMULATION */
+ typedef DWORD ACE_thread_key_t;
+# endif /* ! ACE_HAS_TSS_EMULATION */
+# endif /* ACE_WIN32 */
+
+# if defined (ACE_HAS_THREADS)
+
+# if defined (ACE_HAS_STHREADS)
+# include /**/ <synch.h>
+# include /**/ <thread.h>
+# define ACE_SCOPE_PROCESS P_PID
+# define ACE_SCOPE_LWP P_LWPID
+# define ACE_SCOPE_THREAD (ACE_SCOPE_LWP + 1)
+# else
+# define ACE_SCOPE_PROCESS 0
+# define ACE_SCOPE_LWP 1
+# define ACE_SCOPE_THREAD 2
+# endif /* ACE_HAS_STHREADS */
+
+# if !defined (ACE_HAS_PTHREADS)
+# define ACE_SCHED_OTHER 0
+# define ACE_SCHED_FIFO 1
+# define ACE_SCHED_RR 2
+# endif /* ! ACE_HAS_PTHREADS */
+
+# if defined (ACE_HAS_PTHREADS)
+// moved to pthread.h
+# elif defined (ACE_HAS_STHREADS)
+// Solaris threads, without PTHREADS.
+// Typedefs to help compatibility with Windows NT and Pthreads.
+typedef thread_t ACE_thread_t;
+typedef thread_key_t ACE_thread_key_t;
+typedef mutex_t ACE_mutex_t;
+# if !defined (ACE_LACKS_RWLOCK_T)
+typedef rwlock_t ACE_rwlock_t;
+# endif /* !ACE_LACKS_RWLOCK_T */
+# if !defined (ACE_HAS_POSIX_SEM)
+typedef sema_t ACE_sema_t;
+# endif /* !ACE_HAS_POSIX_SEM */
+
+typedef cond_t ACE_cond_t;
+struct ACE_OS_Export ACE_condattr_t
+{
+ int type;
+};
+struct ACE_OS_Export ACE_mutexattr_t
+{
+ int type;
+};
+typedef ACE_thread_t ACE_hthread_t;
+typedef ACE_mutex_t ACE_thread_mutex_t;
+
+# define THR_CANCEL_DISABLE 0
+# define THR_CANCEL_ENABLE 0
+# define THR_CANCEL_DEFERRED 0
+# define THR_CANCEL_ASYNCHRONOUS 0
+# define THR_JOINABLE 0
+# define THR_SCHED_FIFO 0
+# define THR_SCHED_RR 0
+# define THR_SCHED_DEFAULT 0
+
+# elif defined (ACE_PSOS)
+
+// Some versions of pSOS provide native mutex support. For others,
+// implement ACE_thread_mutex_t and ACE_mutex_t using pSOS semaphores.
+// Either way, the types are all u_longs.
+typedef u_long ACE_mutex_t;
+typedef u_long ACE_thread_mutex_t;
+typedef u_long ACE_thread_t;
+typedef u_long ACE_hthread_t;
+
+# if defined (ACE_PSOS_HAS_COND_T)
+typedef u_long ACE_cond_t;
+typedef u_long ACE_condattr_t;
+struct ACE_OS_Export ACE_mutexattr_t
+{
+ int type;
+};
+# endif /* ACE_PSOS_HAS_COND_T */
+
+
+// TCB registers 0-7 are for application use
+# define PSOS_TASK_REG_TSS 0
+# define PSOS_TASK_REG_MAX 7
+
+# define PSOS_TASK_MIN_PRIORITY 1
+# define PSOS_TASK_MAX_PRIORITY 239
+
+// Key type: the ACE TSS emulation requires the key type be unsigned,
+// for efficiency. Current POSIX and Solaris TSS implementations also
+// use unsigned int, so the ACE TSS emulation is compatible with them.
+// Native pSOS TSD, where available, uses unsigned long as the key type.
+# if defined (ACE_PSOS_HAS_TSS)
+typedef u_long ACE_thread_key_t;
+# else
+typedef u_int ACE_thread_key_t;
+# endif /* ACE_PSOS_HAS_TSS */
+
+# define THR_CANCEL_DISABLE 0 /* thread can never be cancelled */
+# define THR_CANCEL_ENABLE 0 /* thread can be cancelled */
+# define THR_CANCEL_DEFERRED 0 /* cancellation deferred to cancellation point */
+# define THR_CANCEL_ASYNCHRONOUS 0 /* cancellation occurs immediately */
+
+# define THR_BOUND 0
+# define THR_NEW_LWP 0
+# define THR_DETACHED 0
+# define THR_SUSPENDED 0
+# define THR_DAEMON 0
+# define THR_JOINABLE 0
+
+# define THR_SCHED_FIFO 0
+# define THR_SCHED_RR 0
+# define THR_SCHED_DEFAULT 0
+# define USYNC_THREAD T_LOCAL
+# define USYNC_PROCESS T_GLOBAL
+
+/* from psos.h */
+/* #define T_NOPREEMPT 0x00000001 Not preemptible bit */
+/* #define T_PREEMPT 0x00000000 Preemptible */
+/* #define T_TSLICE 0x00000002 Time-slicing enabled bit */
+/* #define T_NOTSLICE 0x00000000 No Time-slicing */
+/* #define T_NOASR 0x00000004 ASRs disabled bit */
+/* #define T_ASR 0x00000000 ASRs enabled */
+
+/* #define SM_GLOBAL 0x00000001 1 = Global */
+/* #define SM_LOCAL 0x00000000 0 = Local */
+/* #define SM_PRIOR 0x00000002 Queue by priority */
+/* #define SM_FIFO 0x00000000 Queue by FIFO order */
+
+/* #define T_NOFPU 0x00000000 Not using FPU */
+/* #define T_FPU 0x00000002 Using FPU bit */
+
+
+
+
+
+
+# elif defined (VXWORKS)
+# include /**/ <sysLib.h> // for sysClkRateGet()
+# include /**/ <taskLib.h>
+# include /**/ <taskHookLib.h>
+
+// make sure these are included for VXWORKS.
+// @todo move these to a common place, perhaps the top of the file.
+# include "ace/os_include/os_fcntl.h"
+# include "ace/os_include/os_netdb.h"
+# include "ace/os_include/os_semaphore.h"
+# include "ace/os_include/os_signal.h"
+# include "ace/os_include/os_stdio.h"
+# include "ace/os_include/os_stdlib.h"
+# include "ace/os_include/os_stropts.h"
+# include "ace/os_include/os_unistd.h"
+# include "ace/os_include/arpa/os_inet.h"
+# include "ace/os_include/sys/os_select.h"
+# include "ace/os_include/sys/os_socket.h"
+
+// task options: the other options are either obsolete, internal, or for
+// Fortran or Ada support
+# define VX_UNBREAKABLE 0x0002 /* breakpoints ignored */
+# define VX_FP_TASK 0x0008 /* floating point coprocessor */
+# define VX_PRIVATE_ENV 0x0080 /* private environment support */
+# define VX_NO_STACK_FILL 0x0100 /* do not stack fill for
+ checkstack () */
+
+# define THR_CANCEL_DISABLE 0
+# define THR_CANCEL_ENABLE 0
+# define THR_CANCEL_DEFERRED 0
+# define THR_CANCEL_ASYNCHRONOUS 0
+# define THR_BOUND 0
+# define THR_NEW_LWP 0
+# define THR_DETACHED 0
+# define THR_SUSPENDED 0
+# define THR_DAEMON 0
+# define THR_JOINABLE 0
+# define THR_SCHED_FIFO 0
+# define THR_SCHED_RR 0
+# define THR_SCHED_DEFAULT 0
+# define THR_INHERIT_SCHED 0
+# define THR_EXPLICIT_SCHED 0
+# define THR_SCHED_IO 0
+# define THR_SCOPE_SYSTEM 0
+# define THR_SCOPE_PROCESS 0
+# define USYNC_THREAD 0
+# define USYNC_PROCESS 1 /* It's all global on VxWorks
+ (without MMU option). */
+
+typedef SEM_ID ACE_mutex_t;
+// Implement ACE_thread_mutex_t with ACE_mutex_t because there's just
+// one process . . .
+typedef ACE_mutex_t ACE_thread_mutex_t;
+# if !defined (ACE_HAS_POSIX_SEM)
+// Use VxWorks semaphores, wrapped ...
+typedef struct
+{
+ /// Semaphore handle. This is allocated by VxWorks.
+ SEM_ID sema_;
+
+ /// Name of the semaphore: always NULL with VxWorks.
+ char *name_;
+} ACE_sema_t;
+# endif /* !ACE_HAS_POSIX_SEM */
+typedef char * ACE_thread_t;
+typedef int ACE_hthread_t;
+// Key type: the ACE TSS emulation requires the key type be unsigned,
+// for efficiency. (Current POSIX and Solaris TSS implementations also
+// use u_int, so the ACE TSS emulation is compatible with them.)
+typedef u_int ACE_thread_key_t;
+
+ // Marker for ACE_Thread_Manager to indicate that it allocated
+ // an ACE_thread_t. It is placed at the beginning of the ID.
+# define ACE_THR_ID_ALLOCATED '\022'
+
+# elif defined (ACE_HAS_WTHREADS)
+
+typedef CRITICAL_SECTION ACE_thread_mutex_t;
+
+typedef struct
+{
+ /// Either USYNC_THREAD or USYNC_PROCESS
+ int type_;
+ union
+ {
+ HANDLE proc_mutex_;
+ CRITICAL_SECTION thr_mutex_;
+ };
+} ACE_mutex_t;
+
+// Wrapper for NT Events.
+typedef HANDLE ACE_event_t;
+
+# if defined (ACE_WIN32)
+//@@ ACE_USES_WINCE_SEMA_SIMULATION is used to debug
+// semaphore simulation on WinNT. It should be
+// changed to ACE_USES_HAS_WINCE at some later point.
+# if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
+typedef HANDLE ACE_sema_t;
+# else
+/**
+ * @class ACE_sema_t
+ *
+ * @brief Semaphore simulation for Windows CE.
+ */
+class ACE_OS_Export ACE_sema_t
+{
+public:
+ /// Serializes access to <count_>.
+ ACE_thread_mutex_t lock_;
+
+ /// This event is signaled whenever the count becomes non-zero.
+ ACE_event_t count_nonzero_;
+
+ /// Current count of the semaphore.
+ u_int count_;
+};
+
+# endif /* ACE_USES_WINCE_SEMA_SIMULATION */
+# endif /* defined (ACE_WIN32) */
+
+// These need to be different values, neither of which can be 0...
+# define USYNC_THREAD 1
+# define USYNC_PROCESS 2
+
+# define THR_CANCEL_DISABLE 0
+# define THR_CANCEL_ENABLE 0
+# define THR_CANCEL_DEFERRED 0
+# define THR_CANCEL_ASYNCHRONOUS 0
+# define THR_DETACHED 0x02000000 /* ignore in most places */
+# define THR_BOUND 0 /* ignore in most places */
+# define THR_NEW_LWP 0 /* ignore in most places */
+# define THR_DAEMON 0 /* ignore in most places */
+# define THR_JOINABLE 0 /* ignore in most places */
+# define THR_SUSPENDED CREATE_SUSPENDED
+# define THR_USE_AFX 0x01000000
+# define THR_SCHED_FIFO 0
+# define THR_SCHED_RR 0
+# define THR_SCHED_DEFAULT 0
+# define THR_SCOPE_PROCESS 0
+# define THR_SCOPE_SYSTEM 0
+# endif /* ACE_HAS_PTHREADS / STHREADS / PSOS / VXWORKS / WTHREADS **********/
+
+// If we're using PACE then we don't want this class (since PACE
+// takes care of it) unless we're on Windows. Win32 mutexes, semaphores,
+// and condition variables are not yet supported in PACE.
+# if defined (ACE_LACKS_COND_T)
+/**
+ * @class ACE_cond_t
+ *
+ * @brief This structure is used to implement condition variables on
+ * platforms that lack it natively, such as VxWorks, pSoS, and
+ * Win32.
+ *
+ * At the current time, this stuff only works for threads
+ * within the same process.
+ */
+class ACE_OS_Export ACE_cond_t
+{
+public:
+
+ /// Returns the number of waiters.
+ long waiters (void) const;
+
+//protected:
+ /// Number of waiting threads.
+ long waiters_;
+
+ /// Serialize access to the waiters count.
+ ACE_thread_mutex_t waiters_lock_;
+
+ /// Queue up threads waiting for the condition to become signaled.
+ ACE_sema_t sema_;
+
+# if defined (VXWORKS) || defined (ACE_PSOS)
+ /**
+ * A semaphore used by the broadcast/signal thread to wait for all
+ * the waiting thread(s) to wake up and be released from the
+ * semaphore.
+ */
+ ACE_sema_t waiters_done_;
+# elif defined (ACE_WIN32)
+ /**
+ * An auto reset event used by the broadcast/signal thread to wait
+ * for the waiting thread(s) to wake up and get a chance at the
+ * semaphore.
+ */
+ HANDLE waiters_done_;
+# else
+# error "Please implement this feature or check your config.h file!"
+# endif /* VXWORKS || ACE_PSOS */
+
+ /// Keeps track of whether we were broadcasting or just signaling.
+ size_t was_broadcast_;
+};
+
+struct ACE_OS_Export ACE_condattr_t
+{
+ int type;
+};
+
+struct ACE_OS_Export ACE_mutexattr_t
+{
+ int type;
+};
+# endif /* ACE_LACKS_COND_T */
+
+# if defined (ACE_LACKS_RWLOCK_T) && !defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+
+/**
+ * @class ACE_rwlock_t
+ *
+ * @brief This is used to implement readers/writer locks on NT,
+ * VxWorks, and POSIX pthreads.
+ *
+ * At the current time, this stuff only works for threads
+ * within the same process.
+ */
+struct ACE_OS_Export ACE_rwlock_t
+{
+public:
+//protected:
+
+ ACE_mutex_t lock_;
+ // Serialize access to internal state.
+
+ ACE_cond_t waiting_readers_;
+ // Reader threads waiting to acquire the lock.
+
+ int num_waiting_readers_;
+ // Number of waiting readers.
+
+ ACE_cond_t waiting_writers_;
+ // Writer threads waiting to acquire the lock.
+
+ int num_waiting_writers_;
+ // Number of waiting writers.
+
+ int ref_count_;
+ // Value is -1 if writer has the lock, else this keeps track of the
+ // number of readers holding the lock.
+
+ int important_writer_;
+ // indicate that a reader is trying to upgrade
+
+ ACE_cond_t waiting_important_writer_;
+ // condition for the upgrading reader
+};
+//# elif defined (ACE_HAS_PTHREADS_UNIX98_EXT)
+//typedef pthread_rwlock_t ACE_rwlock_t;
+# elif defined (ACE_HAS_STHREADS)
+# include /**/ <synch.h>
+typedef rwlock_t ACE_rwlock_t;
+# endif /* ACE_LACKS_RWLOCK_T */
+
+// Define some default thread priorities on all threaded platforms, if
+// not defined above or in the individual platform config file.
+// ACE_THR_PRI_FIFO_DEF should be used by applications for default
+// real-time thread priority. ACE_THR_PRI_OTHER_DEF should be used
+// for non-real-time priority.
+# if !defined(ACE_THR_PRI_FIFO_DEF)
+# if defined (ACE_WTHREADS)
+ // It would be more in spirit to use THREAD_PRIORITY_NORMAL. But,
+ // using THREAD_PRIORITY_ABOVE_NORMAL should give preference to the
+ // threads in this process, even if the process is not in the
+ // REALTIME_PRIORITY_CLASS.
+# define ACE_THR_PRI_FIFO_DEF THREAD_PRIORITY_ABOVE_NORMAL
+# else /* ! ACE_WTHREADS */
+# define ACE_THR_PRI_FIFO_DEF 0
+# endif /* ! ACE_WTHREADS */
+# endif /* ! ACE_THR_PRI_FIFO_DEF */
+
+# if !defined(ACE_THR_PRI_OTHER_DEF)
+# if defined (ACE_WTHREADS)
+ // It would be more in spirit to use THREAD_PRIORITY_NORMAL. But,
+ // using THREAD_PRIORITY_ABOVE_NORMAL should give preference to the
+ // threads in this process, even if the process is not in the
+ // REALTIME_PRIORITY_CLASS.
+# define ACE_THR_PRI_OTHER_DEF THREAD_PRIORITY_NORMAL
+# else /* ! ACE_WTHREADS */
+# define ACE_THR_PRI_OTHER_DEF 0
+# endif /* ! ACE_WTHREADS */
+# endif /* ! ACE_THR_PRI_OTHER_DEF */
+
+// Recursive mutex support.
+//
+// There are two parts to this:
+// 1. The mutex type itself. This is based on whether or not the
+// platform supports recursive mutexes natively or they're emulated.
+// 2. Support for using the recursive mutex with a condition variable.
+// When a thread waits on a condition variable, it has to relinquish
+// the lock and wait atomically, then reacquire it after the condition
+// variable is signaled. In non-recursive mutexes, the platform
+// handles this automatically. But in recursive mutexes, especially
+// when emulated, the recursion count needs to be maintained across
+// the wait. Since another thread needs to be able to acquire the
+// lock, it needs to appear free, even if the waiting thread had done
+// multiple acquires. Thus, there's another structure to hold this
+// information, and is used with the recursive_mutex_cond_unlock()
+// and recursive_mutex_cond_relock() methods to maintain the expected
+// state when the wait finishes.
+# if defined (ACE_HAS_RECURSIVE_MUTEXES)
+typedef ACE_thread_mutex_t ACE_recursive_thread_mutex_t;
+# if defined (ACE_WIN32)
+// Windows has recursive mutexes, but doesn't have condition variables,
+// so there's no built-in support for this. Thus, the condition-related
+// unlock/relock is augmented in ACE.
+struct ACE_recursive_mutex_state
+{
+ // On Windows the augmented processing is simply unlocking/relocking
+ // the recursive locks - the condition handles a single lock ok.
+ LONG relock_count_;
+};
+# else
+// No need for special handling; just need a type for method signatures.
+typedef int ACE_recursive_mutex_state;
+# endif /* ACE_WIN32 */
+# else
+/**
+ * @class ACE_recursive_thread_mutex_t
+ *
+ * @brief Implement a thin C++ wrapper that allows nested acquisition
+ * and release of a mutex that occurs in the same thread.
+ *
+ * This implementation is based on an algorithm sketched by Dave
+ * Butenhof <butenhof@zko.dec.com>. Naturally, I take the
+ * credit for any mistakes ;-)
+ */
+class ACE_recursive_thread_mutex_t
+{
+public:
+ /// Guards the state of the nesting level and thread id.
+ ACE_thread_mutex_t nesting_mutex_;
+
+ /// This condition variable suspends other waiting threads until the
+ /// mutex is available.
+ ACE_cond_t lock_available_;
+
+ /// Current nesting level of the recursion.
+ int nesting_level_;
+
+ /// Current owner of the lock.
+ ACE_thread_t owner_id_;
+};
+
+// Since recursive mutex is emulated, the state saving needs to be handled
+// in ACE as well. These members save those from ACE_recursive_thread_mutex_t.
+struct ACE_recursive_mutex_state
+{
+ int nesting_level_;
+ ACE_thread_t owner_id_;
+};
+# endif /* ACE_HAS_RECURSIVE_MUTEXES */
+
+# else /* !ACE_HAS_THREADS, i.e., the OS/platform doesn't support threading. */
+
+// Give these things some reasonable value...
+# define ACE_SCOPE_PROCESS 0
+# define ACE_SCOPE_LWP 1
+# define ACE_SCOPE_THREAD 2
+# define ACE_SCHED_OTHER 0
+# define ACE_SCHED_FIFO 1
+# define ACE_SCHED_RR 2
+# if !defined (THR_CANCEL_DISABLE)
+# define THR_CANCEL_DISABLE 0
+# endif /* ! THR_CANCEL_DISABLE */
+# if !defined (THR_CANCEL_ENABLE)
+# define THR_CANCEL_ENABLE 0
+# endif /* ! THR_CANCEL_ENABLE */
+# if !defined (THR_CANCEL_DEFERRED)
+# define THR_CANCEL_DEFERRED 0
+# endif /* ! THR_CANCEL_DEFERRED */
+# if !defined (THR_CANCEL_ASYNCHRONOUS)
+# define THR_CANCEL_ASYNCHRONOUS 0
+# endif /* ! THR_CANCEL_ASYNCHRONOUS */
+# if !defined (THR_JOINABLE)
+# define THR_JOINABLE 0 /* ignore in most places */
+# endif /* ! THR_JOINABLE */
+# if !defined (THR_DETACHED)
+# define THR_DETACHED 0 /* ignore in most places */
+# endif /* ! THR_DETACHED */
+# if !defined (THR_DAEMON)
+# define THR_DAEMON 0 /* ignore in most places */
+# endif /* ! THR_DAEMON */
+# if !defined (THR_BOUND)
+# define THR_BOUND 0 /* ignore in most places */
+# endif /* ! THR_BOUND */
+# if !defined (THR_NEW_LWP)
+# define THR_NEW_LWP 0 /* ignore in most places */
+# endif /* ! THR_NEW_LWP */
+# if !defined (THR_SUSPENDED)
+# define THR_SUSPENDED 0 /* ignore in most places */
+# endif /* ! THR_SUSPENDED */
+# if !defined (THR_SCHED_FIFO)
+# define THR_SCHED_FIFO 0
+# endif /* ! THR_SCHED_FIFO */
+# if !defined (THR_SCHED_RR)
+# define THR_SCHED_RR 0
+# endif /* ! THR_SCHED_RR */
+# if !defined (THR_SCHED_DEFAULT)
+# define THR_SCHED_DEFAULT 0
+# endif /* ! THR_SCHED_DEFAULT */
+# if !defined (USYNC_THREAD)
+# define USYNC_THREAD 0
+# endif /* ! USYNC_THREAD */
+# if !defined (USYNC_PROCESS)
+# define USYNC_PROCESS 0
+# endif /* ! USYNC_PROCESS */
+# if !defined (THR_SCOPE_PROCESS)
+# define THR_SCOPE_PROCESS 0
+# endif /* ! THR_SCOPE_PROCESS */
+# if !defined (THR_SCOPE_SYSTEM)
+# define THR_SCOPE_SYSTEM 0
+# endif /* ! THR_SCOPE_SYSTEM */
+
+// These are dummies needed for class OS.h
+typedef int ACE_cond_t;
+struct ACE_OS_Export ACE_condattr_t
+{
+ int type;
+};
+struct ACE_OS_Export ACE_mutexattr_t
+{
+ int type;
+};
+typedef int ACE_mutex_t;
+typedef int ACE_thread_mutex_t;
+typedef int ACE_recursive_thread_mutex_t;
+typedef int ACE_recursive_mutex_state;
+# if !defined (ACE_HAS_POSIX_SEM) && !defined (ACE_PSOS)
+typedef int ACE_sema_t;
+# endif /* !ACE_HAS_POSIX_SEM && !ACE_PSOS */
+typedef int ACE_rwlock_t;
+typedef int ACE_thread_t;
+typedef int ACE_hthread_t;
+typedef unsigned int ACE_thread_key_t;
+
+// Ensure that ACE_THR_PRI_FIFO_DEF and ACE_THR_PRI_OTHER_DEF are
+// defined on non-threaded platforms, to support application source
+// code compatibility. ACE_THR_PRI_FIFO_DEF should be used by
+// applications for default real-time thread priority.
+// ACE_THR_PRI_OTHER_DEF should be used for non-real-time priority.
+# if !defined(ACE_THR_PRI_FIFO_DEF)
+# define ACE_THR_PRI_FIFO_DEF 0
+# endif /* ! ACE_THR_PRI_FIFO_DEF */
+# if !defined(ACE_THR_PRI_OTHER_DEF)
+# define ACE_THR_PRI_OTHER_DEF 0
+# endif /* ! ACE_THR_PRI_OTHER_DEF */
+
+# endif /* ACE_HAS_THREADS ***********************************************/
+
+/**
+ * @class ACE_Thread_ID
+ *
+ * @brief Defines a platform-independent thread ID.
+ */
+class ACE_OS_Export ACE_Thread_ID
+{
+public:
+ // = Initialization method.
+ ACE_Thread_ID (ACE_thread_t, ACE_hthread_t);
+ ACE_Thread_ID (const ACE_Thread_ID &id);
+
+ // = Set/Get the Thread ID.
+ ACE_thread_t id (void);
+ void id (ACE_thread_t);
+
+ // = Set/Get the Thread handle.
+ ACE_hthread_t handle (void);
+ void handle (ACE_hthread_t);
+
+ void to_string (char*);
+
+
+ // != Comparison operator.
+ int operator== (const ACE_Thread_ID &) const;
+ int operator!= (const ACE_Thread_ID &) const;
+
+private:
+ /// Identify the thread.
+ ACE_thread_t thread_id_;
+
+ /// Handle to the thread (typically used to "wait" on Win32).
+ ACE_hthread_t thread_handle_;
+};
+
+// = The ACE_Sched_Priority type should be used for platform-
+// independent thread and process priorities, by convention.
+// int should be used for OS-specific priorities.
+typedef int ACE_Sched_Priority;
+
+# if !defined (ACE_DEFAULT_SYNCH_TYPE)
+# if defined (VXWORKS)
+ // Types include these options: SEM_Q_PRIORITY, SEM_Q_FIFO,
+ // SEM_DELETE_SAFE, and SEM_INVERSION_SAFE. SEM_Q_FIFO is
+ // used as the default because that is VxWorks' default.
+# define ACE_DEFAULT_SYNCH_TYPE SEM_Q_FIFO
+# else
+# define ACE_DEFAULT_SYNCH_TYPE USYNC_THREAD
+# endif /* VXWORKS */
+#endif /* ! ACE_DEFAULT_SYNCH_TYPE */
+
+// forward declaration
+class ACE_Sched_Params;
+class ACE_Time_Value;
+
+# if defined (ACE_PSOS)
+typedef u_long ACE_idtype_t;
+typedef u_long ACE_id_t;
+typedef u_long ACE_pri_t;
+# define ACE_SELF (0)
+# elif defined (ACE_WIN32)
+typedef int ACE_idtype_t;
+typedef DWORD ACE_id_t;
+typedef int ACE_pri_t;
+# define ACE_SELF (0)
+# else /* !defined (ACE_WIN32) && !defined (ACE_PSOS) */
+# if defined (ACE_HAS_IDTYPE_T)
+ typedef idtype_t ACE_idtype_t;
+# else
+ typedef int ACE_idtype_t;
+# endif /* ACE_HAS_IDTYPE_T */
+# if defined (ACE_HAS_STHREADS) || defined (DIGITAL_UNIX)
+# if defined (ACE_LACKS_PRI_T)
+ typedef int pri_t;
+# endif /* ACE_LACKS_PRI_T */
+ typedef id_t ACE_id_t;
+# define ACE_SELF P_MYID
+ typedef pri_t ACE_pri_t;
+# else /* ! ACE_HAS_STHREADS && ! DIGITAL_UNIX */
+ typedef long ACE_id_t;
+# define ACE_SELF (-1)
+ typedef short ACE_pri_t;
+# endif /* ! ACE_HAS_STHREADS && ! DIGITAL_UNIX */
+# endif /* !defined (ACE_WIN32) && !defined (ACE_PSOS) */
+
+# if defined (ACE_HAS_TSS_EMULATION)
+ // Allow config.h to set the default number of thread keys.
+# if !defined (ACE_DEFAULT_THREAD_KEYS)
+# define ACE_DEFAULT_THREAD_KEYS 64
+# endif /* ! ACE_DEFAULT_THREAD_KEYS */
+
+// forward declaration
+class ACE_TSS_Keys;
+
+/**
+ * @class ACE_TSS_Emulation
+ *
+ * @brief Thread-specific storage emulation.
+ *
+ * This provides a thread-specific storage implementation.
+ * It is intended for use on platforms that don't have a
+ * native TSS, or have a TSS with limitations such as the
+ * number of keys or lack of support for removing keys.
+ */
+class ACE_OS_Export ACE_TSS_Emulation
+{
+public:
+ typedef void (*ACE_TSS_DESTRUCTOR)(void *value) /* throw () */;
+
+ /// Maximum number of TSS keys allowed over the life of the program.
+ enum { ACE_TSS_THREAD_KEYS_MAX = ACE_DEFAULT_THREAD_KEYS };
+
+ /// Returns the total number of keys allocated so far.
+ static u_int total_keys ();
+
+ /// Sets the argument to the next available key. Returns 0 on success,
+ /// -1 if no keys are available.
+ static int next_key (ACE_thread_key_t &key);
+
+ /// Release a key that was used. This way the key can be given out in a
+ /// new request. Returns 0 on success, 1 if the key was not reserved.
+ static int release_key (ACE_thread_key_t key);
+
+ /// Returns the exit hook associated with the key. Does _not_ check
+ /// for a valid key.
+ static ACE_TSS_DESTRUCTOR tss_destructor (const ACE_thread_key_t key);
+
+ /// Associates the TSS destructor with the key. Does _not_ check
+ /// for a valid key.
+ static void tss_destructor (const ACE_thread_key_t key,
+ ACE_TSS_DESTRUCTOR destructor);
+
+ /// Accesses the object referenced by key in the current thread's TSS array.
+ /// Does _not_ check for a valid key.
+ static void *&ts_object (const ACE_thread_key_t key);
+
+ /**
+ * Setup an array to be used for local TSS. Returns the array
+ * address on success. Returns 0 if local TSS had already been
+ * setup for this thread. There is no corresponding tss_close ()
+ * because it is not needed.
+ * NOTE: tss_open () is called by ACE for threads that it spawns.
+ * If your application spawns threads without using ACE, and it uses
+ * ACE's TSS emulation, each of those threads should call tss_open
+ * (). See the ace_thread_adapter () implementation for an example.
+ */
+ static void *tss_open (void *ts_storage[ACE_TSS_THREAD_KEYS_MAX]);
+
+ /// Shutdown TSS emulation. For use only by ACE_OS::cleanup_tss ().
+ static void tss_close ();
+
+private:
+ // Global TSS structures.
+ /// Contains the possible value of the next key to be allocated. Which key
+ /// is actually allocated is based on the tss_keys_used
+ static u_int total_keys_;
+
+ /// Array of thread exit hooks (TSS destructors) that are called for each
+ /// key (that has one) when the thread exits.
+ static ACE_TSS_DESTRUCTOR tss_destructor_ [ACE_TSS_THREAD_KEYS_MAX];
+
+ /// TSS_Keys instance to administrate whether a specific key is in used
+ /// or not
+ static ACE_TSS_Keys tss_keys_used_;
+
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ /// Location of current thread's TSS array.
+ static void **tss_base (void* ts_storage[] = 0, u_int *ts_created = 0);
+# else /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */
+ /// Location of current thread's TSS array.
+ static void **&tss_base ();
+# endif /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */
+
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ // Rely on native thread specific storage for the implementation,
+ // but just use one key.
+ static ACE_OS_thread_key_t native_tss_key_;
+
+ // Used to indicate if native tss key has been allocated
+ static int key_created_;
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
+};
+
+# else /* ! ACE_HAS_TSS_EMULATION */
+# if defined (TLS_MINIMUM_AVAILABLE)
+ // WIN32 platforms define TLS_MINIMUM_AVAILABLE natively.
+# define ACE_DEFAULT_THREAD_KEYS TLS_MINIMUM_AVAILABLE
+# endif /* TSL_MINIMUM_AVAILABLE */
+
+# endif /* ACE_HAS_TSS_EMULATION */
+
+// moved ACE_TSS_Ref, ACE_TSS_Info, and ACE_TSS_Keys class
+// declarations from OS.cpp so they are visible to the single
+// file of template instantiations.
+# if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS))
+/**
+ * @class ACE_TSS_Ref
+ *
+ * @brief "Reference count" for thread-specific storage keys.
+ *
+ * Since the <ACE_Unbounded_Stack> doesn't allow duplicates, the
+ * "reference count" is the identify of the thread_id.
+ */
+class ACE_TSS_Ref
+{
+public:
+ /// Constructor
+ ACE_TSS_Ref (ACE_thread_t id);
+
+ /// Default constructor
+ ACE_TSS_Ref (void);
+
+ /// Check for equality.
+ int operator== (const ACE_TSS_Ref &) const;
+
+ /// Check for inequality.
+ int operator!= (const ACE_TSS_Ref &) const;
+
+// private:
+
+ /// ID of thread using a specific key.
+ ACE_thread_t tid_;
+};
+
+/**
+ * @class ACE_TSS_Info
+ *
+ * @brief Thread Specific Key management.
+ *
+ * This class maps a key to a "destructor."
+ */
+class ACE_TSS_Info
+{
+public:
+ /// Constructor
+ ACE_TSS_Info (ACE_thread_key_t key,
+ void (*dest)(void *) = 0,
+ void *tss_inst = 0);
+
+ /// Default constructor
+ ACE_TSS_Info (void);
+
+ /// Returns 1 if the key is in use, 0 if not.
+ int key_in_use (void) const { return thread_count_ != -1; }
+
+ /// Mark the key as being in use if the flag is non-zero, or
+ /// not in use if the flag is 0.
+ void key_in_use (int flag) { thread_count_ = flag == 0 ? -1 : 1; }
+
+ /// Check for equality.
+ int operator== (const ACE_TSS_Info &) const;
+
+ /// Check for inequality.
+ int operator!= (const ACE_TSS_Info &) const;
+
+ /// Dump the state.
+ void dump (void);
+
+private:
+ /// Key to the thread-specific storage item.
+ ACE_thread_key_t key_;
+
+ /// "Destructor" that gets called when the item is finally released.
+ void (*destructor_)(void *);
+
+ /// Pointer to ACE_TSS<xxx> instance that has/will allocate the key.
+ void *tss_obj_;
+
+ /// Count of threads that are using this key. Contains -1 when the
+ /// key is not in use.
+ int thread_count_;
+
+ friend class ACE_TSS_Cleanup;
+};
+
+/**
+ * @class ACE_TSS_Keys
+ *
+ * @brief Collection of in-use flags for a thread's TSS keys.
+ * For internal use only by ACE_TSS_Cleanup; it is public because
+ * some compilers can't use nested classes for template instantiation
+ * parameters.
+ *
+ * Wrapper around array of whether each key is in use. A simple
+ * typedef doesn't work with Sun C++ 4.2.
+ */
+class ACE_TSS_Keys
+{
+public:
+ /// Default constructor, to initialize all bits to zero (unused).
+ ACE_TSS_Keys (void);
+
+ /// Mark the specified key as being in use, if it was not already so marked.
+ /// Returns 1 if the had already been marked, 0 if not.
+ int test_and_set (const ACE_thread_key_t key);
+
+ /// Mark the specified key as not being in use, if it was not already so
+ /// cleared. Returns 1 if the key had already been cleared, 0 if not.
+ int test_and_clear (const ACE_thread_key_t key);
+
+ /// Return whether the specific key is marked as in use.
+ /// Returns 1 if the key is been marked, 0 if not.
+ int is_set (const ACE_thread_key_t key) const;
+
+private:
+ /// For a given key, find the word and bit number that represent it.
+ static void find (const u_int key, u_int &word, u_int &bit);
+
+ enum
+ {
+# if ACE_SIZEOF_LONG == 8
+ ACE_BITS_PER_WORD = 64,
+# elif ACE_SIZEOF_LONG == 4
+ ACE_BITS_PER_WORD = 32,
+# else
+# error ACE_TSS_Keys only supports 32 or 64 bit longs.
+# endif /* ACE_SIZEOF_LONG == 8 */
+ ACE_WORDS = (ACE_DEFAULT_THREAD_KEYS - 1) / ACE_BITS_PER_WORD + 1
+ };
+
+ /// Bit flag collection. A bit value of 1 indicates that the key is in
+ /// use by this thread.
+ u_long key_bit_words_[ACE_WORDS];
+};
+
+# endif /* defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) */
+
+// Support non-scalar thread keys, such as with some POSIX
+// implementations, e.g., MVS.
+# if defined (ACE_HAS_NONSCALAR_THREAD_KEY_T)
+# define ACE_KEY_INDEX(OBJ,KEY) \
+ u_int OBJ; \
+ ACE_OS::memcpy (&OBJ, &KEY, sizeof (u_int))
+# else
+# define ACE_KEY_INDEX(OBJ,KEY) u_int OBJ = KEY
+# endif /* ACE_HAS_NONSCALAR_THREAD_KEY_T */
+
+# if defined (ACE_HAS_THR_C_FUNC)
+// This is necessary to work around nasty problems with MVS C++.
+extern "C" ACE_OS_Export void ace_mutex_lock_cleanup_adapter (void *args);
+# define ACE_PTHREAD_CLEANUP_PUSH(A) pthread_cleanup_push (ace_mutex_lock_cleanup_adapter, (void *) A);
+# define ACE_PTHREAD_CLEANUP_POP(A) pthread_cleanup_pop(A)
+# elif defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CLEANUP)
+// Though we are defining a extern "C" function to match the prototype of
+// pthread_cleanup_push, it is undone by the Solaris header file
+// /usr/include/pthread.h. So this macro generates a warning under Solaris
+// with SunCC. This is a bug in the Solaris header file.
+extern "C" ACE_OS_Export void ace_mutex_lock_cleanup_adapter (void *args);
+# define ACE_PTHREAD_CLEANUP_PUSH(A) pthread_cleanup_push (ace_mutex_lock_cleanup_adapter, (void *) A);
+# define ACE_PTHREAD_CLEANUP_POP(A) pthread_cleanup_pop(A)
+# else
+# define ACE_PTHREAD_CLEANUP_PUSH(A)
+# define ACE_PTHREAD_CLEANUP_POP(A)
+# endif /* ACE_HAS_THR_C_FUNC */
+
+#if !defined (ACE_WIN32)
+// forward decl's
+class ACE_event_t;
+#endif
+
+namespace ACE_OS {
+
+# if 0
+ //@{ @name A set of wrappers for threads (these are portable since they use the ACE_Thread_ID).
+ int thr_continue (const ACE_Thread_ID &thread);
+ int thr_create (ACE_THR_FUNC,
+ void *args,
+ long flags,
+ ACE_Thread_ID *,
+ long priority = ACE_DEFAULT_THREAD_PRIORITY,
+ void *stack = 0,
+ size_t stacksize = 0);
+ int thr_getprio (ACE_Thread_ID thr_id,
+ int &prio,
+ int *policy = 0);
+ int thr_join (ACE_Thread_ID waiter_id,
+ ACE_THR_FUNC_RETURN *status);
+ int thr_kill (ACE_Thread_ID thr_id,
+ int signum);
+ ACE_Thread_ID thr_self (void);
+ int thr_setprio (ACE_Thread_ID thr_id,
+ int prio);
+ int thr_setprio (const ACE_Sched_Priority prio);
+ int thr_suspend (ACE_Thread_ID target_thread);
+ int thr_cancel (ACE_Thread_ID t_id);
+ //@}
+# endif /* 0 */
+
+
+ //@{ @name A set of wrappers for threads
+
+ /// This is necessary to deal with POSIX pthreads and their use of
+ /// structures for thread ids.
+ extern ACE_thread_t NULL_thread;
+
+ /// This is necessary to deal with POSIX pthreads and their use of
+ /// structures for thread handles.
+ extern ACE_hthread_t NULL_hthread;
+
+ /// This is necessary to deal with POSIX pthreads and their use of
+ /// structures for TSS keys.
+ extern ACE_thread_key_t NULL_key;
+
+# if defined (CHORUS)
+ /// This is used to map an actor's id into a KnCap for killing and
+ /// waiting actors.
+ KnCap actorcaps_[ACE_CHORUS_MAX_ACTORS];
+# endif /* CHORUS */
+ //@}
+
+ /**
+ * Call TSS destructors for the current thread. If the current
+ * thread is the main thread, then the argument must be 1.
+ * For private use of ACE_Object_Manager and ACE_Thread_Adapter only.
+ */
+ void cleanup_tss (const u_int main_thread);
+
+ //@{ @name A set of wrappers for condition variables.
+ int condattr_init (ACE_condattr_t &attributes,
+ int type = ACE_DEFAULT_SYNCH_TYPE);
+ int condattr_destroy (ACE_condattr_t &attributes);
+ int cond_broadcast (ACE_cond_t *cv);
+ int cond_destroy (ACE_cond_t *cv);
+ int cond_init (ACE_cond_t *cv,
+ short type = ACE_DEFAULT_SYNCH_TYPE,
+ const char *name = 0,
+ void *arg = 0);
+ int cond_init (ACE_cond_t *cv,
+ ACE_condattr_t &attributes,
+ const char *name = 0,
+ void *arg = 0);
+# if defined (ACE_HAS_WCHAR)
+ int cond_init (ACE_cond_t *cv,
+ short type,
+ const wchar_t *name,
+ void *arg = 0);
+ int cond_init (ACE_cond_t *cv,
+ ACE_condattr_t &attributes,
+ const wchar_t *name,
+ void *arg = 0);
+# endif /* ACE_HAS_WCHAR */
+ int cond_signal (ACE_cond_t *cv);
+ int cond_timedwait (ACE_cond_t *cv,
+ ACE_mutex_t *m,
+ ACE_Time_Value *);
+ int cond_wait (ACE_cond_t *cv,
+ ACE_mutex_t *m);
+# if defined (ACE_WIN32) && defined (ACE_HAS_WTHREADS)
+ int cond_timedwait (ACE_cond_t *cv,
+ ACE_thread_mutex_t *m,
+ ACE_Time_Value *);
+ int cond_wait (ACE_cond_t *cv,
+ ACE_thread_mutex_t *m);
+# endif /* ACE_WIN32 && ACE_HAS_WTHREADS */
+
+ //@{ @name A set of wrappers for auto-reset and manual events.
+
+ int event_destroy (ACE_event_t *event);
+
+ int event_init (ACE_event_t *event,
+ int manual_reset = 0,
+ int initial_state = 0,
+ int type = ACE_DEFAULT_SYNCH_TYPE,
+ const char *name = 0,
+ void *arg = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+# if defined (ACE_HAS_WCHAR)
+ int event_init (ACE_event_t *event,
+ int manual_reset,
+ int initial_state,
+ int type,
+ const wchar_t *name,
+ void *arg = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+# endif /* ACE_HAS_WCHAR */
+
+ int event_pulse (ACE_event_t *event);
+
+ int event_reset (ACE_event_t *event);
+
+ int event_signal (ACE_event_t *event);
+
+ int event_timedwait (ACE_event_t *event,
+ ACE_Time_Value *timeout,
+ int use_absolute_time = 1);
+
+ int event_wait (ACE_event_t *event);
+
+ //@}
+
+ int lwp_getparams (ACE_Sched_Params &);
+
+ int lwp_setparams (const ACE_Sched_Params &);
+
+
+ //@{ @name A set of wrappers for mutex locks.
+
+ int mutex_destroy (ACE_mutex_t *m);
+
+ int mutex_init (ACE_mutex_t *m,
+ int type = ACE_DEFAULT_SYNCH_TYPE,
+ const char *name = 0,
+ ACE_mutexattr_t *arg = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+#if defined (ACE_HAS_WCHAR)
+ int mutex_init (ACE_mutex_t *m,
+ int type,
+ const wchar_t *name,
+ ACE_mutexattr_t *arg = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+#endif /* ACE_HAS_WCHAR */
+
+ /// Win32 note: Abandoned mutexes are not treated differently. 0 is
+ /// returned since the calling thread does get the ownership.
+ int mutex_lock (ACE_mutex_t *m);
+
+ /// This method is only implemented for Win32. For abandoned
+ /// mutexes, <abandoned> is set to 1 and 0 is returned.
+ int mutex_lock (ACE_mutex_t *m,
+ int &abandoned);
+
+ /**
+ * This method attempts to acquire a lock, but gives up if the lock
+ * has not been acquired by the given time. If the lock is not
+ * acquired within the given amount of time, then this method
+ * returns -1 with an <ETIME> errno on platforms that actually
+ * support timed mutexes. The timeout should be an absolute time.
+ * Note that the mutex should not be a recursive one, i.e., it
+ * should only be a standard mutex or an error checking mutex.
+ */
+ int mutex_lock (ACE_mutex_t *m,
+ const ACE_Time_Value &timeout);
+
+ /**
+ * If <timeout> == 0, calls <ACE_OS::mutex_lock(m)>. Otherwise,
+ * this method attempts to acquire a lock, but gives up if the lock
+ * has not been acquired by the given time, in which case it returns
+ * -1 with an <ETIME> errno on platforms that actually support timed
+ * mutexes. The timeout should be an absolute time. Note that the
+ * mutex should not be a recursive one, i.e., it should only be a
+ * standard mutex or an error checking mutex.
+ */
+ int mutex_lock (ACE_mutex_t *m,
+ const ACE_Time_Value *timeout);
+
+ /// Handle asynchronous thread cancellation cleanup.
+ void mutex_lock_cleanup (void *mutex);
+
+ /// Win32 note: Abandoned mutexes are not treated differently. 0 is
+ /// returned since the calling thread does get the ownership.
+ int mutex_trylock (ACE_mutex_t *m);
+
+ /// This method is only implemented for Win32. For abandoned
+ /// mutexes, <abandoned> is set to 1 and 0 is returned.
+ int mutex_trylock (ACE_mutex_t *m,
+ int &abandoned);
+
+ int mutex_unlock (ACE_mutex_t *m);
+
+ //@}
+
+ /// Low-level interface to <priocntl>(2).
+ /**
+ * Can't call the following priocntl, because that's a macro on
+ * Solaris.
+ */
+ int priority_control (ACE_idtype_t, ACE_id_t, int, void *);
+
+ //@{ @name A set of wrappers for recursive mutex locks.
+
+ // These two methods are primarily in support of
+ // ACE_Condition<ACE_Recursive_Thread_Mutex> and should probably not
+ // be called outside that context.
+ int recursive_mutex_cond_unlock (ACE_recursive_thread_mutex_t *m,
+ ACE_recursive_mutex_state &state);
+
+ void recursive_mutex_cond_relock (ACE_recursive_thread_mutex_t *m,
+ ACE_recursive_mutex_state &state);
+
+ int recursive_mutex_destroy (ACE_recursive_thread_mutex_t *m);
+
+ int recursive_mutex_init (ACE_recursive_thread_mutex_t *m,
+ const ACE_TCHAR *name = 0,
+ ACE_mutexattr_t *arg = 0,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+ int recursive_mutex_lock (ACE_recursive_thread_mutex_t *m);
+
+ int recursive_mutex_trylock (ACE_recursive_thread_mutex_t *m);
+
+ int recursive_mutex_unlock (ACE_recursive_thread_mutex_t *m);
+
+ //@}
+
+
+ //@{ @name A set of wrappers for readers/writer locks.
+
+ int rw_rdlock (ACE_rwlock_t *rw);
+
+ int rw_tryrdlock (ACE_rwlock_t *rw);
+
+ int rw_trywrlock (ACE_rwlock_t *rw);
+
+ int rw_trywrlock_upgrade (ACE_rwlock_t *rw);
+
+ int rw_unlock (ACE_rwlock_t *rw);
+
+ int rw_wrlock (ACE_rwlock_t *rw);
+
+ int rwlock_destroy (ACE_rwlock_t *rw);
+
+ int rwlock_init (ACE_rwlock_t *rw,
+ int type = ACE_DEFAULT_SYNCH_TYPE,
+ const ACE_TCHAR *name = 0,
+ void *arg = 0);
+
+ //@}
+
+ //@{ @name Thread scheduler interface.
+ /// Set scheduling parameters. An id of ACE_SELF indicates, e.g.,
+ /// set the parameters on the calling thread.
+ int sched_params (const ACE_Sched_Params &, ACE_id_t id = ACE_SELF);
+ //@}
+
+ /// Find the schedling class ID that corresponds to the class name.
+ int scheduling_class (const char *class_name, ACE_id_t &);
+
+ //@{ @name A set of wrappers for semaphores.
+
+ int sema_destroy (ACE_sema_t *s);
+
+ int sema_init (ACE_sema_t *s,
+ u_int count,
+ int type = ACE_DEFAULT_SYNCH_TYPE,
+ const char *name = 0,
+ void *arg = 0,
+ int max = 0x7fffffff,
+ LPSECURITY_ATTRIBUTES sa = 0);
+
+# if defined (ACE_HAS_WCHAR)
+ int sema_init (ACE_sema_t *s,
+ u_int count,
+ int type,
+ const wchar_t *name,
+ void *arg = 0,
+ int max = 0x7fffffff,
+ LPSECURITY_ATTRIBUTES sa = 0);
+# endif /* ACE_HAS_WCHAR */
+
+ int sema_post (ACE_sema_t *s);
+
+ int sema_post (ACE_sema_t *s,
+ u_int release_count);
+
+ int sema_trywait (ACE_sema_t *s);
+
+ int sema_wait (ACE_sema_t *s);
+
+ int sema_wait (ACE_sema_t *s,
+ ACE_Time_Value &tv);
+
+ int sema_wait (ACE_sema_t *s,
+ ACE_Time_Value *tv);
+
+ //@}
+
+ //@{ @name A set of wrappers for System V semaphores.
+ int semctl (int int_id,
+ int semnum,
+ int cmd,
+ semun);
+ int semget (key_t key,
+ int nsems,
+ int flags);
+ int semop (int int_id,
+ struct sembuf *sops,
+ size_t nsops);
+ //@}
+
+ /// Friendly interface to <priocntl>(2).
+ int set_scheduling_params (const ACE_Sched_Params &,
+ ACE_id_t id = ACE_SELF);
+
+ int sigtimedwait (const sigset_t *set,
+ siginfo_t *info,
+ const ACE_Time_Value *timeout);
+
+ int sigwait (sigset_t *set,
+ int *sig = 0);
+
+ int sigwaitinfo (const sigset_t *set,
+ siginfo_t *info);
+
+ int thr_cancel (ACE_thread_t t_id);
+
+ int thr_cmp (ACE_hthread_t t1,
+ ACE_hthread_t t2);
+ // These are non-portable since they use ACE_thread_t and
+ // ACE_hthread_t and will go away in a future release.
+ int thr_continue (ACE_hthread_t target_thread);
+
+ /*
+ * Creates a new thread having <flags> attributes and running <func>
+ * with <args> (if <thread_adapter> is non-0 then <func> and <args>
+ * are ignored and are obtained from <thread_adapter>). <thr_id>
+ * and <t_handle> are set to the thread's ID and handle (?),
+ * respectively. The thread runs at <priority> priority (see
+ * below).
+ *
+ * The <flags> are a bitwise-OR of the following:
+ * = BEGIN<INDENT>
+ * THR_CANCEL_DISABLE, THR_CANCEL_ENABLE, THR_CANCEL_DEFERRED,
+ * THR_CANCEL_ASYNCHRONOUS, THR_BOUND, THR_NEW_LWP, THR_DETACHED,
+ * THR_SUSPENDED, THR_DAEMON, THR_JOINABLE, THR_SCHED_FIFO,
+ * THR_SCHED_RR, THR_SCHED_DEFAULT, THR_EXPLICIT_SCHED,
+ * THR_SCOPE_SYSTEM, THR_SCOPE_PROCESS
+ * = END<INDENT>
+ *
+ * By default, or if <priority> is set to
+ * ACE_DEFAULT_THREAD_PRIORITY, an "appropriate" priority value for
+ * the given scheduling policy (specified in <flags}>, e.g.,
+ * <THR_SCHED_DEFAULT>) is used. This value is calculated
+ * dynamically, and is the median value between the minimum and
+ * maximum priority values for the given policy. If an explicit
+ * value is given, it is used. Note that actual priority values are
+ * EXTREMEMLY implementation-dependent, and are probably best
+ * avoided.
+ *
+ * Note that <thread_adapter> is always deleted by <thr_create>,
+ * therefore it must be allocated with global operator new.
+ */
+ int thr_create (ACE_THR_FUNC func,
+ void *args,
+ long flags,
+ ACE_thread_t *thr_id,
+ ACE_hthread_t *t_handle = 0,
+ long priority = ACE_DEFAULT_THREAD_PRIORITY,
+ void *stack = 0,
+ size_t stacksize = 0,
+ ACE_Base_Thread_Adapter *thread_adapter = 0);
+
+ int thr_equal (ACE_thread_t t1,
+ ACE_thread_t t2);
+
+ void thr_exit (ACE_THR_FUNC_RETURN status = 0);
+
+ int thr_getconcurrency (void);
+
+ int thr_getprio (ACE_hthread_t id,
+ int &priority);
+
+ int thr_getprio (ACE_hthread_t id,
+ int &priority,
+ int &policy);
+
+# if defined (ACE_HAS_TSS_EMULATION) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ int thr_getspecific (ACE_OS_thread_key_t key,
+ void **data);
+# endif /* ACE_HAS_TSS_EMULATION && ACE_HAS_THREAD_SPECIFIC_STORAGE */
+
+ int thr_getspecific (ACE_thread_key_t key,
+ void **data);
+
+ int thr_join (ACE_hthread_t waiter_id,
+ ACE_THR_FUNC_RETURN *status);
+
+ int thr_join (ACE_thread_t waiter_id,
+ ACE_thread_t *thr_id,
+ ACE_THR_FUNC_RETURN *status);
+
+ int thr_key_detach (void *inst);
+
+ int thr_key_used (ACE_thread_key_t key);
+
+# if defined (ACE_HAS_THR_C_DEST)
+# if defined (ACE_HAS_TSS_EMULATION) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ int thr_keycreate (ACE_OS_thread_key_t *key,
+ ACE_THR_C_DEST,
+ void *inst = 0);
+# endif /* ACE_HAS_TSS_EMULATION && ACE_HAS_THREAD_SPECIFIC_STORAGE */
+ int thr_keycreate (ACE_thread_key_t *key,
+ ACE_THR_C_DEST,
+ void *inst = 0);
+# else
+# if defined (ACE_HAS_TSS_EMULATION) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ int thr_keycreate (ACE_OS_thread_key_t *key,
+ ACE_THR_DEST,
+ void *inst = 0);
+# endif /* ACE_HAS_TSS_EMULATION && ACE_HAS_THREAD_SPECIFIC_STORAGE */
+ int thr_keycreate (ACE_thread_key_t *key,
+ ACE_THR_DEST,
+ void *inst = 0);
+# endif /* ACE_HAS_THR_C_DEST */
+
+ int thr_keyfree (ACE_thread_key_t key);
+
+ int thr_kill (ACE_thread_t thr_id,
+ int signum);
+
+ size_t thr_min_stack (void);
+
+ ACE_thread_t thr_self (void);
+
+ void thr_self (ACE_hthread_t &);
+
+ int thr_setcancelstate (int new_state,
+ int *old_state);
+
+ int thr_setcanceltype (int new_type,
+ int *old_type);
+
+ int thr_setconcurrency (int hint);
+
+ int thr_setprio (ACE_hthread_t id,
+ int priority,
+ int policy = -1);
+
+ int thr_setprio (const ACE_Sched_Priority prio);
+
+# if defined (ACE_HAS_TSS_EMULATION) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
+ int thr_setspecific (ACE_OS_thread_key_t key,
+ void *data);
+# endif /* ACE_HAS_TSS_EMULATION && ACE_HAS_THREAD_SPECIFIC_STORAGE */
+
+ int thr_setspecific (ACE_thread_key_t key,
+ void *data);
+
+ int thr_sigsetmask (int how,
+ const sigset_t *nsm,
+ sigset_t *osm);
+
+ int thr_suspend (ACE_hthread_t target_thread);
+
+ void thr_testcancel (void);
+
+ void thr_yield (void);
+
+ //@{ @name A set of wrappers for mutex locks that only work within a single process.
+
+ int thread_mutex_destroy (ACE_thread_mutex_t *m);
+
+ int thread_mutex_init (ACE_thread_mutex_t *m,
+ int type = ACE_DEFAULT_SYNCH_TYPE,
+ const char *name = 0,
+ ACE_mutexattr_t *arg = 0);
+
+#if defined (ACE_HAS_WCHAR)
+ int thread_mutex_init (ACE_thread_mutex_t *m,
+ int type,
+ const wchar_t *name,
+ ACE_mutexattr_t *arg = 0);
+#endif /* ACE_HAS_WCHAR */
+
+ int thread_mutex_lock (ACE_thread_mutex_t *m);
+
+ int thread_mutex_lock (ACE_thread_mutex_t *m,
+ const ACE_Time_Value &timeout);
+
+ int thread_mutex_lock (ACE_thread_mutex_t *m,
+ const ACE_Time_Value *timeout);
+
+ int thread_mutex_trylock (ACE_thread_mutex_t *m);
+
+ int thread_mutex_unlock (ACE_thread_mutex_t *m);
+
+ //@}
+
+ /**
+ * This method uses process id and object pointer to come up with a
+ * machine wide unique name. The process ID will provide uniqueness
+ * between processes on the same machine. The "this" pointer of the
+ * <object> will provide uniqueness between other "live" objects in
+ * the same process. The uniqueness of this name is therefore only
+ * valid for the life of <object>.
+ */
+ void unique_name (const void *object,
+ ACE_TCHAR *name,
+ size_t length);
+
+ //@}
+
+} /* namespace ACE_OS */
+
+#if !defined (ACE_WIN32)
+/**
+ * @class ACE_event_t
+ *
+ * @brief Wrapper for NT events on UNIX.
+ */
+class ACE_OS_Export ACE_event_t
+{
+ friend int ACE_OS::event_init(ACE_event_t*, int, int, int, const char*, void*,int);
+ friend int ACE_OS::event_destroy(ACE_event_t*);
+ friend int ACE_OS::event_wait(ACE_event_t*);
+ friend int ACE_OS::event_timedwait(ACE_event_t*, ACE_Time_Value*, int);
+ friend int ACE_OS::event_signal(ACE_event_t*);
+ friend int ACE_OS::event_pulse(ACE_event_t*);
+ friend int ACE_OS::event_reset(ACE_event_t*);
+protected:
+
+ /// Protect critical section.
+ ACE_mutex_t lock_;
+
+ /// Keeps track of waiters.
+ ACE_cond_t condition_;
+
+ /// Specifies if this is an auto- or manual-reset event.
+ int manual_reset_;
+
+ /// "True" if signaled.
+ int is_signaled_;
+
+ /// Number of waiting threads.
+ unsigned long waiting_threads_;
+};
+#endif /* ACE_WIN32 */
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+
+/**
+ * @class ACE_OS_Thread_Mutex_Guard
+ *
+ * This data structure is meant to be used within an ACE_OS
+ * function. It performs automatic aquisition and release of
+ * an ACE_thread_mutex_t.
+ *
+ * For internal use only by ACE_OS.
+ */
+class ACE_OS_Thread_Mutex_Guard
+{
+public:
+ /// Implicitly and automatically acquire the lock.
+ ACE_OS_Thread_Mutex_Guard (ACE_thread_mutex_t &m);
+
+ /// Implicitly release the lock.
+ ~ACE_OS_Thread_Mutex_Guard (void);
+
+ /// Explicitly acquire the lock.
+ int acquire (void);
+
+ /// Explicitly release the lock.
+ int release (void);
+
+protected:
+ /// Reference to the mutex.
+ ACE_thread_mutex_t &lock_;
+
+ /// Keeps track of whether we acquired the lock or failed.
+ int owner_;
+
+ // = Prevent assignment and initialization.
+ ACE_OS_Thread_Mutex_Guard &operator= (const ACE_OS_Thread_Mutex_Guard &);
+ ACE_OS_Thread_Mutex_Guard (const ACE_OS_Thread_Mutex_Guard &);
+};
+
+/**
+ * @class ACE_OS_Recursive_Thread_Mutex_Guard
+ *
+ * @brief For internal use only by ACE_OS.
+ *
+ * This data structure is meant to be used within an ACE_OS
+ * function. It performs automatic aquisition and release of
+ * an ACE_recursive_thread_mutex_t.
+ */
+class ACE_OS_Recursive_Thread_Mutex_Guard
+{
+public:
+ /// Implicitly and automatically acquire the lock.
+ ACE_OS_Recursive_Thread_Mutex_Guard (ACE_recursive_thread_mutex_t &m);
+
+ /// Implicitly release the lock.
+ ~ACE_OS_Recursive_Thread_Mutex_Guard (void);
+
+ /// Explicitly acquire the lock.
+ int acquire (void);
+
+ /// Explicitly release the lock.
+ int release (void);
+
+protected:
+ /// Reference to the mutex.
+ ACE_recursive_thread_mutex_t &lock_;
+
+ /// Keeps track of whether we acquired the lock or failed.
+ int owner_;
+
+ // = Prevent assignment and initialization.
+ ACE_OS_Recursive_Thread_Mutex_Guard &operator= (
+ const ACE_OS_Recursive_Thread_Mutex_Guard &);
+ ACE_OS_Recursive_Thread_Mutex_Guard (
+ const ACE_OS_Recursive_Thread_Mutex_Guard &);
+};
+
+// used in time and unistd
+# define ACE_OS_GUARD \
+ ACE_OS_Thread_Mutex_Guard ace_os_guard__ (*(ACE_thread_mutex_t *) \
+ ACE_OS_Object_Manager::preallocated_object[ \
+ ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]);
+
+// used in Thread
+# define ACE_TSS_CLEANUP_GUARD \
+ ACE_OS_Recursive_Thread_Mutex_Guard ace_tss_cleanup_guard__ (*(ACE_recursive_thread_mutex_t *) \
+ ACE_OS_Object_Manager::preallocated_object[ \
+ ACE_OS_Object_Manager::ACE_TSS_CLEANUP_LOCK]);
+
+// used in Thread
+# define ACE_TSS_BASE_GUARD \
+ ACE_OS_Recursive_Thread_Mutex_Guard ace_tss_base_guard__ (*(ACE_recursive_thread_mutex_t *) \
+ ACE_OS_Object_Manager::preallocated_object[ \
+ ACE_OS_Object_Manager::ACE_TSS_BASE_LOCK]);
+
+#else /* ! ACE_MT_SAFE */
+# define ACE_OS_GUARD
+# define ACE_TSS_CLEANUP_GUARD
+# define ACE_TSS_BASE_GUARD
+#endif /* ! ACE_MT_SAFE */
+
+# if defined (ACE_HAS_INLINED_OSCALLS)
+# if defined (ACE_INLINE)
+# undef ACE_INLINE
+# endif /* ACE_INLINE */
+# define ACE_INLINE inline
+# include "ace/OS_NS_Thread.inl"
+# endif /* ACE_HAS_INLINED_OSCALLS */
+
+# include /**/ "ace/post.h"
+#endif /* ACE_OS_NS_THREAD_H */