// -*- C++ -*- //============================================================================= /** * @file OS_NS_Thread.h * * @author Douglas C. Schmidt * @author Jesper S. M|ller * @author and a cast of thousands... */ //============================================================================= #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_HAS_TSS_EMULATION) && !defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) # if defined (ACE_HAS_VXTHREADS) && !defined (_WRS_CONFIG_SMP) && !defined (INCLUDE_AMP_CPU) # include "taskVarLib.h" /* used by VxWorks < 6.9 */ # endif /* VxWorks and ! SMP */ #endif # 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 /**/ # endif /* sun */ // Need to #include these before #defining USYNC_PROCESS on SunOS 5.x. # include /**/ # include /**/ # 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 /**/ # include /**/ # 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 /**/ // for sysClkRateGet() # include /**/ # if !defined (__RTP__) # include /**/ # include /**/ # 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 ACE_VX_TASK_ID ACE_thread_t; typedef ACE_VX_TASK_ID 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 # 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 @c 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 # if !defined (STACK_SIZE_PARAM_IS_A_RESERVATION) # define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000 # endif /* STACK_SIZE_PARAM_IS_A_RESERVATION */ # 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 defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE) typedef CONDITION_VARIABLE ACE_cond_t; # elif 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 () 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) || defined (ACE_MQX) /** * 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_; }; ACE_END_VERSIONED_NAMESPACE_DECL # endif /* ACE_LACKS_COND_T */ # if defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE) || defined (ACE_LACKS_COND_T) ACE_BEGIN_VERSIONED_NAMESPACE_DECL struct ACE_Export ACE_condattr_t { int type; }; #if !defined (ACE_MQX) struct ACE_Export ACE_mutexattr_t { int type; }; #endif ACE_END_VERSIONED_NAMESPACE_DECL # endif /* ACE_HAS_WTHREADS_CONDITION_VARIABLE || ACE_LACKS_COND_T */ # if defined (ACE_LACKS_RWLOCK_T) 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 bool 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 /**/ 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 . 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 (); /// Copy constructor. ACE_Thread_ID (const ACE_Thread_ID &id); /// Assignment operator ACE_Thread_ID& operator= (const ACE_Thread_ID &id); /// Get the thread id. ACE_thread_t id () const; /// Set the thread id. void id (ACE_thread_t); /// Get the thread handle. ACE_hthread_t handle () const; /// Set the thread handle. void handle (ACE_hthread_t); // Create a string representation of the thread id. void to_string (char *thr_string, size_t thr_string_len) const; // Create a string representation of the thread id. template void to_string (char (&thr_string)[N]) const { this->to_string (thr_string, N); } /// 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) # 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 */ typedef long ACE_id_t; # define ACE_SELF (-1) typedef short ACE_pri_t; # endif /* ! ACE_HAS_STHREADS */ #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); /// 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 (); # if defined (ACE_HAS_VXTHREADS) # if (defined (_WRS_CONFIG_SMP) || defined (INCLUDE_AMP_CPU)) static __thread void* ace_tss_keys; # else /* ! VxWorks SMP */ static void* ace_tss_keys; # endif /* ! VxWorks SMP */ # endif /* ACE_HAS_VXTHREADS */ # 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 bool key_created_; # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ }; # 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 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 () 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: ACE_ALLOC_HOOK_DECLARE; /// 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) */ 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. ACE_NAMESPACE_INLINE_FUNCTION int condattr_init (ACE_condattr_t &attributes, int type = ACE_DEFAULT_SYNCH_TYPE); ACE_NAMESPACE_INLINE_FUNCTION int condattr_synctype (ACE_condattr_t &attributes, int& type); ACE_NAMESPACE_INLINE_FUNCTION int condattr_destroy (ACE_condattr_t &attributes); ACE_NAMESPACE_INLINE_FUNCTION int condattr_setclock(ACE_condattr_t &attributes, clockid_t clock_id); #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 *timeout); #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) extern ACE_Export int cond_timedwait (ACE_cond_t *cv, ACE_thread_mutex_t *m, ACE_Time_Value *timeout); extern ACE_Export 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); ACE_NAMESPACE_INLINE_FUNCTION 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); extern ACE_Export int event_init (ACE_event_t *event, int type, ACE_condattr_t *attributes, int manual_reset = 0, int initial_state = 0, 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); ACE_NAMESPACE_INLINE_FUNCTION int event_init (ACE_event_t *event, int type, ACE_condattr_t *attributes, int manual_reset, int initial_state, 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); ACE_NAMESPACE_INLINE_FUNCTION 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 @a timeout == 0, calls . 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 @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. */ 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, @a 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 @c 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 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 scheduling 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); ACE_NAMESPACE_INLINE_FUNCTION int sema_init (ACE_sema_t *s, u_int count, int type, ACE_condattr_t *attributes, 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); ACE_NAMESPACE_INLINE_FUNCTION int sema_init (ACE_sema_t *s, u_int count, int type, ACE_condattr_t *attributes, const wchar_t *name, void *arg = 0, int max = 0x7fffffff, LPSECURITY_ATTRIBUTES sa = 0); # endif /* ACE_HAS_WCHAR */ ACE_NAMESPACE_INLINE_FUNCTION void sema_avoid_unlink (ACE_sema_t *s, bool avoid_unlink); ACE_NAMESPACE_INLINE_FUNCTION int sema_unlink (const char *name); 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 @c 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 @a flags attributes and running @a func * with @a args (if @a thread_adapter is non-0 then @a func and @a args * are ignored and are obtained from @a thread_adapter). @a thr_id * and @a t_handle are set to the thread's ID and handle (?), * respectively. The thread runs at @a priority priority (see * below). * * The @a flags are a bitwise-OR of the following: * = BEGIN * 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 * * By default, or if @a priority is set to * ACE_DEFAULT_THREAD_PRIORITY, an "appropriate" priority value for * the given scheduling policy (specified in @a flags, e.g., * @c 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 @a thread_adapter is always deleted by @c thr_create, * therefore it must be allocated with global operator new. * * At the moment for @a thr_name a valid string is passed then this * will be used on VxWorks to set the task name. If we just pass a pointer * the name of the task is returned */ 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 = ACE_DEFAULT_THREAD_STACKSIZE, ACE_Base_Thread_Adapter *thread_adapter = 0, const char** thr_name = 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 (); 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_HAS_VXTHREADS) extern ACE_Export #else ACE_NAMESPACE_INLINE_FUNCTION #endif /* ACE_HAS_VXTHREADS */ int thr_join (ACE_hthread_t waiter_id, ACE_THR_FUNC_RETURN *status); #if defined (ACE_HAS_VXTHREADS) extern ACE_Export #else ACE_NAMESPACE_INLINE_FUNCTION #endif /* ACE_HAS_VXTHREADS */ 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, in bytes. * @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 thr_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, in bytes. * @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); extern ACE_Export int thr_key_detach (ACE_thread_key_t key); 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 */ extern ACE_Export int thr_keycreate (ACE_thread_key_t *key, ACE_THR_C_DEST); # 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 */ extern ACE_Export int thr_keycreate (ACE_thread_key_t *key, ACE_THR_DEST); # 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 (); ACE_NAMESPACE_INLINE_FUNCTION ACE_thread_t thr_self (); ACE_NAMESPACE_INLINE_FUNCTION void thr_self (ACE_hthread_t &); ACE_NAMESPACE_INLINE_FUNCTION const char* thr_name (); /// Stores a string version of the current thread id into buffer and /// returns the size of this thread id in bytes. ACE_NAMESPACE_INLINE_FUNCTION ssize_t thr_id (char buffer[], size_t buffer_length); /** * For systems that support it (Only Linux as of writing), this is a wrapper * for pid_t gettid(). * * It returns the system-wide thread id (TID) for the current thread. These * are similar to PIDs and, for x86 Linux at least, are much shorter than * what is returned from thr_self(), which is an address. * * For older Linux (pre 2.4.11) and other systems that don't have gettid(), * this uses ACE_NOTSUP_RETURN (-1). */ ACE_NAMESPACE_INLINE_FUNCTION pid_t thr_gettid (); /** * Puts the string representation of pid_t thr_gettid() into the buffer and * returns number of bytes added. */ ACE_NAMESPACE_INLINE_FUNCTION ssize_t thr_gettid (char buffer[], size_t buffer_length); /// State is THR_CANCEL_ENABLE or THR_CANCEL_DISABLE ACE_NAMESPACE_INLINE_FUNCTION int thr_setcancelstate (int new_state, int *old_state); /// Type is THR_CANCEL_DEFERRED or THR_CANCEL_ASYNCHRONOUS 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 (); ACE_NAMESPACE_INLINE_FUNCTION void thr_yield (); //@{ @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 * @a 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 @a 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 */ #if !defined (ACE_WIN32) /// Implementation details of Event emulation on Unix, may be in shared memory struct ACE_eventdata_t { /// Protect critical section. ACE_mutex_t lock_; /// Keeps track of waiters. ACE_cond_t condition_; /// 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_timedwait () to see * how this is used for auto_events. * @todo 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_ALLOC_HOOK_DECLARE; }; # if !defined ACE_USES_FIFO_SEM \ && !(defined ACE_HAS_POSIX_SEM && defined ACE_HAS_POSIX_SEM_TIMEOUT \ && !defined ACE_LACKS_NAMED_POSIX_SEM) # define ACE_EVENT_NO_FIFO_SEM # endif # if (defined ACE_HAS_PTHREADS && defined _POSIX_THREAD_PROCESS_SHARED \ && !defined ACE_LACKS_MUTEXATTR_PSHARED) || defined ACE_EVENT_NO_FIFO_SEM # define ACE_EVENT_USE_MUTEX_PSHARED 1 # else # define ACE_EVENT_USE_MUTEX_PSHARED 0 # endif # if (defined ACE_HAS_PTHREADS && defined _POSIX_THREAD_PROCESS_SHARED \ && !defined ACE_LACKS_CONDATTR_PSHARED \ && !defined ACE_LACKS_MUTEXATTR_PSHARED) || defined ACE_EVENT_NO_FIFO_SEM # define ACE_EVENT_USE_COND_PSHARED 1 # else # define ACE_EVENT_USE_COND_PSHARED 0 # endif /** * @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_init (ACE_event_t *, int, ACE_condattr_t *, 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 *); public: /// Constructor initializing all pointer fields to null ACE_event_t (); private: /// Lock the internal mutex/semaphore int lock (); /// Unlock the internal mutex/semaphore int unlock (); /// Use the internal semaphore or condition variable to unblock one thread int wake_one (); /// Event name if process shared. char *name_; /// Event data ACE_eventdata_t *eventdata_; # if !ACE_EVENT_USE_COND_PSHARED /// Keeps track of waiters. ACE_sema_t semaphore_; # endif # if !ACE_EVENT_USE_MUTEX_PSHARED /// Protect critical section. ACE_sema_t lock_; # endif }; #endif /* ACE_WIN32 */ ACE_END_VERSIONED_NAMESPACE_DECL #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 (); /// Explicitly acquire the lock. int acquire (); /// Explicitly release the lock. int release (); protected: /// Reference to the mutex. ACE_thread_mutex_t &lock_; /// Keeps track of whether we acquired the lock or failed. int owner_; ACE_OS_Thread_Mutex_Guard &operator= (const ACE_OS_Thread_Mutex_Guard &) = delete; ACE_OS_Thread_Mutex_Guard (const ACE_OS_Thread_Mutex_Guard &) = delete; }; /** * @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 (); /// Explicitly acquire the lock. int acquire (); /// Explicitly release the lock. int release (); protected: /// Reference to the mutex. ACE_recursive_thread_mutex_t &lock_; /// Keeps track of whether we acquired the lock or failed. int owner_; ACE_OS_Recursive_Thread_Mutex_Guard &operator= (const ACE_OS_Recursive_Thread_Mutex_Guard &) = delete; ACE_OS_Recursive_Thread_Mutex_Guard (const ACE_OS_Recursive_Thread_Mutex_Guard &) = delete; }; 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 */