diff options
Diffstat (limited to 'ace/Synch_T.h')
-rw-r--r-- | ace/Synch_T.h | 613 |
1 files changed, 613 insertions, 0 deletions
diff --git a/ace/Synch_T.h b/ace/Synch_T.h new file mode 100644 index 00000000000..ffa705c0f70 --- /dev/null +++ b/ace/Synch_T.h @@ -0,0 +1,613 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Synch_T.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SYNCH_T_H) +#define ACE_SYNCH_T_H + +#include "ace/Event_Handler.h" +#include "ace/Synch.h" + +// Forward decl +class ACE_Time_Value; + +template <class LOCK, class TYPE> +class ACE_Test_and_Set : public ACE_Event_Handler +{ + // = TITLE + // Implements the classic ``test and set'' operation. + // + // = DESCRIPTION + // This class keeps track of the status of <is_set_>, which can + // be set based on various events (such as receipt of a signal). +public: + ACE_Test_and_Set (TYPE initial_value = 0); + + TYPE is_set (void) const; + // Returns true if we are set, else false. + + TYPE set (TYPE); + // Sets the <set_> status, returning + + virtual int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0); + // Called when object is signaled by OS (either via UNIX signals or + // when a Win32 object becomes signaled). + +private: + TYPE is_set_; + // Keeps track of our state. + + LOCK lock_; +}; + +template <class LOCK, class TYPE> +class ACE_Atomic_Op + // = TITLE + // Transparently parameterizes synchronization into basic + // arithmetic operations. + // + // = DESCRIPTION + // This class is described in an article in the July/August 1994 + // issue of the C++ Report magazine. It implements a + // templatized version of the Decorator pattern from the GoF book. +{ +public: + ACE_Atomic_Op (void); + // Initialize <count_> to 0. + + ACE_Atomic_Op (TYPE c); + // Initialize <count_> to c. + + TYPE operator++ (void); + // Atomically pre-increment <count_>. + + TYPE operator++ (int); + // Atomically post-increment <count_>. + + TYPE operator+= (const TYPE i); + // Atomically increment <count_> by inc. + + TYPE operator-- (void); + // Atomically pre-decrement <count_>. + + TYPE operator-- (int); + // Atomically post-decrement <count_>. + + TYPE operator-= (const TYPE i); + // Atomically decrement <count_> by dec. + + TYPE operator== (const TYPE i) const; + // Atomically compare <count_> with rhs. + + TYPE operator>= (const TYPE i) const; + // Atomically check if <count_> greater than or equal to rhs. + + TYPE operator> (const TYPE rhs) const; + // Atomically check if <count_> greater than rhs. + + TYPE operator<= (const TYPE rhs) const; + // Atomically check if <count_> less than or equal to rhs. + + TYPE operator< (const TYPE rhs) const; + // Atomically check if <count_> less than rhs. + + void operator= (const TYPE i); + // Atomically assign rhs to <count_>. + + void operator= (const ACE_Atomic_Op<LOCK, TYPE> &rhs); + // Atomically assign <rhs> to <count_>. + + operator TYPE () const; + // Atomically return <count_>. + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + + ACE_Atomic_Op (const ACE_Atomic_Op<LOCK, TYPE> &); + // Manage copying... + +private: + LOCK lock_; + // Type of synchronization mechanism. + + TYPE value_; + // Current object decorated by the atomic op. +}; + +template <class TYPE> +class ACE_TSS + // = TITLE + // Allows objects that are "physically" in thread specific + // storage (i.e., private to a thread) to be accessed as though + // they were "logically" global to a program. + // + // = DESCRIPTION + // This class is a wrapper around the OS thread library + // thread-specific functions. It uses the C++ operator->() to + // shield applications from the details of accessing + // thread-specific storage. +{ +public: + ACE_TSS (TYPE *ts_obj = 0); + // If caller has passed us a non-NULL ts_obj *, then we'll just use + // this to initialize the thread-specific value. Thus, subsequent + // calls to operator->() will return this value. This is useful + // since it enables us to assign objects to thread-specific data + // that have arbitrarily complex constructors! + + ~ACE_TSS (void); + // Deregister with thread-key administration. + + TYPE *ts_object (void) const; + // Get the thread-specific object for the key associated with this + // object. Returns 0 if the data has never been initialized, + // otherwise returns a pointer to the data. + + TYPE *ts_object (TYPE *); + // Set the thread-specific object for the key associated with this + // object. Returns 0 if the data has never been initialized, + // otherwise returns a pointer to the previous value for the data. + + TYPE *operator-> () const; + // Use a "smart pointer" to get the thread-specific object + // associated with the <key_>. + + operator TYPE *(void) const; + // return or create and return the calling threads TYPE object. + + virtual TYPE *make_TSS_TYPE (void) const; + // hook for construction parameters. + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + TYPE *ts_get (void) const; + // Actually implements the code that retrieves the object from + // thread-specific storage. + +#if !(defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)) + TYPE type_; + // This implementation only works for non-threading systems... +#else + ACE_Mutex keylock_; + // Avoid race conditions during initialization. + + int once_; + // "First time in" flag. + + ACE_thread_key_t key_; + // Key for the thread-specific error data. + + static void cleanup (void *ptr); + // "Destructor" that deletes internal TYPE * when thread exits. +#endif /* defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) */ + // = Disallow copying... + void operator= (const ACE_TSS<TYPE> &) {} + ACE_TSS (const ACE_TSS<TYPE> &) {} +}; + +#if defined (ACE_HAS_TEMPLATE_TYPEDEFS) +class ACE_NULL_SYNCH + // = TITLE + // Implement a do nothing Synchronization wrapper that + // typedefs the <ACE_Condition> and <ACE_Mutex> to the Null* versions. +{ +public: + typedef ACE_Null_Mutex MUTEX; + // "Do-nothing" mutex type. + + typedef ACE_Null_Condition_Mutex CONDITION; + // "Do-nothing" condition type. +}; +#else /* Necessary to support broken cfront-based C++ compilers... */ +#define ACE_NULL_SYNCH ACE_Null_Mutex, ACE_Null_Condition_Mutex +#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */ + +template <class LOCK> +class ACE_Guard + // = TITLE + // This data structure is meant to be used within a method or + // function... It performs automatic aquisition and release of + // a parameterized synchronization object <LOCK>. + // + // = DESCRIPTION + // The <LOCK> class given as an actual parameter must provide at + // the very least the <acquire>, <tryacquire>, <release>, and + // <remove> methods. +{ +public: + ACE_Guard (LOCK &l, int block = 1): lock_ (&l) + { + this->owner_ = block ? this->acquire () : this->tryacquire (); + } + // Implicitly and automatically acquire (or try to acquire) the + // lock. + + ~ACE_Guard (void) { if (this->owner_ != -1) this->release (); } + // Implicitly release the lock. + + int locked (void) { return this->owner_ != -1; } + // 1 if locked, 0 if couldn't acquire the lock + // (errno will contain the reason for this). + + int remove (void) { return this->release (); } + // Explicitly release the lock. + + int acquire (void) { return this->owner_ = this->lock_->acquire (); } + // Explicitly acquire the lock. + + int tryacquire (void) { return this->owner_ = this->lock_->tryacquire (); } + // Conditionally acquire the lock (i.e., won't block). + + int release (void) { this->owner_ = -1; return this->lock_->release (); } + // Explicitly release the lock. + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + ACE_Guard (LOCK *lock): lock_ (lock) {} + // Helper, meant for subclass only. + + LOCK *lock_; + // Pointer to the LOCK we're guarding. + + int owner_; + // Keeps track of whether we acquired the lock or failed. + +private: + // = Prevent assignment and initialization. + void operator= (const ACE_Guard<LOCK> &) {} + ACE_Guard (const ACE_Guard<LOCK> &) {} +}; + +template <class LOCK> +class ACE_Write_Guard : public ACE_Guard<LOCK> + // = TITLE + // This class is similar to class <ACE_Guard>, though it + // acquires/releases a write lock automatically (naturally, the + // <LOCK> it is instantiated with must support the appropriate + // API). +{ +public: + ACE_Write_Guard (LOCK &m, int block = 1): ACE_Guard<LOCK> (&m) + { + this->owner_ = block ? this->acquire_write () : this->tryacquire_write (); + } + // Implicitly and automatically acquire (or try to acquire) a write + // lock. + + int acquire_write (void) { return this->owner_ = this->lock_->acquire_write (); } + // Explicitly acquire the write lock. + + int acquire (void) { return this->owner_ = this->lock_->acquire_write (); } + // Explicitly acquire the write lock. + + int tryacquire_write (void) { return this->owner_ = this->lock_->acquire_write (); } + // Conditionally acquire the write lock (i.e., won't block). + + int tryacquire (void) { return this->owner_ = this->lock_->tryacquire_write (); } + // Conditionally acquire the write lock (i.e., won't block). + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +template <class LOCK> +class ACE_Read_Guard : public ACE_Guard<LOCK> + // = TITLE + // This class is similar to class <ACE_Guard>, though it + // acquires/releases a read lock automatically (naturally, the + // <LOCK> it is instantiated with must support the appropriate + // API). +{ +public: + ACE_Read_Guard (LOCK &m, int block = 1): ACE_Guard<LOCK> (&m) + { + this->owner_ = block ? this->acquire_read () : this->tryacquire_read (); + } + // Implicitly and automatically acquire (or try to acquire) a read + // lock. + + int acquire_read (void) { return this->owner_ = this->lock_->acquire_read (); } + // Explicitly acquire the read lock. + + int acquire (void) { return this->owner_ = this->lock_->acquire_read (); } + // Explicitly acquire the read lock. + + int tryacquire_read (void) { return this->owner_ = this->lock_->tryacquire_read (); } + // Conditionally acquire the read lock (i.e., won't block). + + int tryacquire (void) { return this->owner_ = this->lock_->tryacquire_read (); } + // Conditionally acquire the read lock (i.e., won't block). + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#if !(defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)) + +#define ACE_TSS_Guard ACE_Guard +#define ACE_TSS_Write_GUARD ACE_Write_Guard +#define ACE_TSS_Read_GUARD ACE_Read_Guard + +#else // ACE platform supports some form of threading and + // thread-specific storage. + +template <class LOCK> +class ACE_TSS_Guard + // = TITLE + // This data structure is meant to be used within a method or + // function... It performs automatic aquisition and release of + // a synchronization object. Moreover, it ensures that the lock + // is released even if a thread exits via "thr_exit()"! +{ +public: + ACE_TSS_Guard (LOCK &lock, int block = 1); + // Implicitly and automatically acquire the thread-specific lock. + + ~ACE_TSS_Guard (void); + // Implicitly release the thread-specific lock. + + int remove (void); + // Explicitly release the thread-specific lock. + + int acquire (void); + // Explicitly acquire the thread-specific lock. + + int tryacquire (void); + // Conditionally acquire the thread-specific lock (i.e., won't + // block). + + int release (void); + // Explicitly release the thread-specific lock. + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + ACE_TSS_Guard (void); + // Helper, meant for subclass only. + + void init_key (void); + // Initialize the key. + + static void cleanup (void *ptr); + // Called when thread exits to clean up the lock. + + ACE_thread_key_t key_; + // Thread-specific key... + +private: + // = Prevent assignment and initialization. + void operator= (const ACE_TSS_Guard<LOCK> &) {} + ACE_TSS_Guard (const ACE_TSS_Guard<LOCK> &) {} +}; + +template <class LOCK> +class ACE_TSS_Write_Guard : public ACE_TSS_Guard<LOCK> + // = TITLE + // This class is similar to class ACE_TSS_Guard, though it + // acquires/releases a write-lock automatically (naturally, the + // LOCK it is instantiated with must support the appropriate + // API). +{ +public: + ACE_TSS_Write_Guard (LOCK &lock, int block = 1); + // Implicitly and automatically acquire the thread-specific write lock. + + int acquire_write (void); + // Explicitly acquire the thread-specific write lock. + + int acquire (void); + // Explicitly acquire the thread-specific write lock. + + int tryacquire_write (void); + // Conditionally acquire the thread-specific write lock (i.e., won't block). + + int tryacquire (void); + // Conditionally acquire the thread-specific write lock (i.e., won't block). + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +template <class LOCK> +class ACE_TSS_Read_Guard : public ACE_TSS_Guard<LOCK> + // = TITLE + // This class is similar to class <ACE_TSS_Guard>, though it + // acquires/releases a read lock automatically (naturally, the + // <LOCK> it is instantiated with must support the appropriate + // API). +{ +public: + ACE_TSS_Read_Guard (LOCK &lock, int block = 1); + // Implicitly and automatically acquire the thread-specific read lock. + + int acquire_read (void); + // Explicitly acquire the thread-specific read lock. + + int acquire (void); + // Explicitly acquire the thread-specific read lock. + + int tryacquire_read (void); + // Conditionally acquire the thread-specific read lock (i.e., won't block). + + int tryacquire (void); + // Conditionally acquire the thread-specific read lock (i.e., won't block). + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; +#endif /* !(defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)) */ + +#if defined (ACE_HAS_THREADS) // ACE platform supports some form of threading. + +template <class MUTEX> +class ACE_Condition + // = TITLE + // ACE_Condition variable wrapper, which allows threads to block + // until shared data changes state. +{ +public: + ACE_Condition (MUTEX &m, int type = USYNC_THREAD, + LPCTSTR name = 0, void *arg = 0); + // Initialize the condition variable. + + ~ACE_Condition (void); + // Implicitly destroy the condition variable. + + int remove (void); + // Explicitly destroy the condition variable. + + int wait (const ACE_Time_Value *abstime); + // Block on condition, or until absolute time-of-day has passed. If + // abstime == 0 use "blocking" <wait> semantics. Else, if <abstime> + // != 0 and the call times out before the condition is signaled + // <wait> returns -1 and sets errno to ETIME. + + int wait (void); + // Block on condition. + + int wait (MUTEX &mutex, const ACE_Time_Value *abstime = 0); + // Block on condition or until absolute time-of-day has passed. If + // abstime == 0 use "blocking" wait() semantics on the <mutex> + // passed as a parameter (this is useful if you need to store the + // <Condition> in shared memory). Else, if <abstime> != 0 and the + // call times out before the condition is signaled <wait> returns -1 + // and sets errno to ETIME. + + int signal (void); + // Signal one waiting thread. + + int broadcast (void); + // Signal *all* waiting threads. + + MUTEX &mutex (void); + // Returns a reference to the underlying mutex_; + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_cond_t cond_; + // Condition variable. + + MUTEX &mutex_; + // Reference to mutex lock. + + // = Prevent assignment and initialization. + void operator= (const ACE_Condition<MUTEX> &) {} + ACE_Condition (const ACE_Condition<MUTEX> &c): mutex_ (c.mutex_) {} +}; + +template <class MUTEX> +class ACE_Process_Condition : public ACE_Condition<MUTEX> + // = TITLE + // ACE_Condition variable wrapper that works across processes. +{ +public: + ACE_Process_Condition (MUTEX &m, LPCTSTR name = 0, void *arg = 0); + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +template <class MUTEX> +class ACE_Thread_Condition : public ACE_Condition<MUTEX> + // = TITLE + // ACE_Condition variable wrapper that works within processes. +{ +public: + ACE_Thread_Condition (MUTEX &m, LPCTSTR name = 0, void *arg = 0); + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#if defined (ACE_HAS_TEMPLATE_TYPEDEFS) +class ACE_MT_SYNCH + // = TITLE + // Implement a default thread safe synchronization wrapper that + // typedefs the <ACE_Condition> and <ACE_Mutex> to the + // <ACE_Condition> and <ACE_Mutex> versions. Note that this + // should be a template, but SunC++ 4.0.1 complains about + // this... +{ +public: + typedef ACE_Thread_Mutex MUTEX; + typedef ACE_Condition_Thread_Mutex CONDITION; +}; +#else /* Necessary to support broken cfront-based C++ compilers... */ +#define ACE_MT_SYNCH ACE_Thread_Mutex,ACE_Condition_Thread_Mutex +#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */ + +#if defined (__osf__) && ! defined (__GNUG__) +#pragma define_template ACE_Condition <ACE_Mutex> +#endif + +#define ACE_SYNCH ACE_MT_SYNCH +#else +#define ACE_SYNCH ACE_NULL_SYNCH +#endif /* ACE_HAS_THREADS */ + +#if defined (__ACE_INLINE__) +#include "ace/Synch_T.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Synch_T.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Synch_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_SYNCH_T_H */ |