#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(). |