mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-02-04 11:33:48 +00:00
restructured repository based on following standards:
https://github.com/HW-Core/directory-structure
This commit is contained in:
270
modules/dep/acelite/ace/Token_Manager.cpp
Normal file
270
modules/dep/acelite/ace/Token_Manager.cpp
Normal file
@@ -0,0 +1,270 @@
|
||||
#include "ace/Token_Manager.h"
|
||||
|
||||
#if defined (ACE_HAS_TOKENS_LIBRARY)
|
||||
|
||||
#include "ace/Object_Manager.h"
|
||||
#include "ace/os_include/os_typeinfo.h"
|
||||
|
||||
#if !defined (__ACE_INLINE__)
|
||||
#include "ace/Token_Manager.inl"
|
||||
#endif /* __ACE_INLINE__ */
|
||||
|
||||
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
|
||||
|
||||
// singleton token manager
|
||||
ACE_Token_Manager *ACE_Token_Manager::token_manager_ = 0;
|
||||
|
||||
ACE_Token_Manager::ACE_Token_Manager ()
|
||||
{
|
||||
ACE_TRACE ("ACE_Token_Manager::ACE_Token_Manager");
|
||||
}
|
||||
|
||||
ACE_Token_Manager::~ACE_Token_Manager ()
|
||||
{
|
||||
ACE_TRACE ("ACE_Token_Manager::~ACE_Token_Manager");
|
||||
|
||||
COLLECTION::ITERATOR iterator (collection_);
|
||||
|
||||
for (COLLECTION::ENTRY *temp = 0;
|
||||
iterator.next (temp) != 0;
|
||||
iterator.advance ())
|
||||
{
|
||||
// @ should I be doing an unbind here?
|
||||
delete temp->int_id_;
|
||||
// The ext_id_'s delete themselves when the array of
|
||||
// COLLECTION::ENTRYs goes away.
|
||||
}
|
||||
}
|
||||
|
||||
ACE_Token_Manager *
|
||||
ACE_Token_Manager::instance (void)
|
||||
{
|
||||
ACE_TRACE ("ACE_Token_Manager::instance");
|
||||
|
||||
// This first check is to avoid acquiring the mutex in the common
|
||||
// case. Double-Check pattern rules.
|
||||
if (token_manager_ == 0)
|
||||
{
|
||||
#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
|
||||
ACE_TOKEN_CONST::MUTEX *lock =
|
||||
ACE_Managed_Object<ACE_TOKEN_CONST::MUTEX>::get_preallocated_object
|
||||
(ACE_Object_Manager::ACE_TOKEN_MANAGER_CREATION_LOCK);
|
||||
ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, *lock, 0);
|
||||
#endif /* ACE_MT_SAFE */
|
||||
|
||||
if (token_manager_ == 0)
|
||||
{
|
||||
ACE_NEW_RETURN (token_manager_,
|
||||
ACE_Token_Manager,
|
||||
0);
|
||||
// Register for destruction with ACE_Object_Manager.
|
||||
ACE_Object_Manager::at_exit (token_manager_, 0, typeid (token_manager_).name ());
|
||||
}
|
||||
}
|
||||
|
||||
return token_manager_;
|
||||
}
|
||||
|
||||
void
|
||||
ACE_Token_Manager::get_token (ACE_Token_Proxy *proxy,
|
||||
const ACE_TCHAR *token_name)
|
||||
{
|
||||
ACE_TRACE ("ACE_Token_Manager::get_token");
|
||||
// Hmm. I think this makes sense. We perform our own locking here
|
||||
// (see safe_acquire.) We have to make sure that only one thread
|
||||
// uses the collection at a time.
|
||||
|
||||
ACE_GUARD (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_);
|
||||
|
||||
TOKEN_NAME name (token_name);
|
||||
|
||||
if (collection_.find (name, proxy->token_) == -1)
|
||||
// We did not find one in the collection.
|
||||
{
|
||||
// Make one.
|
||||
proxy->token_ = proxy->create_token (token_name);
|
||||
|
||||
// Put it in the collection.
|
||||
if (collection_.bind (name, proxy->token_) == -1)
|
||||
{
|
||||
delete proxy->token_;
|
||||
proxy->token_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (proxy->token_ != 0)
|
||||
proxy->token_->inc_reference ();
|
||||
|
||||
// We may be returning proxy->token_ == 0 if new failed, caller must
|
||||
// check.
|
||||
}
|
||||
|
||||
// 0. check_deadlock (TOKEN)
|
||||
// 1. if TOKEN->visited (), return 0.
|
||||
// 2. mark TOKEN visited.
|
||||
// 3. get ALL_OWNERS
|
||||
// 4. if CLIENT in ALL_OWNERS, return *DEADLOCK*.
|
||||
// 5. for each OWNER in ALL_OWNERS,
|
||||
// 6. if OWNER is not waiting for a NEW_TOKEN, continue.
|
||||
// 7. else, if check_deadlock (NEW_TOKEN) == 1, return *DEADLOCK*
|
||||
// 8. return 0.
|
||||
|
||||
int
|
||||
ACE_Token_Manager::check_deadlock (ACE_Token_Proxy *proxy)
|
||||
{
|
||||
ACE_TRACE ("ACE_Token_Manager::check_deadlock");
|
||||
|
||||
// Start the recursive deadlock detection algorithm.
|
||||
int result = this->check_deadlock (proxy->token_, proxy);
|
||||
|
||||
// Whether or not we detect deadlock, we have to unmark all tokens
|
||||
// for the next time.
|
||||
COLLECTION::ITERATOR iterator (collection_);
|
||||
for (COLLECTION::ENTRY *temp = 0;
|
||||
iterator.next (temp) != 0;
|
||||
iterator.advance ())
|
||||
temp->int_id_->visit (0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
ACE_Token_Manager::check_deadlock (ACE_Tokens *token, ACE_Token_Proxy *proxy)
|
||||
{
|
||||
ACE_TRACE ("ACE_Token_Manager::check_deadlock");
|
||||
|
||||
if (token->visited ())
|
||||
return 0;
|
||||
|
||||
token->visit (1);
|
||||
|
||||
ACE_Tokens::OWNER_STACK owners;
|
||||
|
||||
int is_owner = token->owners (owners, proxy->client_id ());
|
||||
|
||||
switch (is_owner)
|
||||
{
|
||||
case -1:
|
||||
// Error.
|
||||
return -1;
|
||||
case 1:
|
||||
// The caller is an owner, so we have a deadlock situation.
|
||||
if (debug_)
|
||||
{
|
||||
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Deadlock detected.\n")));
|
||||
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("%s owns %s and is waiting for %s.\n"),
|
||||
proxy->client_id (),
|
||||
token->name (),
|
||||
proxy->token_->name ()));
|
||||
}
|
||||
|
||||
return 1;
|
||||
case 0:
|
||||
default:
|
||||
// Recurse on each owner.
|
||||
while (!owners.is_empty ())
|
||||
{
|
||||
ACE_TPQ_Entry *e;
|
||||
owners.pop (e);
|
||||
// If the owner is waiting on another token, recurse.
|
||||
ACE_Tokens *twf = this->token_waiting_for (e->client_id ());
|
||||
if ((twf != 0) &&
|
||||
(this->check_deadlock (twf, proxy) == 1))
|
||||
{
|
||||
if (debug_)
|
||||
{
|
||||
ACELIB_DEBUG ((LM_DEBUG,
|
||||
ACE_TEXT ("%s owns %s and is waiting for %s.\n"),
|
||||
e->client_id (),
|
||||
token->name (),
|
||||
twf->name ()));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
// else, check the next owner.
|
||||
}
|
||||
|
||||
// We've checked all the owners and found no deadlock.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ACE_Tokens *
|
||||
ACE_Token_Manager::token_waiting_for (const ACE_TCHAR *client_id)
|
||||
{
|
||||
COLLECTION::ITERATOR iterator (collection_);
|
||||
for (COLLECTION::ENTRY *temp = 0;
|
||||
iterator.next (temp) != 0;
|
||||
iterator.advance ())
|
||||
{
|
||||
if (temp->int_id_->is_waiting_for (client_id))
|
||||
return temp->int_id_;
|
||||
}
|
||||
|
||||
// nothing was found, return NULL.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Notify the token manager that a token is has been released. If
|
||||
// as a result, there is no owner of the token, the token is
|
||||
// deleted.
|
||||
void
|
||||
ACE_Token_Manager::release_token (ACE_Tokens *&token)
|
||||
{
|
||||
ACE_TRACE ("ACE_Token_Manager::release_token");
|
||||
// again, let's perform our own locking here.
|
||||
|
||||
ACE_GUARD (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_);
|
||||
|
||||
if (token->dec_reference () == 0)
|
||||
{
|
||||
// No one has the token, so we can delete it and remove it from
|
||||
// our collection. First, let's get it from the collection.
|
||||
TOKEN_NAME token_name (token->name ());
|
||||
|
||||
ACE_Tokens *temp;
|
||||
|
||||
if (collection_.unbind (token_name, temp) == -1)
|
||||
// we did not find one in the collection
|
||||
{
|
||||
errno = ENOENT;
|
||||
ACELIB_ERROR ((LM_ERROR, ACE_TEXT ("Token Manager could not release %s:%d\n"),
|
||||
token->name (), token->type ()));
|
||||
// @@ bad
|
||||
}
|
||||
else
|
||||
// we found it
|
||||
{
|
||||
// sanity pointer comparison. The token referenced by the
|
||||
// proxy better be the one we found in the list.
|
||||
ACE_ASSERT (token == temp);
|
||||
delete token; // or delete temp
|
||||
// we set their token to zero. if the calling proxy is
|
||||
// still going to be used, it had better check it's token
|
||||
// value before calling a method on it!
|
||||
token = 0;
|
||||
}
|
||||
}
|
||||
// else
|
||||
// someone is still interested in the token, so keep it around.
|
||||
}
|
||||
|
||||
void
|
||||
ACE_Token_Manager::dump (void) const
|
||||
{
|
||||
#if defined (ACE_HAS_DUMP)
|
||||
ACE_TRACE ("ACE_Token_Manager::dump");
|
||||
ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
|
||||
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Token_Manager::dump:\n")));
|
||||
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("lock_\n")));
|
||||
lock_.dump ();
|
||||
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("collection_\n")));
|
||||
collection_.dump ();
|
||||
ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
|
||||
#endif /* ACE_HAS_DUMP */
|
||||
}
|
||||
|
||||
ACE_END_VERSIONED_NAMESPACE_DECL
|
||||
|
||||
#endif /* ACE_HAS_TOKENS_LIBRARY */
|
||||
Reference in New Issue
Block a user