Reference

ACE_Token(3)

Class that acquires, renews, and releases a synchronization token that is serviced in strict FIFO ordering and that also supports readers/writer semantics.

NAME

ACE_Token - Class that acquires, renews, and releases a synchronization token that is serviced in strict FIFO ordering and that also supports readers/writer semantics.

SYNOPSIS

#include <ace/Token.h>
class ACE_Token
{
  public:
    ACE_Token (LPCTSTR name = 0, void * = 0);
    virtual ~ACE_Token (void);
    int acquire (void (*sleep_hook)(
        void *),
        void *arg = 0,
        ACE_Time_Value *timeout = 0
        );
    int acquire (ACE_Time_Value *timeout = 0);
    virtual void sleep_hook (void);
    int renew (int requeue_position = 0, ACE_Time_Value *timeout = 0);
    int tryacquire (void);
    int remove (void);
    int release (void);
    int acquire_read (void);
    int acquire_read (void (*sleep_hook)(
        void *),
        void *arg = 0,
        ACE_Time_Value *timeout = 0
        );
    int acquire_write (void);
    int acquire_write (void (*sleep_hook)(
        void *),
        void *arg = 0,
        ACE_Time_Value *timeout = 0
        );
    int tryacquire_read (void);
    int tryacquire_write (void);
    int waiters (void);
    ACE_thread_t current_owner (void);
    int signal_all_threads (void);
    void dump (void) const;
    ACE_ALLOC_HOOK_DECLARE;
    struct ACE_Token_Queue_Entry
    {
      public:
        ACE_Token_Queue_Entry (
            ACE_Thread_Mutex &m,
            ACE_thread_t t_id
            );
        ACE_Token_Queue_Entry (
            ACE_Thread_Mutex &m,
            ACE_thread_t t_id,
            ACE_Condition_Attributes &attributes
            );
        int wait (ACE_Time_Value *timeout, ACE_Thread_Mutex &lock);
        int signal (void);
        ACE_Token_Queue_Entry *next_;
        ACE_thread_t thread_id_;
        ACE_Semaphore cv_;
        ACE_Condition_Thread_Mutex cv_;
        int runable_;
    };

inline int acquire (ACE_Time_Value * = 0); inline int tryacquire (void); inline int remove (void); inline int release (void);
private: enum ACE_Token_Op_Type{ READ_TOKEN = 1, WRITE_TOKEN };

struct ACE_Token_Queue
{
public: ACE_Token_Queue (void); void remove_entry (ACE_Token_Queue_Entry *); ACE_Token_Queue_Entry *head_; ACE_Token_Queue_Entry *tail_;
}; int shared_acquire (void (*sleep_hook_func)(
void *),
void *arg,
ACE_Time_Value *timeout,
ACE_Token_Op_Type op_type
); ACE_Token_Queue writers_; ACE_Token_Queue readers_; ACE_Thread_Mutex lock_; ACE_thread_t owner_; int in_use_; int waiters_; int nesting_level_; int signal_all_threads_; ACE_Condition_Attributes attributes_; };

DESCRIPTION

This class is a more general-purpose synchronization mechanism than SunOS 5.x mutexes. For example, it implements "recursive mutex" semantics, where a thread that owns the token can reacquire it without deadlocking. In addition, 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 1.) to borrow the semantic to give writers higher priority, and, 2.) to support a common interface over all locking classes in ACE.

Initialization and termination.

ACE_Token (LPCTSTR name = 0, void * = 0);

virtual ~ACE_Token (void);

Synchronization operations.

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).

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.

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...

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.

int tryacquire (void);

Become interface-compliant with other lock mechanisms (implements a non-blocking acquire).

int remove (void);

Shuts down the ACE_Token instance.

int release (void);

Relinquish the token. If there are any waiters then the next one in line gets it.

int acquire_read (void);

Behave like acquire but in a lower priority. It should probably be called acquire_yield.

int acquire_read (void (*sleep_hook)(
    void *),
    void *arg = 0,
    ACE_Time_Value *timeout = 0
    );

More sophisticate version of acquire_read.

int acquire_write (void);

Just calls acquire.

int acquire_write (void (*sleep_hook)(
    void *),
    void *arg = 0,
    ACE_Time_Value *timeout = 0
    );

More sophisticate version of acquire_write.

int tryacquire_read (void);

Lower priority try_acquire.

int tryacquire_write (void);

Just calls tryacquire.

Accessor methods.

int waiters (void);

Return the number of threads that are currently waiting to get the token.

ACE_thread_t current_owner (void);

Return the id of the current thread that owns the token.

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.

void dump (void) const;

Dump the state of an object.

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.

AUTHOR

Original author -- Karl-Heinz Dorn ([email protected]) Ported to ACE by Douglas C. Schmidt ([email protected])

LIBRARY

ace