diff options
author | levine <levine@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1996-10-21 21:41:34 +0000 |
---|---|---|
committer | levine <levine@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1996-10-21 21:41:34 +0000 |
commit | a5fdebc5f6375078ec1763850a4ca23ec7fe6458 (patch) | |
tree | bcf0a25c3d45a209a6e3ac37b233a4812f29c732 /ace/Local_Tokens.h | |
download | ATCD-a5fdebc5f6375078ec1763850a4ca23ec7fe6458.tar.gz |
Initial revision
Diffstat (limited to 'ace/Local_Tokens.h')
-rw-r--r-- | ace/Local_Tokens.h | 974 |
1 files changed, 974 insertions, 0 deletions
diff --git a/ace/Local_Tokens.h b/ace/Local_Tokens.h new file mode 100644 index 00000000000..6d5786f2658 --- /dev/null +++ b/ace/Local_Tokens.h @@ -0,0 +1,974 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Local_Tokens +// +// = AUTHOR +// Karl-Heinz Dorn (kdorn@erlh.siemens.de) +// Douglas C. Schmidt (schmidt@cs.wustl.edu) +// Tim Harrison (harrison@cs.wustl.edu) +// +// = DESCRIPTION +// This file contains definitions for the following classes: +// +// public: +// 7. ACE_Token_Proxy +// 8. ACE_Null_Token : public ACE_Token_Proxy +// 9. ACE_Local_Mutex : public ACE_Token_Proxy +// *. ACE_Local_RLock : public ACE_Local_Mutex +// &. ACE_Local_WLock : public ACE_Local_Mutex +// private: +// 1. ACE_TOKEN_CONST +// 3. ACE_TPQ_Entry +// b. ACE_TSS_TPQ_Entry +// c. ACE_TPQ_Iterator +// 4. ACE_Token_Proxy_Queue +// 5. ACE_Tokens +// 6. ACE_Mutex_Token : public ACE_Tokens +// 12. ACE_RW_Token : public ACE_Tokens +// a. ACE_Token_Name +// +// ============================================================================ + +#if !defined (ACE_LOCAL_MUTEX_H) +#define ACE_LOCAL_MUTEX_H + +#include "ace/Synch.h" +#include "ace/Stack.h" +#include "ace/Synch_Options.h" +#include "ace/Map_Manager.h" + +// 1. +class ACE_Export ACE_TOKEN_CONST +{ + // = TITLE + // Not a public interface. + // + // = DESCRIPTION + // Constant definitions and typdefs for Token library. Mostly, + // this class is necessary to fight the compiler with order of + // declaration errors. +public: +#if defined (ACE_MT_SAFE) + // ACE platform supports some form of threading. + typedef ACE_Condition_Thread_Mutex COND_VAR; + typedef ACE_Thread_Mutex MUTEX; + typedef ACE_Thread_Mutex_Guard GUARD; +#else + typedef ACE_Null_Condition_Mutex COND_VAR; + typedef ACE_Null_Mutex MUTEX; + typedef ACE_Null_Mutex_Guard GUARD; +#endif /* ACE_HAS_THREADS */ +}; + +class ACE_Token_Proxy; + +// 3.. +class ACE_Export ACE_TPQ_Entry + // = TITLE + // Not a public interface. + // + // = DESCRIPTION + // Token Proxy Queue entry. + // Used in the ACE_Token_Proxy_Queue +{ +friend class ACE_Token_Manager; +public: + typedef void (*PTVF) (void *); + + ACE_TPQ_Entry (void); + // Null constructor. + + ACE_TPQ_Entry (const ACE_Token_Proxy *proxy, + const char *client_id); + // Construction. + + ACE_TPQ_Entry (const ACE_TPQ_Entry &rhs); + // Copy constructor. + + ~ACE_TPQ_Entry (void); + // Death. + + void operator= (const ACE_TPQ_Entry &rhs); + // Copy operator use by the queue. + + // = Set/get top of the queue. + ACE_Token_Proxy *proxy (void) const; + void proxy (ACE_Token_Proxy *); + + // = Delta/get nesting level of the entry. + int nesting_level (void) const; + void nesting_level (int delta); + + // = Set/get client_id of the entry. + const char *client_id (void) const; + void client_id (const char *); + + int equal_client_id (const char *id); + // Returns 1 if <id> == client id. Does not check for <id> == 0. + + void set (void (*sleep_hook)(void *)); + // One method for arg and sleep_hook. + + // = Set/get sleep hook of the entry. + void sleep_hook (void (*sh)(void *)); + PTVF sleep_hook (void) const; + + void call_sleep_hook (void); + // Call the sleep hook function or method passing arg. + + ACE_TPQ_Entry *next_; + // Pointer to next in list. + + void dump (void) const; + // Dump the state of the class. + + // = Used to block the thread if an acquire fails with EWOULDBLOCK. + ACE_TOKEN_CONST::MUTEX lock_; + ACE_TOKEN_CONST::COND_VAR cond_var_; + + // = Get/set whether this client is blocked waiting for a token. + int waiting (void) const; + void waiting (int w); + +private: + + int waiting_; + // This client is waiting for a token. + + ACE_Token_Proxy *proxy_; + // Proxy. + + int nesting_level_; + // Nesting level. + + void *arg_; + // Arg. + + char client_id_[ACE_MAXCLIENTIDLEN]; + // Client id. + + void (*sleep_hook_)(void *); + // Sleep hook. +}; + +// ************************************************************ + +// b.. +#if defined (ACE_NO_TSS_TOKENS) +typedef ACE_TPQ_Entry ACE_TPQ_ENTRY; +#else +typedef ACE_TSS<ACE_TPQ_Entry> ACE_TPQ_ENTRY; +#endif /* ACE_NO_TSS_TOKENS */ + +class ACE_Export ACE_TSS_TPQ_Entry : public ACE_TPQ_ENTRY + // = TITLE + // Not a public interface. + // = DESCRIPTION + // ACE_TSS_TPQ_Entry +{ +public: + ACE_TSS_TPQ_Entry (const ACE_Token_Proxy *proxy, + const char *client_id); + // These are passed to the constructor of ACE_TPQ_Entry in + // make_TSS_TYPE + + virtual ACE_TPQ_Entry *make_TSS_TYPE (void) const; + // Allows us to pass args to the construction of the TSS object. + + operator ACE_TPQ_Entry *(void); + // Operator overloading and inheritence don't mix. + + void dump (void) const; + // Dump the state of the class. + +#if defined (ACE_NO_TSS_TOKENS) + ACE_TSS_TPQ_Entry *operator-> (void) + { + return this; + } +#endif + +private: + // = These are passed to the constructor of ACE_TPQ_Entry in + // make_TSS_TYPE + const ACE_Token_Proxy *proxy_; + // Proxy. + const char *client_id_; + // Client_id. +}; + +// ************************************************************ + +class ACE_Token_Proxy_Queue; + +// c.. +class ACE_Export ACE_TPQ_Iterator + // = TITLE + // Not a public interface. + // + // = DESCRIPTION + // Iterates through ACE_Token_Proxy_Queues. +{ +public: + ACE_TPQ_Iterator (ACE_Token_Proxy_Queue &q); + // Construction. + + int next (ACE_TPQ_Entry *&next_item); + // Pass back the <next_item>. Returns 0 when all items have been + // seen, else 1. + + void advance (void); + // Move forward by one element in the queue. + + void dump (void) const; + // Dump the state of an object. + +private: + ACE_TPQ_Entry *current_; +}; + +// 4.. +class ACE_Export ACE_Token_Proxy_Queue + // = TITLE + // Not a public interface. + // + // = DESCRIPTION + // Token waiter list. + // This queue holds all the token proxies waiting for ownership of + // a token. Along with the proxy reference, it also stores the + // nesting level, client id, and a magic cookie from the proxy. + // This queue stores the ACE_TPQ_Entries by pointer values. It + // DOES NOT make copies. Thus, the user is responsible to ensure + // that the TPQ's stick around. This is motivated by the need to + // reduce dynamic memory allocation. +{ + friend class ACE_TPQ_Iterator; +public: + ACE_Token_Proxy_Queue (void); + // Construction. + + void enqueue (ACE_TPQ_Entry* new_entry, + int position); + // Enqueue a proxy, nesting level, client_id, and a magic cookie at + // the given position in the list. If the position is -1, we + // enqueue at the end of the list (I think). + + const ACE_TPQ_Entry* head (void); + // Top of the queue. + +// int member (const char *id); + // Is this id in the waiter list? + + void dequeue (void); + // Remove the top waiter. + + void remove (const ACE_TPQ_Entry *remove_me); + // Remove the waiter whose proxy ref matches remove_me. + + int size (void); + // The number of waiters. + + void dump (void) const; + // Dump the state of the class. + +protected: + ACE_TPQ_Entry *head_; + // Head. + ACE_TPQ_Entry *tail_; + // Tail. + int size_; + // Size. +}; + +// 5.. +class ACE_Export ACE_Tokens + // = TITLE + // Not a public interface. + // + // = DESCRIPTION + // Abstract representation of ACE tokens. + // Currently, I don't see a reason for providing an abstract + // interface at this level of the library. As of yet, no one uses + // ACE_Tokens derivatives through this abstract interface except + // for Token_Manager. It only uses the statistical methods which + // are shared by all Tokens. For that reason, it still makes + // since to have a common base class. However, acquire, renew, + // and release do not need to have matching interfaces throughout + // all Tokens. + + // = EXTENDING TOKENS + // To add a new type of token (e.g. semaphore), this class must be + // subtyped to define the new semantics. See ACE_Token_Manager + // for details. +{ +public: + + ACE_Tokens (void); + // Null constructor. + + virtual int acquire (ACE_TPQ_Entry *caller, + int ignore_deadlock, + int notify) = 0; + // No implementation. + + virtual int tryacquire (ACE_TPQ_Entry *caller) = 0; + // No implementation. + + virtual int renew (ACE_TPQ_Entry *caller, + int requeue_position) = 0; + // No implementation. + + virtual int release (ACE_TPQ_Entry *caller) = 0; + // No implementation. + + void make_owner (ACE_TPQ_Entry *caller); + // Move the caller to the front of the waiter list. This is for use + // with remote mutexes and shadow mutexes. + + void remove (ACE_TPQ_Entry *caller); + // Remove the caller from the waiter list. + + // = Accessor methods. + + typedef ACE_Unbounded_Stack<ACE_TPQ_Entry *> + OWNER_STACK; + // Stack of owners. + + virtual int owners (OWNER_STACK &o, const char *id) = 0; + // Returns a stack of the current owners. Returns -1 on error, 0 on + // success. If <id> is non-zero, returns 1 if id is an owner. + + virtual int is_waiting_for (const char *id) = 0; + // Returns 1 if <id> is waiting for this token. 0 otherwise. + + virtual int is_owner (const char *id) = 0; + // Returns 1 if <id> is an owner of this token. 0 otherwise. + + virtual ACE_Token_Proxy_Queue *waiters (void); + // Return the queue of waiters. + + virtual int no_of_waiters (void); + // Return the number of proxies that are currently waiting to get + // the token. + + const char *owner_id (void); + // The current owner. + + const char* name (void); + // Token name. + + // = Reference counting. These are only called by the + // Token_Manager. + void inc_reference (void); + int dec_reference (void); + + void dump (void) const; + // Dump the state of the class. + + enum TOKEN_TYPES { MUTEX, RWLOCK }; + // These are the Token types supported by the library at ship time. + // There is no restriction on the number of Token types added by + // "3rd parties." These are only necessary for the Token Server. + + virtual int type (void) const = 0; + // Provides a manual RTTI mechanism. This method is used only by + // ACE_Token_Request so that the type of a token can be sent to a + // remote Token Server. + + // = The following methods allow the deadlock detection algorithm to + // check if this token has been visited. + + void visit (int v); + // Mark or unmark the token as visited. + + int visited (void); + // Check if the token has been visited. + + ACE_TPQ_Entry *owner (void); + // All the data of the current owner. + +protected: + + int visited_; + // For the deadlock detection algorithm. + + int reference_count_; + // Reference count. + + ACE_Token_Proxy_Queue waiters_; + // List of client's owning and waiting the token. + + char token_name_[ACE_MAXTOKENNAMELEN]; + // Name of token. +}; + +class ACE_Local_Mutex; + +// 6.. +class ACE_Export ACE_Mutex_Token : public ACE_Tokens + // = TITLE + // Not a public interface. + // + // = DESCRIPTION + // Class that acquires, renews, and releases a process-local + // synchronization token. + // 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 (SunOS 5.x mutexes don't strictly + // enforce an acquisition order). +{ +public: + ACE_Mutex_Token (const char* name); + // life + + ~ACE_Mutex_Token (void); + // death + + // = Synchronization operations. + // With acquire, renew, and release, the caller must be specified so + // that multiple proxies (e.g. ACE_Local_Mutex) can use the same + // token. + + virtual int acquire (ACE_TPQ_Entry *caller, + int ignore_deadlock, + int notify); + // Returns 0 on success, -1 on failure with ACE_LOG_MSG->errnum() as + // the reason. If errnum == EWOULDBLOCK, and notify == 1, + // ACE_Token_Proxy::sleep_hook() has been called on the current owner + // of the token. If ignore_deadlock is passed as 1 and errnum == + // EDEADLK, then deadlock was detected via ace_token_manager. + + virtual int tryacquire (ACE_TPQ_Entry *caller); + // same as acquire, but fails if would block + + virtual int renew (ACE_TPQ_Entry *caller, + int requeue_position); + // 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 degrade 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... + // Returns 0 on success, -1 on failure with ACE_LOG_MSG->errnum() as + // the reason. If errnum == EWOULDBLOCK, and notify == 1, + // ACE_Token_Proxy::sleep_hook() has been called on the current owner + // of the token. + + virtual int release (ACE_TPQ_Entry *caller); + // Relinquish the token. If there are any waiters then the next one + // in line gets it. If the caller is not the owner, caller is + // removed from the waiter list. + + void dump (void) const; + // Dump the state of the class. + + virtual int type (void) const; + // Returns ACE_Tokens::MUTEX. + + virtual int owners (OWNER_STACK &o, const char *id); + // Returns a stack of the current owners. Returns -1 on error, 0 on + // success. If <id> is non-zero, returns 1 if id is an owner. + + virtual int is_waiting_for (const char *id); + // Returns 1 if <id> is waiting for this token. 0 otherwise. + + virtual int is_owner (const char *id); + // Returns 1 if <id> is an owner of this token. 0 otherwise. + +private: + ACE_TOKEN_CONST::MUTEX lock_; + // ACE_Mutex_Token used to lock internal data structures. +}; + +// 12.. +class ACE_Export ACE_RW_Token : public ACE_Tokens + // = TITLE + // Not a public interface. + // + // = DESCRIPTION + // Class that acquires, renews, and releases a process-local + // synchronization token. + // 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 (SunOS 5.x mutexes don't strictly + // enforce an acquisition order). +{ +public: + ACE_RW_Token (const char* name); + // Life. + + ~ACE_RW_Token (void); + // Death. + + // = Synchronization operations. + // With acquire, renew, and release, the caller must be specified so + // that multiple proxies (e.g. ACE_Local_Mutex) can use the same + // token. + + virtual int acquire (ACE_TPQ_Entry *caller, + int ignore_deadlock, + int notify); + // Returns 0 on success, -1 on failure with ACE_LOG_MSG->errnum() as + // the reason. If errnum == EWOULDBLOCK, and notify == 1, + // ACE_Token_Proxy::sleep_hook() has been called on the current owner + // of the token. If ignore_deadlock is passed as 1 and errnum == + // EDEADLK, then deadlock was detected via ace_token_manager. + + virtual int tryacquire (ACE_TPQ_Entry *caller); + // same as acquire except fails on would block + + virtual int renew (ACE_TPQ_Entry *caller, + int requeue_position); + // 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 degrade 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... + // Returns 0 on success, -1 on failure with ACE_LOG_MSG->errnum() as + // the reason. If errnum == EWOULDBLOCK, and notify == 1, + // ACE_Token_Proxy::sleep_hook() has been called on the current owner + // of the token. + + virtual int release (ACE_TPQ_Entry *caller); + // Relinquish the token. If there are any waiters then the next one + // in line gets it. If the caller is not the owner, caller is + // removed from the waiter list. + + void dump (void) const; + // Dump the state of the class. + + enum PROXY_TYPE { READER, WRITER }; + // These are the types that proxies can be. + + virtual int type (void) const; + // Returns READER or WRITER. + + virtual int owners (OWNER_STACK &o, const char *id); + // Returns a stack of the current owners. Returns -1 on error, 0 on + // success. If <id> is non-zero, returns 1 if id is an owner. + + virtual int is_waiting_for (const char *id); + // Returns 1 if <id> is waiting for this token. 0 otherwise. + + virtual int is_owner (const char *id); + // Returns 1 if <id> is an owner of this token. 0 otherwise. + +protected: + int num_writers_; + // the number of waiting writers. + + ACE_TOKEN_CONST::MUTEX lock_; + // ACE_Mutex_Token used to lock internal data structures. + + void notify_new_owner (ACE_TPQ_Entry *caller); + // Sets the new owner. +}; + +// a.. +class ACE_Token_Name + // = TITLE + // Allows Token_Manger to identify tokens. + // + // = DESCRIPTION + // For now, this is just a string. We need a string class anyway + // to use in ACE_Map_Manager. Having this class (instead of + // SString) allows us to easily change if needed. For instance, + // we may choose to identify tokens by name and *type* in the + // future. +{ +public: + ACE_Token_Name (const char *token_name = 0); + // Construction. + + ACE_Token_Name (const ACE_Token_Name &rhs); + // Copy construction. + + ~ACE_Token_Name (void); + // Death. + + void operator= (const ACE_Token_Name &rhs); + // Copy. + + int operator== (const ACE_Token_Name &rhs) const; + // Comparison. + + const char *name (void) const; + // Token name. + + void name (const char *new_name); + // Token name. + + void dump (void) const; + // Dump the state of the class. + +private: + char token_name_[ACE_MAXTOKENNAMELEN]; + // Name of the token. +}; + + +// 7.. +class ACE_Export ACE_Token_Proxy + // = TITLE + // Abstract representation of ACE tokens. + // + // = DESCRIPTION + // Interface for all Tokens in ACE. This class implements the + // synchronization needed for tokens (condition variables etc.) + // The algorithms for the operations (acquire, release, etc.) + // operate on the generic ACE_Tokens interface. Thus, the _type_ + // of token (mutex, rwlock) can be set at construction of + // ACE_Token_Proxy. You can use all Tokens in ACE through the + // ACE_Token_Proxy by passing the proper values at construction. + // Alternatively, there are class definitions which "know" how to + // do this (ACE_Local_Mutex, ACE_Local_RLock, ACE_Local_WLock). + + // = EXTENDING TOKENS + // To add a new type of token (e.g. semaphore), this class is not + // changed. See ACE_Token_Manager for details. + + // = RESTRICTIONS + // Tokens (e.g. ACE_Mutex_Token) assume that it can always call + // ACE_Token_Proxy::token_acquired () on a new token owner. This + // is not a problem for synchronous use of token proxies (that is, + // when acquires block until successful.) However, for + // implementations of the Token Server, which may use asynch + // operations, the proxy can not go away after an acquire until + // the token is acquired. This is not really a problem, but + // should be understood. +{ +friend class ACE_Token_Manager; +friend class ACE_Token_Invariant_Manager; // For testing. +public: + + // Initialization and termination methods. + ACE_Token_Proxy (void); + // Construction. + + ~ACE_Token_Proxy (void); + // Death. + + virtual int open (const char *name, + int ignore_deadlock = 0, + int debug = 0); + // <name> is the string uniquely identifying the token. + // <ignore_deadlock> can be 1 to disable deadlock notifications. + // <debug> prints debug messages. + + // = The following methods have implementations which are + // independent of the token semantics (mutex, rwlock, etc.) They + // forward operations to the underlying token and perform the + // necessary blocking semantics for operations (condition variables + // etc.) This allows reuse of the blocking code as well as having + // multiple proxies to the same token. + + virtual int acquire (int notify = 0, + void (*sleep_hook)(void *) = 0, + ACE_Synch_Options &options = + ACE_Synch_Options::defaults); + // Calls acquire on the token. Blocks the calling thread if would + // block. + + virtual int renew (int requeue_position = -1, + ACE_Synch_Options &options = + ACE_Synch_Options::defaults); + // Calls renew on the token. Blocks the calling thread if would + // block. + + virtual int tryacquire (void (*sleep_hook)(void *) = 0); + // Calls renew on the token. + + virtual int release (ACE_Synch_Options &options = + ACE_Synch_Options::defaults); + // Calls release on the token. + + virtual int remove (ACE_Synch_Options &options = + ACE_Synch_Options::defaults); + // Calls remove on the token. + + // = Utility methods. + + virtual const char *client_id (void) const; + // Get the client id of the proxy. This is implemented as + // thread-specific data. + + virtual void client_id (const char *client_id); + // Set the client_id for the calling thread. I strongly recommend + // that this not be used unless you really know what you're doing. + // I use this in the Token Server, and it caused many headaches. + + virtual const char *name (void) const; + // Return the name of the token. This is important for use within + // the token servers (local and remote) as well as with token + // collections. So, all derivations of ACE_Token_Proxy must be able to + // stringify some name. The name must uniquely identify a token. + // So, for instance, the token within the reactor should probably be + // called "Reactor Token." + + virtual void sleep_hook (void); + // This should really be called someone_waiting (). + // This is called by ACE_Token_xx's when another proxy enters the + // waiting list and requests that the current token holder be notified. + + virtual void token_acquired (ACE_TPQ_Entry *); + // This is called when a queued (waiting) proxy is removed from the + // waiters list and given the token. + + virtual const char *owner_id (void); + // the client id of the current token holder + + virtual ACE_Token_Proxy *clone (void) const = 0; + // Return a dynamically allocated clone of the derived class. + + void dump (void) const; + // Dump the state of the class. + + virtual int type (void) const; + // This method can be used be Tokens (e.g. Readers/Writer Tokens) to + // distinguish between Proxy types. For instance a Reader proxy + // should return a different type value than a Writer proxy. The + // default implementation returns 0. + +protected: + ACE_Token_Proxy (const ACE_Token_Proxy &); + // Duplication. + + int ignore_deadlock_; + // If this is set, we ignore deadlock. + + int debug_; + // Print a bunch of debug messages. + + ACE_Tokens *token_; + // Reference to the actual logical token. Many ACE_Local_Mutex + // proxies can reference the same ACE_Mutex_Token. + + int handle_options (ACE_Synch_Options &options, + ACE_TOKEN_CONST::COND_VAR &cv); + // Handles cond_var waits. + + ACE_TSS_TPQ_Entry waiter_; + // Waiter info used for asynchronous transactions. + + virtual ACE_Tokens *create_token (const char *name) = 0; + // Make the correct type of ACE_Tokens. This is called by the Token + // Manager. +}; + +// 8.. +class ACE_Export ACE_Null_Token : public ACE_Token_Proxy + // = TITLE + // No op class for nonthreaded platform protocols. +{ +public: + ACE_Null_Token (void) {}; + // Construction. + + virtual int acquire (int /* notify */ = 0, + void (* /* sleep_hook */ )(void *) = 0, + ACE_Synch_Options & /* options */ = + ACE_Synch_Options::defaults) { return 0; } + // Acquire. + + virtual int renew (int /* requeue_position */ = -1, + ACE_Synch_Options & /* options */ = + ACE_Synch_Options::defaults) { return 0; } + // Renew. + + virtual int tryacquire (void (* /* sleep_hook */)(void *) = 0) { return 0; } + // Try acquire. + + virtual int release (ACE_Synch_Options & /* options */ = + ACE_Synch_Options::defaults) { return 0; } + // Release. + + virtual int remove (ACE_Synch_Options & /* options */ = + ACE_Synch_Options::defaults) { return 0; } + // Remove. + + virtual ACE_Token_Proxy *clone (void) const { return new ACE_Null_Token; } + // Return a dynamically allocated clone of the derived class. + + void dump (void) const; + // Dump the state of the class. + + virtual ACE_Tokens *create_token (const char *) { return 0; } + // Do not allow the Token Manager to create us. +}; + +// 9.. +class ACE_Export ACE_Local_Mutex : public ACE_Token_Proxy + // = TITLE + // Class that acquires, renews, and releases a synchronization + // token local to the process. + // + // = 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 (SunOS 5.x mutexes + // don't strictly enforce an acquisition order). Lastly, + // ACE_Local_Mutex performs deadlock detection on acquire calls. + // + // = Synchronization operations. + // The interfaces for acquire, tryacquire, renew, release, + // etc. are defined in ACE_Token_Proxy. The semantics for + // ACE_Local_Mutex are that of a mutex. +{ +public: + ACE_Local_Mutex (const char *token_name = 0, + int ignore_deadlock = 0, + int debug = 0); + // <token_name> uniquely id's the token. + // <ignore_deadlock> will allow deadlock to occur (useful for + // testing). <debug> prints a bunch of messages. + + void dump (void) const; + // Dump the state of the class. + + virtual ACE_Token_Proxy *clone (void) const; + // Return deep copy. + +protected: + virtual ACE_Tokens *create_token (const char *name); + // Return a new ACE_Local_Mutex. +}; + +// *. +class ACE_Export ACE_Local_RLock : public ACE_Token_Proxy +// = TITLE +// Class that acquires, renews, and releases a readers lock that +// is local to the process. +// +// = DESCRIPTION +// This class implements the reader interface to canonical +// readers/writer locks. Multiple readers can hold the lock +// simultaneously when no writers have the lock. Alternatively, +// when a writer holds the lock, no other participants (readers or +// writers) may hold the lock. This class is a more +// general-purpose synchronization mechanism than SunOS 5.x RLocks. +// For example, it implements "recursive RLock" 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 +// (SunOS 5.x RLockes don't strictly enforce an acquisition +// order). +// +// = Synchronization operations. +// The interfaces for acquire, tryacquire, renew, release, etc. are +// defined in ACE_Token_Proxy. The semantics for ACE_Local_RLock +// are that of a readers/writers lock. Acquire for this class +// implies a reader acquisition. That is, multiple clients may +// acquire a lock for read only. +{ +public: + // = Initialization and termination. + + ACE_Local_RLock (const char *token_name = 0, + int ignore_deadlock = 0, + int debug = 0); + // <token_name> uniquely id's the token. + // <ignore_deadlock> will allow deadlock to occur (useful for + // testing). <debug> prints a bunch of messages. + + void dump (void) const; + // Dump the state of the class. + + virtual int type (void) const; + // Returns ACE_RW_Token::RLOCK. + + virtual ACE_Token_Proxy *clone (void) const; + // Return deep copy. + +protected: + virtual ACE_Tokens *create_token (const char *name); + // Return a new ACE_Local_Mutex. +}; + +// *. +class ACE_Export ACE_Local_WLock : public ACE_Token_Proxy +// = TITLE +// Class that acquires, renews, and releases a writer lock that +// is local to the process. +// +// = DESCRIPTION +// This class implements the writer interface to canonical +// readers/writer locks. Multiple readers can hold the lock +// simultaneously when no writers have the lock. Alternatively, +// when a writer holds the lock, no other participants (readers or +// writers) may hold the lock. This class is a more +// general-purpose synchronization mechanism than SunOS 5.x WLock. +// For example, it implements "recursive WLock" 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 +// (SunOS 5.x WLocks don't strictly enforce an acquisition order). +// +// = Synchronization operations. +// The interfaces for acquire, tryacquire, renew, release, +// etc. are defined in ACE_Token_Proxy. The semantics for +// ACE_Local_WLock are that of a readers/writers lock. Acquire +// for this class implies a writer acquisition. That is, only one +// client may hold the lock for writing. +{ +public: + // = Initialization and termination. + + ACE_Local_WLock (const char *token_name = 0, + int ignore_deadlock = 0, + int debug = 0); + // <token_name> uniquely id's the token. + // <ignore_deadlock> will allow deadlock to occur (useful for + // testing). <debug> prints a bunch of messages. + + void dump (void) const; + // Dump the state of the class. + + virtual int type (void) const; + // Returns ACE_RW_Token::WLOCK. + + virtual ACE_Token_Proxy *clone (void) const; + // Return deep copy. + +protected: + ACE_Tokens *create_token (const char *name); + // Return a new ACE_Local_Mutex. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Local_Tokens.i" +#endif /* __ACE_INLINE__ */ +#endif /* ACE_LOCAL_MUTEX_H */ |