1 #include "ace/Token_Manager.h"
3 #if defined (ACE_HAS_TOKENS_LIBRARY)
5 #include "ace/Object_Manager.h"
6 #include "ace/os_include/os_typeinfo.h"
8 #if !defined (__ACE_INLINE__)
9 #include "ace/Token_Manager.inl"
10 #endif /* __ACE_INLINE__ */
12 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
14 // singleton token manager
15 ACE_Token_Manager
*ACE_Token_Manager::token_manager_
= 0;
17 ACE_Token_Manager::ACE_Token_Manager ()
19 ACE_TRACE ("ACE_Token_Manager::ACE_Token_Manager");
22 ACE_Token_Manager::~ACE_Token_Manager ()
24 ACE_TRACE ("ACE_Token_Manager::~ACE_Token_Manager");
26 COLLECTION::ITERATOR
iterator (collection_
);
28 for (COLLECTION::ENTRY
*temp
= 0;
29 iterator
.next (temp
) != 0;
32 // @ should I be doing an unbind here?
34 // The ext_id_'s delete themselves when the array of
35 // COLLECTION::ENTRYs goes away.
40 ACE_Token_Manager::instance ()
42 ACE_TRACE ("ACE_Token_Manager::instance");
44 // This first check is to avoid acquiring the mutex in the common
45 // case. Double-Check pattern rules.
46 if (token_manager_
== 0)
48 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
49 ACE_TOKEN_CONST::MUTEX
*lock
=
50 ACE_Managed_Object
<ACE_TOKEN_CONST::MUTEX
>::get_preallocated_object
51 (ACE_Object_Manager::ACE_TOKEN_MANAGER_CREATION_LOCK
);
52 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX
, ace_mon
, *lock
, 0);
53 #endif /* ACE_MT_SAFE */
55 if (token_manager_
== 0)
57 ACE_NEW_RETURN (token_manager_
,
60 // Register for destruction with ACE_Object_Manager.
61 ACE_Object_Manager::at_exit (token_manager_
, 0, typeid (token_manager_
).name ());
65 return token_manager_
;
69 ACE_Token_Manager::get_token (ACE_Token_Proxy
*proxy
,
70 const ACE_TCHAR
*token_name
)
72 ACE_TRACE ("ACE_Token_Manager::get_token");
73 // Hmm. I think this makes sense. We perform our own locking here
74 // (see safe_acquire.) We have to make sure that only one thread
75 // uses the collection at a time.
77 ACE_GUARD (ACE_TOKEN_CONST::MUTEX
, ace_mon
, this->lock_
);
79 TOKEN_NAME
name (token_name
);
81 if (collection_
.find (name
, proxy
->token_
) == -1)
82 // We did not find one in the collection.
85 proxy
->token_
= proxy
->create_token (token_name
);
87 // Put it in the collection.
88 if (collection_
.bind (name
, proxy
->token_
) == -1)
95 if (proxy
->token_
!= 0)
96 proxy
->token_
->inc_reference ();
98 // We may be returning proxy->token_ == 0 if new failed, caller must
102 // 0. check_deadlock (TOKEN)
103 // 1. if TOKEN->visited (), return 0.
104 // 2. mark TOKEN visited.
106 // 4. if CLIENT in ALL_OWNERS, return *DEADLOCK*.
107 // 5. for each OWNER in ALL_OWNERS,
108 // 6. if OWNER is not waiting for a NEW_TOKEN, continue.
109 // 7. else, if check_deadlock (NEW_TOKEN) == 1, return *DEADLOCK*
113 ACE_Token_Manager::check_deadlock (ACE_Token_Proxy
*proxy
)
115 ACE_TRACE ("ACE_Token_Manager::check_deadlock");
117 // Start the recursive deadlock detection algorithm.
118 int result
= this->check_deadlock (proxy
->token_
, proxy
);
120 // Whether or not we detect deadlock, we have to unmark all tokens
121 // for the next time.
122 COLLECTION::ITERATOR
iterator (collection_
);
123 for (COLLECTION::ENTRY
*temp
= 0;
124 iterator
.next (temp
) != 0;
126 temp
->int_id_
->visit (0);
132 ACE_Token_Manager::check_deadlock (ACE_Tokens
*token
, ACE_Token_Proxy
*proxy
)
134 ACE_TRACE ("ACE_Token_Manager::check_deadlock");
136 if (token
->visited ())
141 ACE_Tokens::OWNER_STACK owners
;
143 int is_owner
= token
->owners (owners
, proxy
->client_id ());
151 // The caller is an owner, so we have a deadlock situation.
154 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%t) Deadlock detected.\n")));
155 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("%s owns %s and is waiting for %s.\n"),
158 proxy
->token_
->name ()));
164 // Recurse on each owner.
165 while (!owners
.is_empty ())
169 // If the owner is waiting on another token, recurse.
170 ACE_Tokens
*twf
= this->token_waiting_for (e
->client_id ());
172 (this->check_deadlock (twf
, proxy
) == 1))
176 ACELIB_DEBUG ((LM_DEBUG
,
177 ACE_TEXT ("%s owns %s and is waiting for %s.\n"),
184 // else, check the next owner.
187 // We've checked all the owners and found no deadlock.
194 ACE_Token_Manager::token_waiting_for (const ACE_TCHAR
*client_id
)
196 COLLECTION::ITERATOR
iterator (collection_
);
197 for (COLLECTION::ENTRY
*temp
= 0;
198 iterator
.next (temp
) != 0;
201 if (temp
->int_id_
->is_waiting_for (client_id
))
202 return temp
->int_id_
;
205 // nothing was found, return NULL.
209 // Notify the token manager that a token is has been released. If
210 // as a result, there is no owner of the token, the token is
213 ACE_Token_Manager::release_token (ACE_Tokens
*&token
)
215 ACE_TRACE ("ACE_Token_Manager::release_token");
216 // again, let's perform our own locking here.
218 ACE_GUARD (ACE_TOKEN_CONST::MUTEX
, ace_mon
, this->lock_
);
220 if (token
->dec_reference () == 0)
222 // No one has the token, so we can delete it and remove it from
223 // our collection. First, let's get it from the collection.
224 TOKEN_NAME
token_name (token
->name ());
228 if (collection_
.unbind (token_name
, temp
) == -1)
229 // we did not find one in the collection
232 ACELIB_ERROR ((LM_ERROR
, ACE_TEXT ("Token Manager could not release %s:%d\n"),
233 token
->name (), token
->type ()));
239 // sanity pointer comparison. The token referenced by the
240 // proxy better be the one we found in the list.
241 ACE_ASSERT (token
== temp
);
242 delete token
; // or delete temp
243 // we set their token to zero. if the calling proxy is
244 // still going to be used, it had better check it's token
245 // value before calling a method on it!
250 // someone is still interested in the token, so keep it around.
254 ACE_Token_Manager::dump () const
256 #if defined (ACE_HAS_DUMP)
257 ACE_TRACE ("ACE_Token_Manager::dump");
258 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
259 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("ACE_Token_Manager::dump:\n")));
260 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("lock_\n")));
262 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("collection_\n")));
264 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
265 #endif /* ACE_HAS_DUMP */
268 ACE_END_VERSIONED_NAMESPACE_DECL
270 #endif /* ACE_HAS_TOKENS_LIBRARY */