diff options
Diffstat (limited to 'ace/Token.h')
-rw-r--r-- | ace/Token.h | 242 |
1 files changed, 126 insertions, 116 deletions
diff --git a/ace/Token.h b/ace/Token.h index 06e286d3a67..54835a1ef1f 100644 --- a/ace/Token.h +++ b/ace/Token.h @@ -1,19 +1,18 @@ /* -*- C++ -*- */ -// $Id$ - -// ============================================================================ -// -// = LIBRARY -// ace -// -// = FILENAME -// Token.h -// -// = AUTHOR -// Original author -- Karl-Heinz Dorn (kdorn@erlh.siemens.de) -// Ported to ACE by Douglas C. Schmidt (schmidt@cs.wustl.edu) -// -// ============================================================================ + +//============================================================================= +/** + * @file Token.h + * + * $Id$ + * + * @author Original author + * @author Karl-Heinz Dorn (kdorn@erlh.siemens.de) + * @author Ported to ACE by + * @author Douglas C. Schmidt (schmidt@cs.wustl.edu) + */ +//============================================================================= + #ifndef ACE_TOKEN_H #define ACE_TOKEN_H @@ -32,36 +31,37 @@ # define ACE_TOKEN_USES_SEMAPHORE #endif /* (ACE_WIN32 && !ACE_HAS_WINCE) || VXWORKS || ACE_PSOS */ +/** + * @class ACE_Token + * + * @brief Class that acquires, renews, and releases a synchronization + * token that is serviced in strict FIFO ordering and that also + * supports (1) recursion and (2) readers/writer semantics. + * + * This class is a more general-purpose synchronization mechanism + * than many native OS mutexes. For example, it implements + * "recursive mutex" semantics, where a thread that owns the token + * can reacquire it without deadlocking. If the same thread calls + * <acquire> multiple times, however, it must call <release> an + * equal number of times before the token is actually released. + * Threads that are blocked awaiting the token are serviced in + * strict FIFO order as other threads release the token (Solaris + * and Pthread mutexes don't strictly enforce an acquisition + * order). There are two FIFO lists within the class. Write + * acquires always have higher priority over read acquires. Which + * means, if you use both write/read operations, care must be + * taken to avoid starvation on the readers. Notice that the + * read/write acquire operations do not have the usual semantic of + * reader/writer locks. Only one reader can acquire the token at + * a time (which is different from the usual reader/writer locks + * where several readers can acquire a lock at the same time as + * long as there is no writer waiting for the lock). We choose + * the names to (1) borrow the semantic to give writers higher + * priority and (2) support a common interface for all locking + * classes in ACE. + */ class ACE_Export ACE_Token { - // = TITLE - // Class that acquires, renews, and releases a synchronization - // token that is serviced in strict FIFO ordering and that also - // supports (1) recursion and (2) readers/writer semantics. - // - // = DESCRIPTION - // This class is a more general-purpose synchronization mechanism - // than many native OS mutexes. For example, it implements - // "recursive mutex" semantics, where a thread that owns the token - // can reacquire it without deadlocking. If the same thread calls - // <acquire> multiple times, however, it must call <release> an - // equal number of times before the token is actually released. - // - // Threads that are blocked awaiting the token are serviced in - // strict FIFO order as other threads release the token (Solaris - // and Pthread mutexes don't strictly enforce an acquisition - // order). There are two FIFO lists within the class. Write - // acquires always have higher priority over read acquires. Which - // means, if you use both write/read operations, care must be - // taken to avoid starvation on the readers. Notice that the - // read/write acquire operations do not have the usual semantic of - // reader/writer locks. Only one reader can acquire the token at - // a time (which is different from the usual reader/writer locks - // where several readers can acquire a lock at the same time as - // long as there is no writer waiting for the lock). We choose - // the names to (1) borrow the semantic to give writers higher - // priority and (2) support a common interface for all locking - // classes in ACE. public: // = Initialization and termination. @@ -70,113 +70,123 @@ public: // = Synchronization operations. + /** + * Acquire the token, sleeping until it is obtained or until the + * expiration of <timeout>, which is treated as "absolute" time. If + * some other thread currently holds the token then <sleep_hook> is + * called before our thread goes to sleep. This <sleep_hook> can be + * used by the requesting thread to unblock a token-holder that is + * sleeping, e.g., by means of writing to a pipe (the ACE + * ACE_Reactor uses this functionality). Return values: 0 if + * acquires without calling <sleep_hook> 1 if <sleep_hook> is + * called. 2 if the token is signaled. -1 if failure or timeout + * occurs (if timeout occurs errno == ETIME) If <timeout> == + * <&ACE_Time_Value::zero> then acquire has polling semantics (and + * does *not* call <sleep_hook>). + */ int acquire (void (*sleep_hook)(void *), void *arg = 0, ACE_Time_Value *timeout = 0); - // Acquire the token, sleeping until it is obtained or until the - // expiration of <timeout>, which is treated as "absolute" time. If - // some other thread currently holds the token then <sleep_hook> is - // called before our thread goes to sleep. This <sleep_hook> can be - // used by the requesting thread to unblock a token-holder that is - // sleeping, e.g., by means of writing to a pipe (the ACE - // ACE_Reactor uses this functionality). Return values: 0 if - // acquires without calling <sleep_hook> 1 if <sleep_hook> is - // called. 2 if the token is signaled. -1 if failure or timeout - // occurs (if timeout occurs errno == ETIME) If <timeout> == - // <&ACE_Time_Value::zero> then acquire has polling semantics (and - // does *not* call <sleep_hook>). + /** + * This behaves just like the previous <acquire> method, except that + * it invokes the virtual function called <sleep_hook> that can be + * overridden by a subclass of ACE_Token. + */ int acquire (ACE_Time_Value *timeout = 0); - // This behaves just like the previous <acquire> method, except that - // it invokes the virtual function called <sleep_hook> that can be - // overridden by a subclass of ACE_Token. + /** + * This should be overridden by a subclass to define the appropriate + * behavior before <acquire> goes to sleep. By default, this is a + * no-op... + */ virtual void sleep_hook (void); - // This should be overridden by a subclass to define the appropriate - // behavior before <acquire> goes to sleep. By default, this is a - // no-op... + /** + * An optimized method that efficiently reacquires the token if no + * other threads are waiting. This is useful for situations where + * you don't want to degrad the quality of service if there are + * other threads waiting to get the token. If <requeue_position> == + * -1 and there are other threads waiting to obtain the token we are + * queued at the end of the list of waiters. If <requeue_position> + * > -1 then it indicates how many entries to skip over before + * inserting our thread into the list of waiters (e.g., + * <requeue_position> == 0 means "insert at front of the queue"). + * Renew has the rather odd semantics such that if there are other + * waiting threads it will give up the token even if the + * nesting_level_ > 1. I'm not sure if this is really the right + * thing to do (since it makes it possible for shared data to be + * changed unexpectedly) so use with caution... This method + * maintians the original token priority. As in <acquire>, the + * <timeout> value is an absolute time. + */ int renew (int requeue_position = 0, ACE_Time_Value *timeout = 0); - // An optimized method that efficiently reacquires the token if no - // other threads are waiting. This is useful for situations where - // you don't want to degrad the quality of service if there are - // other threads waiting to get the token. If <requeue_position> == - // -1 and there are other threads waiting to obtain the token we are - // queued at the end of the list of waiters. If <requeue_position> - // > -1 then it indicates how many entries to skip over before - // inserting our thread into the list of waiters (e.g., - // <requeue_position> == 0 means "insert at front of the queue"). - // Renew has the rather odd semantics such that if there are other - // waiting threads it will give up the token even if the - // nesting_level_ > 1. I'm not sure if this is really the right - // thing to do (since it makes it possible for shared data to be - // changed unexpectedly) so use with caution... This method - // maintians the original token priority. As in <acquire>, the - // <timeout> value is an absolute time. + /// Become interface-compliant with other lock mechanisms (implements + /// a non-blocking <acquire>). int tryacquire (void); - // Become interface-compliant with other lock mechanisms (implements - // a non-blocking <acquire>). + /// Shuts down the ACE_Token instance. int remove (void); - // Shuts down the ACE_Token instance. + /// Relinquish the token. If there are any waiters then the next one + /// in line gets it. int release (void); - // Relinquish the token. If there are any waiters then the next one - // in line gets it. + /// Behave like acquire but in a lower priority. It should probably + /// be called acquire_yield. int acquire_read (void); - // Behave like acquire but in a lower priority. It should probably - // be called acquire_yield. + /// More sophisticate version of acquire_read. int acquire_read (void (*sleep_hook)(void *), void *arg = 0, ACE_Time_Value *timeout = 0); - // More sophisticate version of acquire_read. + /// Just calls <acquire>. int acquire_write (void); - // Just calls <acquire>. + /// More sophisticate version of acquire_write. int acquire_write (void (*sleep_hook)(void *), void *arg = 0, ACE_Time_Value *timeout = 0); - // More sophisticate version of acquire_write. + /// Lower priority try_acquire. int tryacquire_read (void); - // Lower priority try_acquire. + /// Just calls <tryacquire>. int tryacquire_write (void); - // Just calls <tryacquire>. + /// Assumes the caller has acquired the token and returns 0. int tryacquire_write_upgrade (void); - // Assumes the caller has acquired the token and returns 0. // = Accessor methods. + /// Return the number of threads that are currently waiting to get + /// the token. int waiters (void); - // Return the number of threads that are currently waiting to get - // the token. + /// Return the id of the current thread that owns the token. ACE_thread_t current_owner (void); - // Return the id of the current thread that owns the token. + /** + * Force all threads waiting to acquire the token to return one by + * one. The method sets the <signal_all_thread_> to non-zero if + * there're threads waiting, and returns the number of threads + * waiting. If there's no thread waiting for the token, the call + * returns 0 and doesn't do anything. The last thread releases the + * token also reset the <singal_all_thread_> flag to 0. This means, + * any threads that try to acquire the token after the call is + * issued will also get "signaled" and the number of threads waiting + * the token is only a snapshot. + */ int signal_all_threads (void); - // Force all threads waiting to acquire the token to return one by - // one. The method sets the <signal_all_thread_> to non-zero if - // there're threads waiting, and returns the number of threads - // waiting. If there's no thread waiting for the token, the call - // returns 0 and doesn't do anything. The last thread releases the - // token also reset the <singal_all_thread_> flag to 0. This means, - // any threads that try to acquire the token after the call is - // issued will also get "signaled" and the number of threads waiting - // the token is only a snapshot. + /// Dump the state of an object. void dump (void) const; - // Dump the state of an object. + /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; - // Declare the dynamic allocation hooks. // = The following structure implements a ACE_FIFO of waiter threads // that are asleep waiting to obtain the token. @@ -241,42 +251,42 @@ private: // Tail of the list of waiting threads. }; + /// Implements the <acquire> and <tryacquire> methods above. int shared_acquire (void (*sleep_hook_func)(void *), void *arg, ACE_Time_Value *timeout, ACE_Token_Op_Type op_type); - // Implements the <acquire> and <tryacquire> methods above. + /// Wake next in line for ownership. void wakeup_next_waiter (void); - // Wake next in line for ownership. + /// A queue of writer threads. ACE_Token_Queue writers_; - // A queue of writer threads. + /// A queue of reader threads. ACE_Token_Queue readers_; - // A queue of reader threads. + /// ACE_Thread_Mutex used to lock internal data structures. ACE_Thread_Mutex lock_; - // ACE_Thread_Mutex used to lock internal data structures. + /// Current owner of the token. ACE_thread_t owner_; - // Current owner of the token. + /// Some thread (i.e., <owner_>) is using the token. We need this + /// extra variable to deal with POSIX pthreads madness... int in_use_; - // Some thread (i.e., <owner_>) is using the token. We need this - // extra variable to deal with POSIX pthreads madness... + /// Number of waiters. int waiters_; - // Number of waiters. + /// Current nesting level. int nesting_level_; - // Current nesting level. + /// Whether we are "signaling" all threads or not. int signal_all_threads_; - // Whether we are "signaling" all threads or not. + /// The attributes for the condition variables, optimizes lock time. ACE_Condition_Attributes attributes_; - // The attributes for the condition variables, optimizes lock time. }; #if defined (__ACE_INLINE__) |