/* -*- C++ -*- */ // $Id$ // ============================================================================ // // = LIBRARY // ace // // = FILENAME // Local_Tokens.h // // = AUTHOR // Karl-Heinz Dorn , // Douglas C. Schmidt , and // Tim Harrison // // = 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 // // Note that the locking classes defined in this file are *not* // intended to be used as general-purpose synchronization // mechanisms, such as mutexes or semaphores. Instead, you should // use the , , // , etc., that are defined in // $ACE_ROOT/ace/Synch.h and $ACE_ROOT/ace/Synch_T.h or the // that's defined in $ACE_ROOT/ace/Token.h. // // ============================================================================ #ifndef ACE_LOCAL_MUTEX_H #define ACE_LOCAL_MUTEX_H #include "ace/pre.h" #include "ace/Synch_T.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "ace/Containers.h" #include "ace/Synch_Options.h" #include "ace/Map_Manager.h" #include "ace/Log_Msg.h" #if !(defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)) # define ACE_NO_TSS_TOKENS 1 #endif /* !(defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)) */ // 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_MT_SAFE != 0) // ACE platform supports some form of threading. typedef ACE_Condition_Thread_Mutex COND_VAR; typedef ACE_Thread_Mutex MUTEX; typedef ACE_Guard GUARD; #else typedef ACE_Null_Condition COND_VAR; typedef ACE_Null_Mutex MUTEX; typedef ACE_Guard GUARD; #endif /* ACE_HAS_THREADS */ }; // Forward decl. class ACE_Token_Proxy; // 3.. class ACE_Export ACE_TPQ_Entry { // = TITLE // Token Proxy Queue entry. Used in the ACE_Token_Proxy_Queue // // = DESCRIPTION // Not a public interface. 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 ACE_TCHAR *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 ACE_TCHAR *client_id (void) const; void client_id (const ACE_TCHAR *); int equal_client_id (const ACE_TCHAR *id); // Returns 1 if == client id. Does not check for == 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. void dump (void) const; // Dump the state of the class. // = Used to block the thread if an acquire fails with EWOULDBLOCK. ACE_TOKEN_CONST::COND_VAR cond_var_; ACE_TOKEN_CONST::MUTEX lock_; ACE_TPQ_Entry *next_; // Pointer to next in list. // = 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. ACE_TCHAR 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; #endif /* ACE_NO_TSS_TOKENS */ class ACE_Export ACE_TSS_TPQ_Entry : public ACE_TPQ_ENTRY { // = TITLE // ACE_TSS_TPQ_Entry // // = DESCRIPTION // Not a public interface. public: ACE_TSS_TPQ_Entry (const ACE_Token_Proxy *proxy, const ACE_TCHAR *client_id); // These are passed to the constructor of ACE_TPQ_Entry in // make_TSS_TYPE virtual ~ACE_TSS_TPQ_Entry (void); // Destructor. 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_TPQ_Entry *operator-> (void) { return (ACE_TPQ_Entry *) this; } #endif /* ACE_NO_TSS_TOKENS */ private: ACE_TSS_TPQ_Entry (const ACE_TSS_TPQ_Entry &); void operator= (const ACE_TSS_TPQ_Entry &); // Private: should not be used // = These are passed to the constructor of ACE_TPQ_Entry in // make_TSS_TYPE const ACE_Token_Proxy *proxy_; // Proxy. const ACE_TCHAR *client_id_; // Client_id. }; class ACE_Token_Proxy_Queue; // c.. class ACE_Export ACE_TPQ_Iterator { // = TITLE // Iterates through ACE_Token_Proxy_Queues. // // = DESCRIPTION // Not a public interface. public: ACE_TPQ_Iterator (ACE_Token_Proxy_Queue &q); // Construction. ~ACE_TPQ_Iterator (void); // Destructor. int next (ACE_TPQ_Entry *&next_item); // Pass back the . int done (void) const; // Returns 1 when all items have been seen, else 0. 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 // Token waiter list. // // = DESCRIPTION // Not a public interface. // // 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. public: friend class ACE_TPQ_Iterator; ACE_Token_Proxy_Queue (void); // Construction. ~ACE_Token_Proxy_Queue (void); // Destructor 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 ACE_TCHAR *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 // Abstract representation of ACE tokens. // // = DESCRIPTION // Not a public interface. // // Currently, I don't see a reason for providing an abstract // interface at this level of the library. As of yet, no one // uses . 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. // // To add a new type of token (e.g. semaphore), this class must // be subtyped to define the new semantics. See // for details. public: ACE_Tokens (void); // Null constructor. virtual ~ACE_Tokens (void); // Destructor 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 OWNER_STACK; // Stack of owners. virtual int owners (OWNER_STACK &o, const ACE_TCHAR *id) = 0; // Returns a stack of the current owners. Returns -1 on error, 0 on // success. If is non-zero, returns 1 if id is an owner. virtual int is_waiting_for (const ACE_TCHAR *id) = 0; // Returns 1 if is waiting for this token. 0 otherwise. virtual int is_owner (const ACE_TCHAR *id) = 0; // Returns 1 if 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 ACE_TCHAR *owner_id (void); // The current owner. const ACE_TCHAR* 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. ACE_TCHAR token_name_[ACE_MAXTOKENNAMELEN]; // Name of token. }; class ACE_Local_Mutex; // 6.. class ACE_Export ACE_Mutex_Token : public ACE_Tokens { // = TITLE // Class that acquires, renews, and releases a process-local // synchronization token. // // = DESCRIPTION // Not a public interface. // // 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_EXPLICIT ACE_Mutex_Token (const ACE_TCHAR* name); // life virtual ~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 as // the reason. If errnum == EWOULDBLOCK, and notify == 1, // 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 == // -1 and there are other threads waiting to obtain the token we are // queued at the end of the list of waiters. If // > -1 then it indicates how many entries to skip over before // inserting our thread into the list of waiters (e.g., // == 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 as the reason. // If errnum == EWOULDBLOCK, and notify == 1, // 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 ACE_TCHAR *id); // Returns a stack of the current owners. Returns -1 on error, 0 on // success. If is non-zero, returns 1 if id is an owner. virtual int is_waiting_for (const ACE_TCHAR *id); // Returns 1 if is waiting for this token. 0 otherwise. virtual int is_owner (const ACE_TCHAR *id); // Returns 1 if 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 // Class that acquires, renews, and releases a process-local // synchronization token. // // = DESCRIPTION // Not a public interface. // // 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_EXPLICIT ACE_RW_Token (const ACE_TCHAR* name); // Life. virtual ~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 as // the reason. If errnum == EWOULDBLOCK, and notify == 1, // 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 == // -1 and there are other threads waiting to obtain the token we are // queued at the end of the list of waiters. If // > -1 then it indicates how many entries to skip over before // inserting our thread into the list of waiters (e.g., // == 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 as the reason. // If errnum == EWOULDBLOCK, and notify == 1, // 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 ACE_TCHAR *id); // Returns a stack of the current owners. Returns -1 on error, 0 on // success. If is non-zero, returns 1 if id is an owner. virtual int is_waiting_for (const ACE_TCHAR *id); // Returns 1 if is waiting for this token. 0 otherwise. virtual int is_owner (const ACE_TCHAR *id); // Returns 1 if 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_Export 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 . Having this class // (instead of ) 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 ACE_TCHAR *token_name = 0); // Construction. ACE_Token_Name (const ACE_Token_Name &rhs); // Copy construction. virtual ~ACE_Token_Name (void); // Death. void operator= (const ACE_Token_Name &rhs); // Copy. int operator== (const ACE_Token_Name &rhs) const; // Comparison. const ACE_TCHAR *name (void) const; // Token name. void name (const ACE_TCHAR *new_name); // Token name. void dump (void) const; // Dump the state of the class. private: ACE_TCHAR 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). // // To add a new type of token (e.g. semaphore), this class is not // changed. See ACE_Token_Manager for details. // // Tokens (e.g. ACE_Mutex_Token) assume that it can always call // 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. public: friend class ACE_Token_Manager; friend class ACE_Token_Invariant_Manager; // For testing. // Initialization and termination methods. ACE_Token_Proxy (void); // Construction. virtual ~ACE_Token_Proxy (void); // Death. virtual int open (const ACE_TCHAR *name, int ignore_deadlock = 0, int debug = 0); // is the string uniquely identifying the token. // can be 1 to disable deadlock notifications. // 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. virtual int acquire_read (int notify = 0, void (*sleep_hook)(void *) = 0, ACE_Synch_Options &options = ACE_Synch_Options::defaults); // Since the locking mechanism doesn't support read locks then this // just calls . virtual int acquire_write (int notify = 0, void (*sleep_hook)(void *) = 0, ACE_Synch_Options &options = ACE_Synch_Options::defaults); // Since the locking mechanism doesn't support write locks then this // just calls . virtual int tryacquire_read (void (*sleep_hook)(void *) = 0); // Since the locking mechanism doesn't support read locks then this // just calls . virtual int tryacquire_write (void (*sleep_hook)(void *) = 0); // Since the locking mechanism doesn't support write locks then this // just calls . // = Utility methods. virtual const ACE_TCHAR *client_id (void) const; // Get the client id of the proxy. This is implemented as // thread-specific data. virtual void client_id (const ACE_TCHAR *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 ACE_TCHAR *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 . 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 ACE_TCHAR *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 ACE_TCHAR *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: #if defined (ACE_LACKS_INLINE_FUNCTIONS) // @@ Hopefully, we can remove this ridicules ifdef when CE's compiler becomes more normal. ACE_Null_Token (void); // Construction. ~ACE_Null_Token (void); // Destructor #endif /* ACE_LACKS_INLINE_FUNCTION */ 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 ACE_TCHAR *) { 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. // // 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 ACE_TCHAR *token_name = 0, int ignore_deadlock = 0, int debug = 0); // uniquely id's the token. // will allow deadlock to occur (useful for // testing). prints a bunch of messages. ~ACE_Local_Mutex (void); // Destructor 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 ACE_TCHAR *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). // // 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 ACE_TCHAR *token_name = 0, int ignore_deadlock = 0, int debug = 0); // uniquely id's the token. // will allow deadlock to occur (useful for // testing). prints a bunch of messages. ~ACE_Local_RLock (void); // Destructor 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 ACE_TCHAR *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). // // 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 ACE_TCHAR *token_name = 0, int ignore_deadlock = 0, int debug = 0); // uniquely id's the token. // will allow deadlock to occur (useful for // testing). prints a bunch of messages. ~ACE_Local_WLock (void); // Destructor 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 ACE_TCHAR *name); // Return a new ACE_Local_Mutex. }; #if defined (__ACE_INLINE__) #include "ace/Local_Tokens.i" #endif /* __ACE_INLINE__ */ #include "ace/post.h" #endif /* ACE_LOCAL_MUTEX_H */