/* -*- C++ -*- */
// $Id: Local_Tokens.h,v 4.28 1999/04/02 01:55:55 othman Exp $

// ============================================================================
//
// = LIBRARY
//    ace
//
// = FILENAME
//    Local_Tokens.h
//
// = 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
//
// ============================================================================

#ifndef ACE_LOCAL_MUTEX_H
#define ACE_LOCAL_MUTEX_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"

// 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<ACE_Thread_Mutex> GUARD;
#else
  typedef ACE_Null_Condition COND_VAR;
  typedef ACE_Null_Mutex MUTEX;
  typedef ACE_Guard<ACE_Null_Mutex> 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 ASYS_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 ASYS_TCHAR *client_id (void) const;
  void client_id (const ASYS_TCHAR *);

  int equal_client_id (const ASYS_TCHAR *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.

  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.

  ASYS_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> 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 ASYS_TCHAR *client_id);
  // These are passed to the constructor of ACE_TPQ_Entry in
  // make_TSS_TYPE

  ~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_TSS_TPQ_Entry *operator-> (void)
    {
      return 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 ASYS_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 <next_item>.

  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 ASYS_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 <ACE_Tokens< derivatives through this abstract interface
  //     except for <ACE_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.
  //
  //     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 ~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<ACE_TPQ_Entry *> OWNER_STACK;
  // Stack of owners.

  virtual int owners (OWNER_STACK &o, const ASYS_TCHAR *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 ASYS_TCHAR *id) = 0;
  // Returns 1 if <id> is waiting for this token.  0 otherwise.

  virtual int is_owner (const ASYS_TCHAR *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 ASYS_TCHAR *owner_id (void);
  // The current owner.

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

  ASYS_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_Mutex_Token (const ASYS_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 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 ASYS_TCHAR *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 ASYS_TCHAR *id);
  // Returns 1 if <id> is waiting for this token.  0 otherwise.

  virtual int is_owner (const ASYS_TCHAR *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
  //    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_RW_Token (const ASYS_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 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 ASYS_TCHAR *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 ASYS_TCHAR *id);
  // Returns 1 if <id> is waiting for this token.  0 otherwise.

  virtual int is_owner (const ASYS_TCHAR *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_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 <ACE_Map_Manager>.  Having this class
  //     (instead of <ACE_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 ASYS_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 ASYS_TCHAR *name (void) const;
  // Token name.

  void name (const ASYS_TCHAR *new_name);
  // Token name.

  void dump (void) const;
  // Dump the state of the class.

private:
  ASYS_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
  //   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.
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 ASYS_TCHAR *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.

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

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

  virtual int tryacquire_read (void (*sleep_hook)(void *) = 0);
  // Since the locking mechanism doesn't support read locks then this
  // just calls <tryacquire>.

  virtual int tryacquire_write (void (*sleep_hook)(void *) = 0);
  // Since the locking mechanism doesn't support write locks then this
  // just calls <tryacquire>.

  // = Utility methods.

  virtual const ASYS_TCHAR *client_id (void) const;
  // Get the client id of the proxy.  This is implemented as
  // thread-specific data.

  virtual void client_id (const ASYS_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 ASYS_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 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 ASYS_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 ASYS_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 ASYS_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 ASYS_TCHAR *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.

  ~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 ASYS_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 ASYS_TCHAR *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.

  ~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 ASYS_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 ASYS_TCHAR *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.

  ~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 ASYS_TCHAR *name);
  // Return a new ACE_Local_Mutex.
};

#if defined (__ACE_INLINE__)
#include "ace/Local_Tokens.i"
#endif /* __ACE_INLINE__ */
#endif /* ACE_LOCAL_MUTEX_H */
