Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

ACE_Mutex_Token Class Reference

Class that acquires, renews, and releases a process-local synchronization token. More...

#include <Local_Tokens.h>

Inheritance diagram for ACE_Mutex_Token:

Inheritance graph
[legend]
Collaboration diagram for ACE_Mutex_Token:

Collaboration graph
[legend]
List of all members.

Public Methods

ACE_EXPLICIT ACE_Mutex_Token (const ACE_TCHAR *name)
 Constructor. More...

virtual ~ACE_Mutex_Token (void)
 Destructor. More...

virtual int acquire (ACE_TPQ_Entry *caller, int ignore_deadlock, int notify)
virtual int tryacquire (ACE_TPQ_Entry *caller)
 Same as acquire, but fails if would block. More...

virtual int renew (ACE_TPQ_Entry *caller, int requeue_position)
virtual int release (ACE_TPQ_Entry *caller)
void dump (void) const
 Dump the state of the class. More...

virtual int type (void) const
 Returns ACE_Tokens::MUTEX. More...

virtual int owners (OWNER_STACK &o, const ACE_TCHAR *id)
 Returns a stack of the current owners. Returns -1 on error, 0 on success. If <id> is non-zero, returns 1 if id is an owner. More...

virtual int is_waiting_for (const ACE_TCHAR *id)
 Returns 1 if <id> is waiting for this token. 0 otherwise. More...

virtual int is_owner (const ACE_TCHAR *id)
 Returns 1 if <id> is an owner of this token. 0 otherwise. More...


Private Attributes

ACE_TOKEN_CONST::MUTEX lock_
 ACE_Mutex_Token used to lock internal data structures. More...


Detailed Description

Class that acquires, renews, and releases a process-local synchronization token.

Not a public interface. This class is a more general-purpose synchronization mechanism than SunOS 5.x mutexes. For example, it implements "recursive mutex" semantics, where a thread that owns the token can reacquire it without deadlocking. In addition, threads that are blocked awaiting the token are serviced in strict FIFO order as other threads release the token (SunOS 5.x mutexes don't strictly enforce an acquisition order).

Definition at line 493 of file Local_Tokens.h.


Constructor & Destructor Documentation

ACE_Mutex_Token::ACE_Mutex_Token const ACE_TCHAR   name
 

Constructor.

Definition at line 434 of file Local_Tokens.cpp.

References ACE_MAXTOKENNAMELEN, ACE_TCHAR, ACE_TRACE, ACE_Tokens::name, and ACE_OS_String::strsncpy.

00435 {
00436   ACE_TRACE ("ACE_Mutex_Token::ACE_Mutex_Token");
00437 
00438   ACE_OS::strsncpy (this->token_name_,
00439                     name,
00440                     ACE_MAXTOKENNAMELEN);
00441 }

ACE_Mutex_Token::~ACE_Mutex_Token void    [virtual]
 

Destructor.

Definition at line 443 of file Local_Tokens.cpp.

References ACE_TRACE.

00444 {
00445   ACE_TRACE ("ACE_Mutex_Token::~ACE_Mutex_Token");
00446 }


Member Function Documentation

int ACE_Mutex_Token::acquire ACE_TPQ_Entry   caller,
int    ignore_deadlock,
int    notify
[virtual]
 

Returns 0 on success, -1 on failure with <ACE_Log_Msg::errnum> as the reason. If errnum == EWOULDBLOCK, and notify == 1, <ACE_Token_Proxy::sleep_hook> has been called on the current owner of the token. If ignore_deadlock is passed as 1 and errnum == EDEADLK, then deadlock was detected via ace_token_manager.

Implements ACE_Tokens.

Definition at line 449 of file Local_Tokens.cpp.

References ACE_GUARD_RETURN, ACE_RETURN, ACE_TRACE, ACE_TPQ_Entry::call_sleep_hook, ACE_Token_Manager::check_deadlock, ACE_TPQ_Entry::client_id, EDEADLK, ACE_Token_Proxy_Queue::enqueue, EWOULDBLOCK, ACE_Token_Manager::instance, is_owner, ACE_Null_Mutex::lock_, ACE_TOKEN_CONST::MUTEX, ACE_TPQ_Entry::nesting_level, ACE_Tokens::owner, ACE_TPQ_Entry::proxy, and ACE_Tokens::waiters_.

00452 {
00453   ACE_TRACE ("ACE_Mutex_Token::acquire");
00454   // We need to acquire two locks. This one to ensure that only one
00455   // thread uses this token at a time.
00456   ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1);
00457   // This one to ensure an atomic transaction across all tokens.  Note
00458   // that this order is crucial too.  It's resource coloring for other
00459   // threads which may be calling this same token.
00460   ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1);
00461 
00462   // Does _anyone_ own the token?
00463   if (this->owner () == 0)
00464     {
00465       // there are no waiters, so queue as the first waiter (the owner.)
00466       this->waiters_.enqueue (caller, -1);
00467       return 0;  // success
00468     }
00469 
00470   // Does the caller already own it?
00471   if (this->is_owner (caller->client_id ()))
00472     {
00473       // Recursive acquisition.
00474       caller->nesting_level (1);
00475       return 0; // success
00476     }
00477 
00478   // Check for deadlock.
00479   if (!ignore_deadlock
00480       && ACE_Token_Manager::instance ()->check_deadlock (caller->proxy ()) == 1)
00481     {
00482       errno = EDEADLK;
00483       ACE_RETURN (-1);
00484     }
00485 
00486   // Someone owns it. Sorry, you're getting queued up at the end of
00487   // the waiter queue.
00488   this->waiters_.enqueue (caller, -1);
00489 
00490   if (notify)
00491     this->owner ()->call_sleep_hook ();
00492 
00493   errno = EWOULDBLOCK;
00494   ACE_RETURN (-1);
00495 
00496   ACE_NOTREACHED (return -1);
00497 }

void ACE_Mutex_Token::dump void    const
 

Dump the state of the class.

Reimplemented from ACE_Tokens.

Definition at line 421 of file Local_Tokens.cpp.

References ACE_BEGIN_DUMP, ACE_DEBUG, ACE_END_DUMP, ACE_LIB_TEXT, ACE_TRACE, ACE_Tokens::dump, LM_DEBUG, and lock_.

00422 {
00423   ACE_TRACE ("ACE_Mutex_Token::dump");
00424   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00425   ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("ACE_Mutex_Token::dump:\n")));
00426   ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("lock_\n")));
00427   lock_.dump ();
00428   ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("base:\n")));
00429   ACE_Tokens::dump ();
00430   ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("ACE_Mutex_Token::dump end.\n")));
00431   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00432 }

int ACE_Mutex_Token::is_owner const ACE_TCHAR   id [virtual]
 

Returns 1 if <id> is an owner of this token. 0 otherwise.

Implements ACE_Tokens.

Definition at line 646 of file Local_Tokens.cpp.

References ACE_TCHAR, ACE_TRACE, ACE_TPQ_Entry::equal_client_id, and ACE_Tokens::owner.

Referenced by acquire, is_waiting_for, release, renew, and tryacquire.

00647 {
00648   ACE_TRACE ("ACE_Mutex_Token::is_owner");
00649   // If there is an owner, return whether it is <id>.
00650   if ((this->owner () != 0) &&
00651       this->owner ()->equal_client_id (id))
00652     return 1;
00653   else
00654     return 0;
00655 }

int ACE_Mutex_Token::is_waiting_for const ACE_TCHAR   id [virtual]
 

Returns 1 if <id> is waiting for this token. 0 otherwise.

Implements ACE_Tokens.

Definition at line 624 of file Local_Tokens.cpp.

References ACE_TCHAR, ACE_TRACE, ACE_TPQ_Iterator::advance, ACE_TPQ_Entry::equal_client_id, is_owner, ACE_TPQ_Iterator::next, ACE_Tokens::owner, and ACE_Tokens::waiters_.

00625 {
00626   ACE_TRACE ("ACE_Mutex_Token::is_waiting_for");
00627   // If there is no owner, or <id> is the owner, return false.
00628   if ((this->owner () == 0) || this->is_owner (id))
00629     return 0;
00630 
00631   // Step through each waiter looking for <id>.
00632   ACE_TPQ_Iterator iterator (waiters_);
00633   iterator.advance ();
00634   for (ACE_TPQ_Entry *temp = 0;
00635        iterator.next (temp) != 0;
00636        iterator.advance ())
00637     {
00638       if (temp->equal_client_id (id))
00639         return 1;
00640     }
00641 
00642   return 0;
00643 }

int ACE_Mutex_Token::owners OWNER_STACK   o,
const ACE_TCHAR   id
[virtual]
 

Returns a stack of the current owners. Returns -1 on error, 0 on success. If <id> is non-zero, returns 1 if id is an owner.

Implements ACE_Tokens.

Definition at line 607 of file Local_Tokens.cpp.

References ACE_TCHAR, ACE_TRACE, ACE_TPQ_Entry::equal_client_id, and ACE_Tokens::owner.

00609 {
00610   ACE_TRACE ("ACE_Mutex_Token::owners");
00611   if (this->owner () != 0)
00612     {
00613       stack.push (this->owner ());
00614       // If an <id> is specified, return whether it is the owner being
00615       // returned.
00616       if (id != 0)
00617         return this->owner ()->equal_client_id (id);
00618     }
00619 
00620   return 0;
00621 }

int ACE_Mutex_Token::release ACE_TPQ_Entry   caller [virtual]
 

Relinquish the token. If there are any waiters then the next one in line gets it. If the caller is not the owner, caller is removed from the waiter list.

Implements ACE_Tokens.

Definition at line 574 of file Local_Tokens.cpp.

References ACE_GUARD_RETURN, ACE_RETURN, ACE_TRACE, ACE_TPQ_Entry::client_id, ACE_Token_Proxy_Queue::dequeue, is_owner, ACE_Null_Mutex::lock_, ACE_TOKEN_CONST::MUTEX, ACE_TPQ_Entry::nesting_level, ACE_Tokens::owner, ACE_TPQ_Entry::proxy, ACE_Tokens::remove, ACE_Token_Proxy::token_acquired, and ACE_Tokens::waiters_.

00575 {
00576   ACE_TRACE ("ACE_Mutex_Token::release");
00577   ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1);
00578 
00579   // Does anyone own the token?
00580   if (this->owner () == 0)
00581     {
00582       errno = EACCES;
00583       ACE_RETURN (-1);
00584     }
00585 
00586   // Is the caller the owner.
00587   if (this->is_owner (caller->client_id ()))
00588     {
00589       // Check the nesting level.
00590       if (caller->nesting_level () > 0)
00591         caller->nesting_level (-1);
00592       else
00593         {
00594           this->waiters_.dequeue ();
00595           // Notify new owner.
00596           if (this->owner () != 0)
00597             this->owner ()->proxy ()->token_acquired (this->owner ());
00598         }
00599     }
00600   else
00601     this->remove (caller);
00602 
00603   return 0;
00604 }

int ACE_Mutex_Token::renew ACE_TPQ_Entry   caller,
int    requeue_position
[virtual]
 

An optimized method that efficiently reacquires the token if no other threads are waiting. This is useful for situations where you don't want to degrade the quality of service if there are other threads waiting to get the token. If <requeue_position> == -1 and there are other threads waiting to obtain the token we are queued at the end of the list of waiters. If <requeue_position> > -1 then it indicates how many entries to skip over before inserting our thread into the list of waiters (e.g., <requeue_position> == 0 means "insert at front of the queue"). Renew has the rather odd semantics such that if there are other waiting threads it will give up the token even if the nesting_level_ > 1. I'm not sure if this is really the right thing to do (since it makes it possible for shared data to be changed unexpectedly) so use with caution... Returns 0 on success, -1 on failure with <ACE_Log_Msg::errnum> as the reason. If errnum == EWOULDBLOCK, and notify == 1, <ACE_Token_Proxy::sleep_hook> has been called on the current owner of the token.

Implements ACE_Tokens.

Definition at line 535 of file Local_Tokens.cpp.

References ACE_GUARD_RETURN, ACE_RETURN, ACE_TRACE, ACE_TPQ_Entry::client_id, ACE_Token_Proxy_Queue::dequeue, ACE_Token_Proxy_Queue::enqueue, EWOULDBLOCK, is_owner, ACE_Null_Mutex::lock_, ACE_TOKEN_CONST::MUTEX, ACE_Tokens::owner, ACE_TPQ_Entry::proxy, ACE_Token_Proxy_Queue::size, ACE_Token_Proxy::token_acquired, and ACE_Tokens::waiters_.

00537 {
00538   ACE_TRACE ("ACE_Mutex_Token::renew");
00539   ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1);
00540 
00541   // Verify that the caller is the owner.
00542   if (this->is_owner (caller->client_id ()) == 0)
00543     {
00544       errno = EACCES;
00545       ACE_RETURN (-1);
00546     }
00547 
00548   // The caller is the owner, so check to see if there are any
00549   // waiters.  If not, we just keep the token.  == 1 means that there
00550   // is only the owner.
00551   if (this->waiters_.size () == 1 || requeue_position == 0)
00552     return 0;
00553 
00554   // Requeue the caller.
00555   this->waiters_.dequeue ();
00556 
00557   this->waiters_.enqueue (caller, requeue_position);
00558 
00559   // Notify new owner.
00560   if (this->owner () != 0)
00561     this->owner ()->proxy ()->token_acquired (this->owner ());
00562 
00563   // Tell the caller that the operation would block.
00564   errno = EWOULDBLOCK;
00565   ACE_RETURN (-1);
00566 
00567   ACE_NOTREACHED (return -1);
00568 }

int ACE_Mutex_Token::tryacquire ACE_TPQ_Entry   caller [virtual]
 

Same as acquire, but fails if would block.

Implements ACE_Tokens.

Definition at line 500 of file Local_Tokens.cpp.

References ACE_GUARD_RETURN, ACE_RETURN, ACE_TRACE, ACE_TPQ_Entry::client_id, ACE_Token_Proxy_Queue::enqueue, EWOULDBLOCK, ACE_Token_Manager::instance, is_owner, ACE_Null_Mutex::lock_, ACE_TOKEN_CONST::MUTEX, ACE_TPQ_Entry::nesting_level, ACE_Tokens::owner, and ACE_Tokens::waiters_.

00501 {
00502   ACE_TRACE ("ACE_Mutex_Token::tryacquire");
00503   // We need to acquire two locks. This one to ensure that only one
00504   // thread uses this token at a time.
00505   ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1);
00506   // This one to ensure an atomic transaction across all tokens.  Note
00507   // that this order is crucial too.  It's resource coloring for other
00508   // threads which may be calling this same token.
00509   ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1);
00510 
00511   // Does _anyone_ own the token?
00512   if (this->owner () == 0)
00513     {
00514       this->waiters_.enqueue (caller, -1);
00515       return 0;  // success
00516     }
00517   // Does the caller already own it?
00518   if (this->is_owner (caller->client_id ()))
00519     {
00520       // recursive acquisition
00521       caller->nesting_level (1);
00522       return 0;  // success
00523     }
00524   else
00525     // Someone owns it.  Fail.
00526     {
00527       errno = EWOULDBLOCK;
00528       ACE_RETURN (-1);
00529     }
00530 
00531   ACE_NOTREACHED (return -1);
00532 }

virtual int ACE_Mutex_Token::type void    const [virtual]
 

Returns ACE_Tokens::MUTEX.

Implements ACE_Tokens.


Member Data Documentation

ACE_TOKEN_CONST::MUTEX ACE_Mutex_Token::lock_ [private]
 

ACE_Mutex_Token used to lock internal data structures.

Definition at line 569 of file Local_Tokens.h.

Referenced by dump.


The documentation for this class was generated from the following files:
Generated on Mon Jun 16 12:50:50 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002