#include <Token_Manager.h>
Inheritance diagram for ACE_Token_Manager:


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::MUTEX & | mutex (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_Manager * | instance (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_Tokens * | token_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_Manager * | token_manager_ = 0 | 
| pointer to singleton token manager.   | |
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.
      
  | 
  
| 
 COLLECTION maintains a mapping from token names to ACE_Tokens*. 
 Definition at line 121 of file Token_Manager.h.  | 
  
      
  | 
  
| 
 Allows iterations through collection_. 
 
 Definition at line 135 of file Token_Manager.h.  | 
  
      
  | 
  
| 
 Allows iterations through collection_. 
 
 Definition at line 128 of file Token_Manager.h.  | 
  
      
  | 
  
| 
 This may be changed to a template type. 
 Definition at line 117 of file Token_Manager.h.  | 
  
      
  | 
  
| 
 
 Definition at line 20 of file Token_Manager.cpp. References ACE_TRACE. 
 00021 {
00022   ACE_TRACE ("ACE_Token_Manager::ACE_Token_Manager");
00023 }
 | 
  
      
  | 
  
| 
 
 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 }
 | 
  
      
  | 
  ||||||||||||
| 
 
 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 }
 | 
  
      
  | 
  
| 
 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 }
 | 
  
      
  | 
  
| 
 Turn debug mode on/off. 
  | 
  
      
  | 
  
| 
 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 }
 | 
  
      
  | 
  ||||||||||||
| 
 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 }
 | 
  
      
  | 
  
| 
 Set the pointer to token manager singleton. 
  | 
  
      
  | 
  
| 
 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 }
 | 
  
      
  | 
  
| 
 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.  | 
  
      
  | 
  
| 
 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 }
 | 
  
      
  | 
  
| 
 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 }
 | 
  
      
  | 
  
| 
 COLLECTION maintains a mapping from token names to ACE_Tokens*. 
 Definition at line 138 of file Token_Manager.h.  | 
  
      
  | 
  
| 
 Whether to print debug messages or not. 
 Definition at line 105 of file Token_Manager.h.  | 
  
      
  | 
  
| 
 ACE_Mutex_Token used to lock internal data structures. 
 Definition at line 114 of file Token_Manager.h.  | 
  
      
  | 
  
| 
 pointer to singleton token manager. 
 Definition at line 18 of file Token_Manager.cpp. Referenced by instance().  | 
  
 
1.3.6