diff options
Diffstat (limited to 'ACE/ace/OS_NS_Thread.h')
-rw-r--r-- | ACE/ace/OS_NS_Thread.h | 2034 |
1 files changed, 2034 insertions, 0 deletions
diff --git a/ACE/ace/OS_NS_Thread.h b/ACE/ace/OS_NS_Thread.h new file mode 100644 index 00000000000..c9f6c261a87 --- /dev/null +++ b/ACE/ace/OS_NS_Thread.h @@ -0,0 +1,2034 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @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/os_include/os_sched.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" +# include "ace/ACE_export.h" +# include "ace/Object_Manager_Base.h" + +# if defined (ACE_EXPORT_MACRO) +# undef ACE_EXPORT_MACRO +# endif +# define ACE_EXPORT_MACRO ACE_Export + +# 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 */ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +# if defined (ACE_WIN32) +typedef DWORD ACE_thread_t; +typedef HANDLE ACE_hthread_t; +// Native TSS key type +typedef DWORD ACE_OS_thread_key_t; +// Application TSS key type (use this type except in TSS Emulation) +# if defined (ACE_HAS_TSS_EMULATION) + typedef u_int ACE_thread_key_t; +# else /* ! ACE_HAS_TSS_EMULATION */ + typedef ACE_OS_thread_key_t ACE_thread_key_t; +# endif /* ! ACE_HAS_TSS_EMULATION */ +# endif /* ACE_WIN32 */ + +ACE_END_VERSIONED_NAMESPACE_DECL + +# if !defined (ACE_HAS_POSIX_SEM) && defined (ACE_USES_FIFO_SEM) + +extern "C" { + typedef struct + { + char* name_; + ACE_HANDLE fd_[2]; + } ACE_sema_t; +} + +#endif /* !ACE_HAS_POSIX_SEM && ACE_USES_FIFO_SEM */ + +# 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) + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +// Solaris threads, without PTHREADS. +// Typedefs to help compatibility with Windows NT and Pthreads. +typedef thread_t ACE_thread_t; +// Native TSS key type (not for general use) +typedef thread_key_t ACE_OS_thread_key_t; +// Application TSS key type (use this type except in TSS Emulation) +# if defined (ACE_HAS_TSS_EMULATION) + typedef u_int ACE_thread_key_t; +# else /* ! ACE_HAS_TSS_EMULATION */ + typedef ACE_OS_thread_key_t ACE_thread_key_t; +# endif /* ! ACE_HAS_TSS_EMULATION */ +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) && !defined (ACE_USES_FIFO_SEM) +typedef sema_t ACE_sema_t; +# endif /* !ACE_HAS_POSIX_SEM */ + +typedef cond_t ACE_cond_t; +struct ACE_Export ACE_condattr_t +{ + int type; +}; +struct ACE_Export ACE_mutexattr_t +{ + int type; +}; +typedef ACE_thread_t ACE_hthread_t; +typedef ACE_mutex_t ACE_thread_mutex_t; + +ACE_END_VERSIONED_NAMESPACE_DECL + +# 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 +# define THR_INHERIT_SCHED 0 +# define THR_SCOPE_PROCESS 0 + +# elif defined (ACE_VXWORKS) +# include /**/ <sysLib.h> // for sysClkRateGet() +# if !defined (__RTP__) +# include /**/ <taskLib.h> +# include /**/ <taskHookLib.h> +# endif + +// 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 */ +# if !defined (VX_FP_TASK) +# define VX_FP_TASK 0x0008 /* floating point coprocessor */ +# endif +# 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). */ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +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.) +// Native TSS key type +typedef u_int ACE_OS_thread_key_t; +// Application TSS key type (use this type except in TSS Emulation) +# if defined (ACE_HAS_TSS_EMULATION) + typedef u_int ACE_thread_key_t; +# else /* ! ACE_HAS_TSS_EMULATION */ + typedef ACE_OS_thread_key_t ACE_thread_key_t; +# endif /* ! ACE_HAS_TSS_EMULATION */ + +ACE_END_VERSIONED_NAMESPACE_DECL + + // 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) + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +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_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) */ + +ACE_END_VERSIONED_NAMESPACE_DECL + +// 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_INHERIT_SCHED 0 +# define THR_EXPLICIT_SCHED 0 +# define THR_SCOPE_PROCESS 0 +# define THR_SCOPE_SYSTEM 0 +# endif /* ACE_HAS_PTHREADS / STHREADS / 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) + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class ACE_cond_t + * + * @brief This structure is used to implement condition variables on + * platforms that lack it natively, such as VxWorks, and Win32. + * + * At the current time, this stuff only works for threads + * within the same process. + */ +class ACE_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 (ACE_VXWORKS) + /** + * 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 /* ACE_VXWORKS */ + + /// Keeps track of whether we were broadcasting or just signaling. + size_t was_broadcast_; +}; + +struct ACE_Export ACE_condattr_t +{ + int type; +}; + +struct ACE_Export ACE_mutexattr_t +{ + int type; +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + +# endif /* ACE_LACKS_COND_T */ + +# if defined (ACE_LACKS_RWLOCK_T) && !defined (ACE_HAS_PTHREADS_UNIX98_EXT) + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @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_Export ACE_rwlock_t +{ +public: +//protected: + + /// Serialize access to internal state. + ACE_mutex_t lock_; + + /// Reader threads waiting to acquire the lock. + ACE_cond_t waiting_readers_; + + /// Number of waiting readers. + int num_waiting_readers_; + + /// Writer threads waiting to acquire the lock. + ACE_cond_t waiting_writers_; + + /// Number of waiting writers. + int num_waiting_writers_; + + /// Value is -1 if writer has the lock, else this keeps track of the + /// number of readers holding the lock. + int ref_count_; + + /// Indicate that a reader is trying to upgrade + int important_writer_; + + /// Condition for the upgrading reader + ACE_cond_t waiting_important_writer_; +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + +# elif defined (ACE_HAS_PTHREADS_UNIX98_EXT) +ACE_BEGIN_VERSIONED_NAMESPACE_DECL +typedef pthread_rwlock_t ACE_rwlock_t; +ACE_END_VERSIONED_NAMESPACE_DECL +# elif defined (ACE_HAS_STHREADS) +# include /**/ <synch.h> +ACE_BEGIN_VERSIONED_NAMESPACE_DECL +typedef rwlock_t ACE_rwlock_t; +ACE_END_VERSIONED_NAMESPACE_DECL +# 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) + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +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 */ + +ACE_END_VERSIONED_NAMESPACE_DECL + +# else + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @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_; +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + +# 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 (THR_INHERIT_SCHED) +# define THR_INHERIT_SCHED 0 +# endif /* ! THR_INHERIT_SCHED */ +# 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 */ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +// These are dummies needed for class OS.h +typedef int ACE_cond_t; +struct ACE_Export ACE_condattr_t +{ + int type; +}; +struct ACE_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_USES_FIFO_SEM) +typedef int ACE_sema_t; +# endif /* !ACE_HAS_POSIX_SEM && !ACE_USES_FIFO_SEM */ +typedef int ACE_rwlock_t; +typedef int ACE_thread_t; +typedef int ACE_hthread_t; +// Native TSS key type +typedef unsigned int ACE_OS_thread_key_t; +// Application TSS key type (use this type except in TSS Emulation) +# if defined (ACE_HAS_TSS_EMULATION) + typedef u_int ACE_thread_key_t; +# else /* ! ACE_HAS_TSS_EMULATION */ + typedef ACE_OS_thread_key_t ACE_thread_key_t; +# endif /* ! ACE_HAS_TSS_EMULATION */ + +ACE_END_VERSIONED_NAMESPACE_DECL + +// 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 ***********************************************/ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class ACE_Thread_ID + * + * @brief Defines a platform-independent thread ID class. Note that + * this class should be defined within the scope of a thread, rather + * than at global scope! + */ +class ACE_Export ACE_Thread_ID +{ +public: + /// Initialize the object using the thread id and thread handle + /// passed as parameters. + ACE_Thread_ID (ACE_thread_t thr_id, + ACE_hthread_t thr_handle); + + /// Initialize the object using calls to ACE_OS::thr_self(). + ACE_Thread_ID (void); + + /// Copy constructor. + ACE_Thread_ID (const ACE_Thread_ID &rhs); + + /// Get the thread id. + ACE_thread_t id (void) const; + + /// Set the thread id. + void id (ACE_thread_t); + + /// Get the thread handle. + ACE_hthread_t handle (void) const; + + /// Set the thread handle. + void handle (ACE_hthread_t); + + // Create a string representation of the thread id. + void to_string (char *thr_string) const; + + /// Equality operator. + bool operator== (const ACE_Thread_ID &) const; + + /// Inequality operator. + bool 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 (ACE_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 /* ACE_VXWORKS */ +#endif /* ! ACE_DEFAULT_SYNCH_TYPE */ + +// forward declaration +class ACE_Sched_Params; +class ACE_Time_Value; + +#if 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) */ +# 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) */ + +# 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_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); + + /// Check a key for validity. + static int is_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. + /// or not. + // Static construction in VxWorks 5.4 and later is slightly broken. + // If the static object is more complex than an integral type, static + // construction will occur twice. The tss_keys_used_ object is + // statically constructed and then modified by ACE_Log_Msg::instance() + // when two keys are created and TSS data is stored. However, at + // the end of static construction the tss_keys_used_ object is again + // initialized and therefore it will appear to next_key() that no + // TSS keys have been handed out. That is all true unless the + // tss_keys_used object is a static pointer instead of a static object. + 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 */ + // allow user to define its own ACE_DEFAULT_THREAD_KEYS in Windows, + // where The MSSDK defines only 64 entries +# if defined (TLS_MINIMUM_AVAILABLE) && !defined (ACE_DEFAULT_THREAD_KEYS) + // 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) +/** + * @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. + bool operator== (const ACE_TSS_Ref &) const; + + /// Check for inequality. + bool 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: + /// Declare pointer to function to destroy tss object. + typedef void (*Destructor)(void *); + + /// Constructor + ACE_TSS_Info (ACE_thread_key_t key, + Destructor dest = 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. + bool operator== (const ACE_TSS_Info &) const; + + /// Check for inequality. + bool 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. + Destructor destructor_; + + /// 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 */ + +ACE_END_VERSIONED_NAMESPACE_DECL + +#if (defined (ACE_HAS_VERSIONED_NAMESPACE) && ACE_HAS_VERSIONED_NAMESPACE == 1) +# define ACE_MUTEX_LOCK_CLEANUP_ADAPTER_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ace_mutex_lock_cleanup_adapter) +#endif /* ACE_HAS_VERSIONED_NAMESPACE == 1 */ + + +# if defined (ACE_HAS_THR_C_FUNC) +// This is necessary to work around nasty problems with MVS C++. +extern "C" ACE_Export void ACE_MUTEX_LOCK_CLEANUP_ADAPTER_NAME (void *args); +# define ACE_PTHREAD_CLEANUP_PUSH(A) pthread_cleanup_push (ACE_MUTEX_LOCK_CLEANUP_ADAPTER_NAME, (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_Export void ACE_MUTEX_LOCK_CLEANUP_ADAPTER_NAME (void *args); +# define ACE_PTHREAD_CLEANUP_PUSH(A) pthread_cleanup_push (ACE_MUTEX_LOCK_CLEANUP_ADAPTER_NAME, (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 */ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +# if !defined (ACE_WIN32) +// forward decl's +class ACE_event_t; +# endif + +class ACE_Base_Thread_Adapter; + +namespace ACE_OS { + //@{ @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_Export ACE_thread_t NULL_thread; + + /// This is necessary to deal with POSIX pthreads and their use of + /// structures for thread handles. + extern ACE_Export ACE_hthread_t NULL_hthread; + + /// This is necessary to deal with POSIX pthreads and their use of + /// structures for TSS keys. + extern ACE_Export ACE_thread_key_t NULL_key; + //@} + + /** + * 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. + */ + extern ACE_Export + void cleanup_tss (const u_int main_thread); + + //@{ @name A set of wrappers for condition variables. +#if defined (ACE_LACKS_COND_T) + extern ACE_Export +#else + ACE_NAMESPACE_INLINE_FUNCTION +#endif /* ACE_LACKS_COND_T */ + int condattr_init (ACE_condattr_t &attributes, + int type = ACE_DEFAULT_SYNCH_TYPE); + +#if defined (ACE_LACKS_COND_T) + extern ACE_Export +#else + ACE_NAMESPACE_INLINE_FUNCTION +#endif /* ACE_LACKS_COND_T */ + int condattr_destroy (ACE_condattr_t &attributes); + +#if defined (ACE_LACKS_COND_T) + extern ACE_Export +#else + ACE_NAMESPACE_INLINE_FUNCTION +#endif /* ACE_LACKS_COND_T */ + int cond_broadcast (ACE_cond_t *cv); + +#if defined (ACE_LACKS_COND_T) + extern ACE_Export +#else + ACE_NAMESPACE_INLINE_FUNCTION +#endif /* ACE_LACKS_COND_T */ + int cond_destroy (ACE_cond_t *cv); + + extern ACE_Export + int cond_init (ACE_cond_t *cv, + short type = ACE_DEFAULT_SYNCH_TYPE, + const char *name = 0, + void *arg = 0); + +#if defined (ACE_LACKS_COND_T) + extern ACE_Export +#else + ACE_NAMESPACE_INLINE_FUNCTION +#endif /* ACE_LACKS_COND_T */ + int cond_init (ACE_cond_t *cv, + ACE_condattr_t &attributes, + const char *name = 0, + void *arg = 0); + +# if defined (ACE_HAS_WCHAR) +# if defined (ACE_LACKS_COND_T) + extern ACE_Export +# else + ACE_NAMESPACE_INLINE_FUNCTION +# endif /* ACE_LACKS_COND_T */ + int cond_init (ACE_cond_t *cv, + short type, + const wchar_t *name, + void *arg = 0); + +# if defined (ACE_LACKS_COND_T) + extern ACE_Export +# else + ACE_NAMESPACE_INLINE_FUNCTION +# endif /* ACE_LACKS_COND_T */ + int cond_init (ACE_cond_t *cv, + ACE_condattr_t &attributes, + const wchar_t *name, + void *arg = 0); +# endif /* ACE_HAS_WCHAR */ + +#if defined (ACE_LACKS_COND_T) + extern ACE_Export +#else + ACE_NAMESPACE_INLINE_FUNCTION +#endif /* ACE_LACKS_COND_T */ + int cond_signal (ACE_cond_t *cv); + +#if defined (ACE_LACKS_COND_T) + extern ACE_Export +#else + ACE_NAMESPACE_INLINE_FUNCTION +#endif /* ACE_LACKS_COND_T */ + int cond_timedwait (ACE_cond_t *cv, + ACE_mutex_t *m, + ACE_Time_Value *); + +#if defined (ACE_LACKS_COND_T) + extern ACE_Export +#else + ACE_NAMESPACE_INLINE_FUNCTION +#endif /* ACE_LACKS_COND_T */ + int cond_wait (ACE_cond_t *cv, + ACE_mutex_t *m); + +# if defined (ACE_WIN32) && defined (ACE_HAS_WTHREADS) +# if defined (ACE_LACKS_COND_T) + extern ACE_Export +# else + ACE_NAMESPACE_INLINE_FUNCTION +# endif /* ACE_LACKS_COND_T */ + int cond_timedwait (ACE_cond_t *cv, + ACE_thread_mutex_t *m, + ACE_Time_Value *); + +# if defined (ACE_LACKS_COND_T) + extern ACE_Export +# else + ACE_NAMESPACE_INLINE_FUNCTION +# endif /* ACE_LACKS_COND_T */ + 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. + + extern ACE_Export + int event_destroy (ACE_event_t *event); + + extern ACE_Export + 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) + ACE_NAMESPACE_INLINE_FUNCTION + 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 */ + + extern ACE_Export + int event_pulse (ACE_event_t *event); + + extern ACE_Export + int event_reset (ACE_event_t *event); + + extern ACE_Export + int event_signal (ACE_event_t *event); + + extern ACE_Export + int event_timedwait (ACE_event_t *event, + ACE_Time_Value *timeout, + int use_absolute_time = 1); + + extern ACE_Export + int event_wait (ACE_event_t *event); + + //@} + + extern ACE_Export + int lwp_getparams (ACE_Sched_Params &); + + extern ACE_Export + int lwp_setparams (const ACE_Sched_Params &); + + + //@{ @name A set of wrappers for mutex locks. + + extern ACE_Export + int mutex_destroy (ACE_mutex_t *m); + + extern ACE_Export + int mutex_init (ACE_mutex_t *m, + int lock_scope = ACE_DEFAULT_SYNCH_TYPE, + const char *name = 0, + ACE_mutexattr_t *arg = 0, + LPSECURITY_ATTRIBUTES sa = 0, + int lock_type = 0); + +#if defined (ACE_HAS_WCHAR) + extern ACE_Export + int mutex_init (ACE_mutex_t *m, + int lock_scope, + const wchar_t *name, + ACE_mutexattr_t *arg = 0, + LPSECURITY_ATTRIBUTES sa = 0, + int lock_type = 0); +#endif /* ACE_HAS_WCHAR */ + + /// Win32 note: Abandoned mutexes are not treated differently. 0 is + /// returned since the calling thread does get the ownership. + extern ACE_Export + int mutex_lock (ACE_mutex_t *m); + + /// This method is only implemented for Win32. For abandoned + /// mutexes, @a abandoned is set to 1 and 0 is returned. + extern ACE_Export + 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 @c 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 since + * some implementations of this method don't support recursive + * mutexes. If you want to use a recursive mutex see the methods + * below. + */ + extern ACE_Export + 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 since some + * implementations of this method don't support recursive mutexes. + * If you want to use a recursive mutex see the methods below. + */ + ACE_NAMESPACE_INLINE_FUNCTION + int mutex_lock (ACE_mutex_t *m, + const ACE_Time_Value *timeout); + + /// Handle asynchronous thread cancellation cleanup. + extern ACE_Export + 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. + extern ACE_Export + 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. + extern ACE_Export + int mutex_trylock (ACE_mutex_t *m, + int &abandoned); + + extern ACE_Export + 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. + */ + ACE_NAMESPACE_INLINE_FUNCTION + long 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. + ACE_NAMESPACE_INLINE_FUNCTION + int recursive_mutex_cond_unlock (ACE_recursive_thread_mutex_t *m, + ACE_recursive_mutex_state &state); + + ACE_NAMESPACE_INLINE_FUNCTION + void recursive_mutex_cond_relock (ACE_recursive_thread_mutex_t *m, + ACE_recursive_mutex_state &state); + + ACE_NAMESPACE_INLINE_FUNCTION + int recursive_mutex_destroy (ACE_recursive_thread_mutex_t *m); + + ACE_NAMESPACE_INLINE_FUNCTION + int recursive_mutex_init (ACE_recursive_thread_mutex_t *m, + const ACE_TCHAR *name = 0, + ACE_mutexattr_t *arg = 0, + LPSECURITY_ATTRIBUTES sa = 0); + + ACE_NAMESPACE_INLINE_FUNCTION + int recursive_mutex_lock (ACE_recursive_thread_mutex_t *m); + + ACE_NAMESPACE_INLINE_FUNCTION + int recursive_mutex_lock (ACE_recursive_thread_mutex_t *m, + const ACE_Time_Value &timeout); + + ACE_NAMESPACE_INLINE_FUNCTION + int recursive_mutex_lock (ACE_recursive_thread_mutex_t *m, + const ACE_Time_Value *timeout); + + ACE_NAMESPACE_INLINE_FUNCTION + int recursive_mutex_trylock (ACE_recursive_thread_mutex_t *m); + + ACE_NAMESPACE_INLINE_FUNCTION + int recursive_mutex_unlock (ACE_recursive_thread_mutex_t *m); + + //@} + + + //@{ @name A set of wrappers for readers/writer locks. + + ACE_NAMESPACE_INLINE_FUNCTION + int rw_rdlock (ACE_rwlock_t *rw); + + ACE_NAMESPACE_INLINE_FUNCTION + int rw_tryrdlock (ACE_rwlock_t *rw); + + ACE_NAMESPACE_INLINE_FUNCTION + int rw_trywrlock (ACE_rwlock_t *rw); + + ACE_NAMESPACE_INLINE_FUNCTION + int rw_trywrlock_upgrade (ACE_rwlock_t *rw); + + ACE_NAMESPACE_INLINE_FUNCTION + int rw_unlock (ACE_rwlock_t *rw); + + ACE_NAMESPACE_INLINE_FUNCTION + int rw_wrlock (ACE_rwlock_t *rw); + + ACE_NAMESPACE_INLINE_FUNCTION + int rwlock_destroy (ACE_rwlock_t *rw); + + extern ACE_Export + 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. + extern ACE_Export + int sched_params (const ACE_Sched_Params &, ACE_id_t id = ACE_SELF); + //@} + + /// Find the schedling class ID that corresponds to the class name. + extern ACE_Export + int scheduling_class (const char *class_name, ACE_id_t &); + + //@{ @name A set of wrappers for semaphores. + + ACE_NAMESPACE_INLINE_FUNCTION + int sema_destroy (ACE_sema_t *s); + + ACE_NAMESPACE_INLINE_FUNCTION + 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) + ACE_NAMESPACE_INLINE_FUNCTION + 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 */ + + ACE_NAMESPACE_INLINE_FUNCTION + int sema_post (ACE_sema_t *s); + + ACE_NAMESPACE_INLINE_FUNCTION + int sema_post (ACE_sema_t *s, + u_int release_count); + + ACE_NAMESPACE_INLINE_FUNCTION + int sema_trywait (ACE_sema_t *s); + + ACE_NAMESPACE_INLINE_FUNCTION + int sema_wait (ACE_sema_t *s); + + ACE_NAMESPACE_INLINE_FUNCTION + int sema_wait (ACE_sema_t *s, + ACE_Time_Value &tv); + + ACE_NAMESPACE_INLINE_FUNCTION + int sema_wait (ACE_sema_t *s, + ACE_Time_Value *tv); + + //@} + + //@{ @name A set of wrappers for System V semaphores. + ACE_NAMESPACE_INLINE_FUNCTION + int semctl (int int_id, + int semnum, + int cmd, + semun); + + ACE_NAMESPACE_INLINE_FUNCTION + int semget (key_t key, + int nsems, + int flags); + + ACE_NAMESPACE_INLINE_FUNCTION + int semop (int int_id, + struct sembuf *sops, + size_t nsops); + //@} + + /// Friendly interface to <priocntl>(2). + extern ACE_Export + int set_scheduling_params (const ACE_Sched_Params &, + ACE_id_t id = ACE_SELF); + + ACE_NAMESPACE_INLINE_FUNCTION + int sigtimedwait (const sigset_t *set, + siginfo_t *info, + const ACE_Time_Value *timeout); + + ACE_NAMESPACE_INLINE_FUNCTION + int sigwait (sigset_t *set, + int *sig = 0); + + ACE_NAMESPACE_INLINE_FUNCTION + int sigwaitinfo (const sigset_t *set, + siginfo_t *info); + + ACE_NAMESPACE_INLINE_FUNCTION + int thr_cancel (ACE_thread_t t_id); + + ACE_NAMESPACE_INLINE_FUNCTION + 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. + ACE_NAMESPACE_INLINE_FUNCTION + 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. + */ + extern ACE_Export + 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); + + ACE_NAMESPACE_INLINE_FUNCTION + int thr_equal (ACE_thread_t t1, + ACE_thread_t t2); + + extern ACE_Export + void thr_exit (ACE_THR_FUNC_RETURN status = 0); + + ACE_NAMESPACE_INLINE_FUNCTION + int thr_getconcurrency (void); + + ACE_NAMESPACE_INLINE_FUNCTION + int thr_getprio (ACE_hthread_t id, + int &priority); + + ACE_NAMESPACE_INLINE_FUNCTION + int thr_getprio (ACE_hthread_t id, + int &priority, + int &policy); + +# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + ACE_NAMESPACE_INLINE_FUNCTION + /// for internal use only. Applications should call thr_getspecific + int thr_getspecific_native (ACE_OS_thread_key_t key, + void **data); +# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ + + ACE_NAMESPACE_INLINE_FUNCTION + int thr_getspecific (ACE_thread_key_t key, + void **data); + +#if defined (ACE_VXWORKS) + extern ACE_Export +#else + ACE_NAMESPACE_INLINE_FUNCTION +#endif /* ACE_VXWORKS */ + int thr_join (ACE_hthread_t waiter_id, + ACE_THR_FUNC_RETURN *status); + +#if defined (ACE_VXWORKS) + extern ACE_Export +#else + ACE_NAMESPACE_INLINE_FUNCTION +#endif /* ACE_VXWORKS */ + int thr_join (ACE_thread_t waiter_id, + ACE_thread_t *thr_id, + ACE_THR_FUNC_RETURN *status); + + /** + * Get the thread affinity + * + * @param thr_id For NPTL-threads, when ACE_HAS_PTHREAD_SETAFFINITY_NP + * defined, this is the thread-id. For linux-threads, when + * ACE_HAS_SCHED_SETAFFINITY defined, it expects a process-id. Since for + * linux-threads a thread is seen as a process, it does the job. + * @param cpu_set_size The size of the cpu_mask + * @param cpu_mask Is a bitmask of CPUs to bind to, e.g value 1 binds the + * thread to the "CPU 0", etc + */ + extern ACE_Export + int thr_get_affinity (ACE_hthread_t id, + size_t cpu_set_size, + cpu_set_t * cpu_mask); + + + /** + * Set the thread affinity + * + * @param thr_id For NPTL-threads, when ACE_HAS_PTHREAD_SETAFFINITY_NP + * defined, this is the thread-id. For linux-threads, when + * ACE_HAS_SCHED_SETAFFINITY defined, it expects a process-id. Since for + * linux-threads a thread is seen as a process, it does the job. + * @param cpu_set_size The size of the cpu_mask + * @param cpu_mask Is a bitmask of CPUs to bind to, e.g value 1 binds the + * thread to the "CPU 0", etc + */ + extern ACE_Export + int thr_set_affinity (ACE_hthread_t thr_id, + size_t cpu_set_size, + const cpu_set_t * cpu_mask); + + /** + * @note the "inst" arg is deprecated. It will be ignored. + */ + extern ACE_Export + int thr_key_detach (ACE_thread_key_t key, void * inst); + + extern ACE_Export + int thr_key_used (ACE_thread_key_t key); + +# if defined (ACE_HAS_THR_C_DEST) +# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + /// @internal Applications should call thr_keycreate + extern ACE_Export + int thr_keycreate_native (ACE_OS_thread_key_t *key, + ACE_THR_C_DEST); +# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ + + /** + * @note the "inst" arge is deprecated. It will be ignored. + */ + extern ACE_Export + int thr_keycreate (ACE_thread_key_t *key, + ACE_THR_C_DEST, + void *inst = 0); +# else +# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + /// @internal Applications should call thr_keycreate instead + extern ACE_Export + int thr_keycreate_native (ACE_OS_thread_key_t *key, + ACE_THR_DEST); +# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ + /** + * @note the "inst" arge is deprecated. It will be ignored. + */ + extern ACE_Export + int thr_keycreate (ACE_thread_key_t *key, + ACE_THR_DEST, + void *inst = 0); + +# endif /* ACE_HAS_THR_C_DEST */ + +# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + /// @internal applications should call thr_keyfree instead + extern ACE_Export + int thr_keyfree_native (ACE_OS_thread_key_t key); +# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ + + extern ACE_Export + int thr_keyfree (ACE_thread_key_t key); + + ACE_NAMESPACE_INLINE_FUNCTION + int thr_kill (ACE_thread_t thr_id, + int signum); + + ACE_NAMESPACE_INLINE_FUNCTION + size_t thr_min_stack (void); + + ACE_NAMESPACE_INLINE_FUNCTION + ACE_thread_t thr_self (void); + + ACE_NAMESPACE_INLINE_FUNCTION + void thr_self (ACE_hthread_t &); + + ACE_NAMESPACE_INLINE_FUNCTION + int thr_setcancelstate (int new_state, + int *old_state); + + ACE_NAMESPACE_INLINE_FUNCTION + int thr_setcanceltype (int new_type, + int *old_type); + + ACE_NAMESPACE_INLINE_FUNCTION + int thr_setconcurrency (int hint); + + ACE_NAMESPACE_INLINE_FUNCTION + int thr_setprio (ACE_hthread_t ht_id, + int priority, + int policy = -1); + + extern ACE_Export + int thr_setprio (const ACE_Sched_Priority prio); + +# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + /// @internal Applications should call thr_setspecific + extern ACE_Export + int thr_setspecific_native (ACE_OS_thread_key_t key, + void *data); +# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ + + extern ACE_Export + int thr_setspecific (ACE_thread_key_t key, + void *data); + + ACE_NAMESPACE_INLINE_FUNCTION + int thr_sigsetmask (int how, + const sigset_t *nsm, + sigset_t *osm); + + ACE_NAMESPACE_INLINE_FUNCTION + int thr_suspend (ACE_hthread_t target_thread); + + ACE_NAMESPACE_INLINE_FUNCTION + void thr_testcancel (void); + + ACE_NAMESPACE_INLINE_FUNCTION + void thr_yield (void); + + //@{ @name A set of wrappers for mutex locks that only work within a single process. + + ACE_NAMESPACE_INLINE_FUNCTION + int thread_mutex_destroy (ACE_thread_mutex_t *m); + + ACE_NAMESPACE_INLINE_FUNCTION + int thread_mutex_init (ACE_thread_mutex_t *m, + int lock_type = 0, + const char *name = 0, + ACE_mutexattr_t *arg = 0); + +#if defined (ACE_HAS_WCHAR) + ACE_NAMESPACE_INLINE_FUNCTION + int thread_mutex_init (ACE_thread_mutex_t *m, + int lock_type, + const wchar_t *name, + ACE_mutexattr_t *arg = 0); +#endif /* ACE_HAS_WCHAR */ + + ACE_NAMESPACE_INLINE_FUNCTION + int thread_mutex_lock (ACE_thread_mutex_t *m); + + ACE_NAMESPACE_INLINE_FUNCTION + int thread_mutex_lock (ACE_thread_mutex_t *m, + const ACE_Time_Value &timeout); + + ACE_NAMESPACE_INLINE_FUNCTION + int thread_mutex_lock (ACE_thread_mutex_t *m, + const ACE_Time_Value *timeout); + + ACE_NAMESPACE_INLINE_FUNCTION + int thread_mutex_trylock (ACE_thread_mutex_t *m); + + ACE_NAMESPACE_INLINE_FUNCTION + 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>. + */ + extern ACE_Export + void unique_name (const void *object, + char *name, + size_t length); +#if defined (ACE_USES_WCHAR) + extern ACE_Export + void unique_name (const void *object, + wchar_t *name, + size_t length); +#endif /* ACE_USES_WCHAR */ +} /* namespace ACE_OS */ + +ACE_END_VERSIONED_NAMESPACE_DECL + +#if !defined (ACE_WIN32) + +extern "C" +{ + typedef struct + { +#if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \ + (!defined (ACE_USES_FIFO_SEM) && \ + (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM))) + /// Protect critical section. + ACE_mutex_t lock_; + /// Keeps track of waiters. + ACE_cond_t condition_; +#else +# if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)) || \ + (!defined (ACE_USES_FIFO_SEM) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_LACKS_NAMED_POSIX_SEM))) + /// Protect critical section. + ACE_mutex_t lock_; +# endif +#endif + + /// Object type. + int type_; + + /// Specifies if this is an auto- or manual-reset event. + int manual_reset_; + + /// "True" if signaled. + int is_signaled_; + + /// Special bool for auto_events alone + /** + * The semantics of auto events forces us to introduce this extra + * variable to ensure that the thread is not woken up + * spuriously. Please see event_wait and event_timedwait () to see + * how this is used for auto_events. Theoretically this is a hack + * that needs revisiting after x.4 + */ + bool auto_event_signaled_; + + /// Number of waiting threads. + unsigned long waiting_threads_; + + /// Signal count + unsigned long signal_count_; + } ACE_eventdata_t; +} + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class ACE_event_t + * + * @brief Wrapper for NT events on UNIX. + */ +class ACE_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: + + /// Event name if process shared. + char* name_; + + /// Event data + ACE_eventdata_t* eventdata_; + +#if (!defined (ACE_HAS_PTHREADS) || !defined (_POSIX_THREAD_PROCESS_SHARED) || defined (ACE_LACKS_CONDATTR_PSHARED)) && \ + (defined (ACE_USES_FIFO_SEM) || \ + (defined (ACE_HAS_POSIX_SEM) && defined (ACE_HAS_POSIX_SEM_TIMEOUT) && !defined (ACE_LACKS_NAMED_POSIX_SEM))) + /// Keeps track of waiters. + ACE_sema_t semaphore_; + +# if (!defined (ACE_HAS_PTHREADS) || !defined (_POSIX_THREAD_PROCESS_SHARED) || defined (ACE_LACKS_MUTEXATTR_PSHARED)) && \ + (defined (ACE_USES_FIFO_SEM) || (defined (ACE_HAS_POSIX_SEM) && !defined (ACE_LACKS_NAMED_POSIX_SEM))) + /// Protect critical section. + ACE_sema_t lock_; +# endif +#endif +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + +#endif /* ACE_WIN32 */ + +#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @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. + * + * If an object of this class is instantiated before ACE_Object_Manager is + * initialized, it will not do anything. This is because this class is + * used only with the ACE_OS_GUARD macro which is passing a reference to + * one of the preallocated Object Manager locks. If the object manager + * hasn't been initialized yet, the lock reference is bogus. This is an + * acceptable tradeoff since in cases where the lock reference is bogus, + * there isn't multithreaded access. Please see detailed comments in + * Object_Manager.h for further information. + * + * 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. + * + * If an object of this class is instantiated before ACE_Object_Manager is + * initialized, it will not do anything. This is because this class is + * used only with the ACE_TSS_GUARD macro which is passing a reference to + * one of the preallocated Object Manager locks. If the object manager + * hasn't been initialized yet, the lock reference is bogus. This is an + * acceptable tradeoff since in cases where the lock reference is bogus, + * there isn't multithreaded access. Please see detailed comments in + * Object_Manager.h for further information. + */ +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 &); +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + +// 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 */ |