mirror of
https://github.com/mangosfour/server.git
synced 2025-12-12 01:37:00 +00:00
2068 lines
65 KiB
C++
2068 lines
65 KiB
C++
// -*- C++ -*-
|
|
|
|
//=============================================================================
|
|
/**
|
|
* @file OS_NS_Thread.h
|
|
*
|
|
* $Id: OS_NS_Thread.h 97911 2014-10-07 21:58:25Z shuston $
|
|
*
|
|
* @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_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 /**/ <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 int 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
|
|
|
|
# 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 (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_;
|
|
};
|
|
|
|
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;
|
|
};
|
|
|
|
struct ACE_Export ACE_mutexattr_t
|
|
{
|
|
int type;
|
|
};
|
|
|
|
ACE_END_VERSIONED_NAMESPACE_DECL
|
|
|
|
# endif /* ACE_HAS_WTHREADS_CONDITION_VARIABLE || 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
|
|
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 /**/ <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 &id);
|
|
|
|
/// Assignment operator
|
|
ACE_Thread_ID& operator= (const ACE_Thread_ID&id);
|
|
|
|
/// 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)
|
|
# 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) /* 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 ();
|
|
|
|
# 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 <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) */
|
|
|
|
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);
|
|
|
|
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 @a 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 @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<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 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
|
|
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<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 @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 (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_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 (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
|
|
const char* thr_name (void);
|
|
|
|
/// 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);
|
|
|
|
/// 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 (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
|
|
* @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 */
|
|
|
|
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.
|
|
* @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_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_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 (void);
|
|
|
|
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 */
|