Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / Token_Manager.cpp
blob052a900db0ea844c71ff7ad703c1aa7fe6039f0a
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;
30 iterator.advance ())
32 // @ should I be doing an unbind here?
33 delete temp->int_id_;
34 // The ext_id_'s delete themselves when the array of
35 // COLLECTION::ENTRYs goes away.
39 ACE_Token_Manager *
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_,
58 ACE_Token_Manager,
59 0);
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_;
68 void
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.
84 // Make one.
85 proxy->token_ = proxy->create_token (token_name);
87 // Put it in the collection.
88 if (collection_.bind (name, proxy->token_) == -1)
90 delete proxy->token_;
91 proxy->token_ = 0;
95 if (proxy->token_ != 0)
96 proxy->token_->inc_reference ();
98 // We may be returning proxy->token_ == 0 if new failed, caller must
99 // check.
102 // 0. check_deadlock (TOKEN)
103 // 1. if TOKEN->visited (), return 0.
104 // 2. mark TOKEN visited.
105 // 3. get ALL_OWNERS
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*
110 // 8. return 0.
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;
125 iterator.advance ())
126 temp->int_id_->visit (0);
128 return result;
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 ())
137 return 0;
139 token->visit (1);
141 ACE_Tokens::OWNER_STACK owners;
143 int is_owner = token->owners (owners, proxy->client_id ());
145 switch (is_owner)
147 case -1:
148 // Error.
149 return -1;
150 case 1:
151 // The caller is an owner, so we have a deadlock situation.
152 if (debug_)
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"),
156 proxy->client_id (),
157 token->name (),
158 proxy->token_->name ()));
161 return 1;
162 case 0:
163 default:
164 // Recurse on each owner.
165 while (!owners.is_empty ())
167 ACE_TPQ_Entry *e;
168 owners.pop (e);
169 // If the owner is waiting on another token, recurse.
170 ACE_Tokens *twf = this->token_waiting_for (e->client_id ());
171 if ((twf != 0) &&
172 (this->check_deadlock (twf, proxy) == 1))
174 if (debug_)
176 ACELIB_DEBUG ((LM_DEBUG,
177 ACE_TEXT ("%s owns %s and is waiting for %s.\n"),
178 e->client_id (),
179 token->name (),
180 twf->name ()));
182 return 1;
184 // else, check the next owner.
187 // We've checked all the owners and found no deadlock.
188 return 0;
193 ACE_Tokens *
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;
199 iterator.advance ())
201 if (temp->int_id_->is_waiting_for (client_id))
202 return temp->int_id_;
205 // nothing was found, return NULL.
206 return 0;
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
211 // deleted.
212 void
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 ());
226 ACE_Tokens *temp;
228 if (collection_.unbind (token_name, temp) == -1)
229 // we did not find one in the collection
231 errno = ENOENT;
232 ACELIB_ERROR ((LM_ERROR, ACE_TEXT ("Token Manager could not release %s:%d\n"),
233 token->name (), token->type ()));
234 // @@ bad
236 else
237 // we found it
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!
246 token = 0;
249 // else
250 // someone is still interested in the token, so keep it around.
253 void
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")));
261 lock_.dump ();
262 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("collection_\n")));
263 collection_.dump ();
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 */