ACE_Token_Manager Class Reference

Manages all tokens in a process space. More...

#include <Token_Manager.h>

Inheritance diagram for ACE_Token_Manager:

Inheritance graph
[legend]
Collaboration diagram for ACE_Token_Manager:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 ACE_Token_Manager (void)
virtual ~ACE_Token_Manager (void)
void instance (ACE_Token_Manager *)
 Set the pointer to token manager singleton.

void get_token (ACE_Token_Proxy *, const ACE_TCHAR *token_name)
int check_deadlock (ACE_Token_Proxy *proxy)
int check_deadlock (ACE_Tokens *token, ACE_Token_Proxy *proxy)
void release_token (ACE_Tokens *&token)
ACE_TOKEN_CONST::MUTEXmutex (void)
void dump (void) const
 Dump the state of the class.

void debug (int d)
 Turn debug mode on/off.


Static Public Member Functions

ACE_Token_Managerinstance (void)
 Get the pointer to token manager singleton.


Private Types

typedef ACE_Token_Name TOKEN_NAME
 This may be changed to a template type.

typedef ACE_Map_Manager< TOKEN_NAME,
ACE_Tokens *, ACE_Null_Mutex
COLLECTION
 COLLECTION maintains a mapping from token names to ACE_Tokens*.

typedef COLLECTION::ITERATOR COLLECTION_ITERATOR
 Allows iterations through collection_.

typedef COLLECTION::ENTRY COLLECTION_ENTRY
 Allows iterations through collection_.


Private Member Functions

ACE_Tokenstoken_waiting_for (const ACE_TCHAR *client_id)
 Return the token that the given client_id is waiting for, if any.


Private Attributes

int debug_
 Whether to print debug messages or not.

ACE_TOKEN_CONST::MUTEX lock_
 ACE_Mutex_Token used to lock internal data structures.

COLLECTION collection_
 COLLECTION maintains a mapping from token names to ACE_Tokens*.


Static Private Attributes

ACE_Token_Managertoken_manager_ = 0
 pointer to singleton token manager.


Detailed Description

Manages all tokens in a process space.

Factory: Proxies use the token manager to obtain token references. This allows multiple proxies to reference the same logical token. Deadlock detection: Tokens use the manager to check for deadlock situations during acquires.

Definition at line 46 of file Token_Manager.h.


Member Typedef Documentation

typedef ACE_Map_Manager<TOKEN_NAME, ACE_Tokens *, ACE_Null_Mutex> ACE_Token_Manager::COLLECTION [private]
 

COLLECTION maintains a mapping from token names to ACE_Tokens*.

Definition at line 121 of file Token_Manager.h.

typedef COLLECTION::ENTRY ACE_Token_Manager::COLLECTION_ENTRY [private]
 

Allows iterations through collection_.

Deprecated:
Deprecated typedef. Use COLLECTION::ENTRY trait instead.

Definition at line 135 of file Token_Manager.h.

typedef COLLECTION::ITERATOR ACE_Token_Manager::COLLECTION_ITERATOR [private]
 

Allows iterations through collection_.

Deprecated:
Deprecated typedef. Use COLLECTION::ITERATOR trait instead.

Definition at line 128 of file Token_Manager.h.

typedef ACE_Token_Name ACE_Token_Manager::TOKEN_NAME [private]
 

This may be changed to a template type.

Definition at line 117 of file Token_Manager.h.


Constructor & Destructor Documentation

ACE_Token_Manager::ACE_Token_Manager void   ) 
 

Definition at line 20 of file Token_Manager.cpp.

References ACE_TRACE.

00021 {
00022   ACE_TRACE ("ACE_Token_Manager::ACE_Token_Manager");
00023 }

ACE_Token_Manager::~ACE_Token_Manager void   )  [virtual]
 

Definition at line 25 of file Token_Manager.cpp.

References ACE_TRACE.

00026 {
00027   ACE_TRACE ("ACE_Token_Manager::~ACE_Token_Manager");
00028 
00029   COLLECTION::ITERATOR iterator (collection_);
00030 
00031   for (COLLECTION::ENTRY *temp = 0;
00032        iterator.next (temp) != 0;
00033        iterator.advance ())
00034     {
00035       // @ should I be doing an unbind here?
00036       delete temp->int_id_;
00037       // The ext_id_'s delete themselves when the array of
00038       // COLLECTION::ENTRYs goes away.
00039     }
00040 }


Member Function Documentation

int ACE_Token_Manager::check_deadlock ACE_Tokens token,
ACE_Token_Proxy proxy
 

Definition at line 135 of file Token_Manager.cpp.

References ACE_DEBUG, ACE_LIB_TEXT, ACE_TRACE, check_deadlock(), ACE_TPQ_Entry::client_id(), ACE_Token_Proxy::client_id(), ACE_Unbounded_Stack< T >::is_empty(), LM_DEBUG, ACE_Tokens::name(), ACE_Tokens::OWNER_STACK, ACE_Tokens::owners(), ACE_Unbounded_Stack< T >::pop(), ACE_Token_Proxy::token_, token_waiting_for(), ACE_Tokens::visit(), and ACE_Tokens::visited().

00136 {
00137   ACE_TRACE ("ACE_Token_Manager::check_deadlock");
00138 
00139   if (token->visited ())
00140     return 0;
00141 
00142   token->visit (1);
00143 
00144   ACE_Tokens::OWNER_STACK owners;
00145 
00146   int is_owner = token->owners (owners, proxy->client_id ());
00147 
00148   switch (is_owner)
00149     {
00150     case -1:
00151       // Error.
00152       return -1;
00153     case 1:
00154       // The caller is an owner, so we have a deadlock situation.
00155       if (debug_)
00156         {
00157           ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("(%t) Deadlock detected.\n")));
00158           ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("%s owns %s and is waiting for %s.\n"),
00159                       proxy->client_id (),
00160                       token->name (),
00161                       proxy->token_->name ()));
00162         }
00163 
00164       return 1;
00165     case 0:
00166     default:
00167       // Recurse on each owner.
00168       while (!owners.is_empty ())
00169         {
00170           ACE_TPQ_Entry *e;
00171           owners.pop (e);
00172           // If the owner is waiting on another token, recurse.
00173           ACE_Tokens *twf = this->token_waiting_for (e->client_id ());
00174           if ((twf != 0) &&
00175               (this->check_deadlock (twf, proxy) == 1))
00176             {
00177               if (debug_)
00178                 {
00179                   ACE_DEBUG ((LM_DEBUG,
00180                               ACE_LIB_TEXT ("%s owns %s and is waiting for %s.\n"),
00181                               e->client_id (),
00182                               token->name (),
00183                               twf->name ()));
00184                 }
00185               return 1;
00186             }
00187           // else, check the next owner.
00188         }
00189 
00190       // We've checked all the owners and found no deadlock.
00191       return 0;
00192     }
00193 }

int ACE_Token_Manager::check_deadlock ACE_Token_Proxy proxy  ) 
 

Check whether acquire will cause deadlock or not. returns 1 if the acquire will _not_ cause deadlock. returns 0 if the acquire _will_ cause deadlock. This method ignores recursive acquisition. That is, it will not report deadlock if the client holding the token requests the token again. Thus, it assumes recursive mutexes.

Definition at line 116 of file Token_Manager.cpp.

References ACE_TRACE, and ACE_Token_Proxy::token_.

Referenced by ACE_RW_Token::acquire(), ACE_Mutex_Token::acquire(), and check_deadlock().

00117 {
00118   ACE_TRACE ("ACE_Token_Manager::check_deadlock");
00119 
00120   // Start the recursive deadlock detection algorithm.
00121   int result = this->check_deadlock (proxy->token_, proxy);
00122 
00123   // Whether or not we detect deadlock, we have to unmark all tokens
00124   // for the next time.
00125   COLLECTION::ITERATOR iterator (collection_);
00126   for (COLLECTION::ENTRY *temp = 0;
00127        iterator.next (temp) != 0;
00128        iterator.advance ())
00129       temp->int_id_->visit (0);
00130 
00131   return result;
00132 }

void ACE_Token_Manager::debug int  d  ) 
 

Turn debug mode on/off.

void ACE_Token_Manager::dump void   )  const
 

Dump the state of the class.

Definition at line 257 of file Token_Manager.cpp.

References ACE_BEGIN_DUMP, ACE_DEBUG, ACE_END_DUMP, ACE_LIB_TEXT, ACE_TRACE, ACE_Null_Mutex::dump(), and LM_DEBUG.

00258 {
00259 #if defined (ACE_HAS_DUMP)
00260   ACE_TRACE ("ACE_Token_Manager::dump");
00261   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00262   ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("ACE_Token_Manager::dump:\n")));
00263   ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("lock_\n")));
00264   lock_.dump ();
00265   ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("collection_\n")));
00266   collection_.dump ();
00267   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00268 #endif /* ACE_HAS_DUMP */
00269 }

void ACE_Token_Manager::get_token ACE_Token_Proxy ,
const ACE_TCHAR token_name
 

The Token manager uses ACE_Token_Proxy::token_id_ to look for an existing token. If none is found, the Token Manager calls ACE_Token_Proxy::create_token to create a new one. When finished, sets ACE_Token_Proxy::token_. token_name uniquely id's the token name.

Definition at line 72 of file Token_Manager.cpp.

References ACE_GUARD, ACE_TCHAR, ACE_TRACE, ACE_Token_Proxy::create_token(), ACE_Tokens::inc_reference(), ACE_TOKEN_CONST::MUTEX, and ACE_Token_Proxy::token_.

Referenced by ACE_Token_Proxy::open().

00074 {
00075   ACE_TRACE ("ACE_Token_Manager::get_token");
00076   // Hmm.  I think this makes sense.  We perform our own locking here
00077   // (see safe_acquire.)  We have to make sure that only one thread
00078   // uses the collection at a time.
00079 
00080   ACE_GUARD (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_);
00081 
00082   TOKEN_NAME name (token_name);
00083 
00084   if (collection_.find (name, proxy->token_) == -1)
00085     // We did not find one in the collection.
00086     {
00087       // Make one.
00088       proxy->token_ = proxy->create_token (token_name);
00089 
00090       // Put it in the collection.
00091       if (collection_.bind (name, proxy->token_) == -1)
00092         {
00093           delete proxy->token_;
00094           proxy->token_ = 0;
00095         }
00096     }
00097 
00098   if (proxy->token_ != 0)
00099     proxy->token_->inc_reference ();
00100 
00101   // We may be returning proxy->token_ == 0 if new failed, caller must
00102   // check.
00103 }

void ACE_Token_Manager::instance ACE_Token_Manager  ) 
 

Set the pointer to token manager singleton.

ACE_Token_Manager * ACE_Token_Manager::instance void   )  [static]
 

Get the pointer to token manager singleton.

Definition at line 43 of file Token_Manager.cpp.

References ACE_GUARD_RETURN, ACE_NEW_RETURN, ACE_TRACE, ACE_Object_Manager::at_exit(), ACE_TOKEN_CONST::MUTEX, and token_manager_.

Referenced by ACE_RW_Token::acquire(), ACE_Mutex_Token::acquire(), ACE_Token_Proxy::open(), and ACE_Token_Proxy::~ACE_Token_Proxy().

00044 {
00045   ACE_TRACE ("ACE_Token_Manager::instance");
00046 
00047   // This first check is to avoid acquiring the mutex in the common
00048   // case.  Double-Check pattern rules.
00049   if (token_manager_ == 0)
00050     {
00051 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
00052       ACE_TOKEN_CONST::MUTEX *lock =
00053         ACE_Managed_Object<ACE_TOKEN_CONST::MUTEX>::get_preallocated_object
00054           (ACE_Object_Manager::ACE_TOKEN_MANAGER_CREATION_LOCK);
00055       ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, *lock, 0);
00056 #endif /* ACE_MT_SAFE */
00057 
00058       if (token_manager_ == 0)
00059         {
00060           ACE_NEW_RETURN (token_manager_,
00061                           ACE_Token_Manager,
00062                           0);
00063           // Register for destruction with ACE_Object_Manager.
00064           ACE_Object_Manager::at_exit (token_manager_);
00065         }
00066     }
00067 
00068   return token_manager_;
00069 }

ACE_TOKEN_CONST::MUTEX& ACE_Token_Manager::mutex void   ) 
 

This is to allow Tokens to perform atomic transactions. The typical usage is to acquire this mutex, check for a safe_acquire, perform some queueing (if need be) and then release the lock. This is necessary since safe_acquire is implemented in terms of the Token queues.

void ACE_Token_Manager::release_token ACE_Tokens *&  token  ) 
 

Notify the token manager that a token has been released. If as a result, there is no owner of the token, the token is deleted.

Definition at line 216 of file Token_Manager.cpp.

References ACE_ASSERT, ACE_ERROR, ACE_GUARD, ACE_LIB_TEXT, ACE_TRACE, ACE_Tokens::dec_reference(), LM_ERROR, ACE_TOKEN_CONST::MUTEX, ACE_Tokens::name(), and ACE_Tokens::type().

Referenced by ACE_Token_Proxy::~ACE_Token_Proxy().

00217 {
00218   ACE_TRACE ("ACE_Token_Manager::release_token");
00219   // again, let's perform our own locking here.
00220 
00221   ACE_GUARD (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_);
00222 
00223   if (token->dec_reference () == 0)
00224     {
00225       // No one has the token, so we can delete it and remove it from
00226       // our collection.  First, let's get it from the collection.
00227       TOKEN_NAME token_name (token->name ());
00228 
00229       ACE_Tokens *temp;
00230 
00231       if (collection_.unbind (token_name, temp) == -1)
00232         // we did not find one in the collection
00233         {
00234           errno = ENOENT;
00235           ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("Token Manager could not release %s:%d\n"),
00236                       token->name (), token->type ()));
00237           // @@ bad
00238         }
00239       else
00240         // we found it
00241         {
00242           // sanity pointer comparison.  The token referenced by the
00243           // proxy better be the one we found in the list.
00244           ACE_ASSERT (token == temp);
00245           delete token;  // or delete temp
00246           // we set their token to zero.  if the calling proxy is
00247           // still going to be used, it had better check it's token
00248           // value before calling a method on it!
00249           token = 0;
00250         }
00251     }
00252   // else
00253   // someone is still interested in the token, so keep it around.
00254 }

ACE_Tokens * ACE_Token_Manager::token_waiting_for const ACE_TCHAR client_id  )  [private]
 

Return the token that the given client_id is waiting for, if any.

Definition at line 197 of file Token_Manager.cpp.

References ACE_TCHAR.

Referenced by check_deadlock().

00198 {
00199   COLLECTION::ITERATOR iterator (collection_);
00200   for (COLLECTION::ENTRY *temp = 0;
00201        iterator.next (temp) != 0;
00202        iterator.advance ())
00203     {
00204       if (temp->int_id_->is_waiting_for (client_id))
00205         return temp->int_id_;
00206     }
00207 
00208   // nothing was found, return NULL.
00209   return 0;
00210 }


Member Data Documentation

COLLECTION ACE_Token_Manager::collection_ [private]
 

COLLECTION maintains a mapping from token names to ACE_Tokens*.

Definition at line 138 of file Token_Manager.h.

int ACE_Token_Manager::debug_ [private]
 

Whether to print debug messages or not.

Definition at line 105 of file Token_Manager.h.

ACE_TOKEN_CONST::MUTEX ACE_Token_Manager::lock_ [private]
 

ACE_Mutex_Token used to lock internal data structures.

Definition at line 114 of file Token_Manager.h.

ACE_BEGIN_VERSIONED_NAMESPACE_DECL ACE_Token_Manager * ACE_Token_Manager::token_manager_ = 0 [static, private]
 

pointer to singleton token manager.

Definition at line 18 of file Token_Manager.cpp.

Referenced by instance().


The documentation for this class was generated from the following files:
Generated on Thu Nov 9 11:31:46 2006 for ACE by doxygen 1.3.6