#include <Local_Tokens.h>
Inheritance diagram for ACE_Mutex_Token:
Public Member Functions | |
ACE_Mutex_Token (const ACE_TCHAR *name) | |
Constructor. | |
virtual | ~ACE_Mutex_Token (void) |
Destructor. | |
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. | |
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. | |
virtual int | type (void) const |
Returns ACE_Tokens::MUTEX. | |
virtual int | owners (OWNER_STACK &o, const ACE_TCHAR *id) |
virtual int | is_waiting_for (const ACE_TCHAR *id) |
Returns 1 if is waiting for this token. 0 otherwise. | |
virtual int | is_owner (const ACE_TCHAR *id) |
Returns 1 if is an owner of this token. 0 otherwise. | |
Private Attributes | |
ACE_TOKEN_CONST::MUTEX | lock_ |
ACE_Mutex_Token used to lock internal data structures. |
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 498 of file Local_Tokens.h.
|
Constructor.
Definition at line 466 of file Local_Tokens.cpp. References ACE_MAXTOKENNAMELEN, ACE_TCHAR, ACE_TRACE, and ACE_OS::strsncpy().
00467 { 00468 ACE_TRACE ("ACE_Mutex_Token::ACE_Mutex_Token"); 00469 00470 ACE_OS::strsncpy (this->token_name_, 00471 name, 00472 ACE_MAXTOKENNAMELEN); 00473 } |
|
Destructor.
Definition at line 475 of file Local_Tokens.cpp. References ACE_TRACE.
00476 { 00477 ACE_TRACE ("ACE_Mutex_Token::~ACE_Mutex_Token"); 00478 } |
|
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 481 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_TOKEN_CONST::MUTEX, ACE_TPQ_Entry::nesting_level(), ACE_Tokens::owner(), and ACE_TPQ_Entry::proxy().
00484 { 00485 ACE_TRACE ("ACE_Mutex_Token::acquire"); 00486 // We need to acquire two locks. This one to ensure that only one 00487 // thread uses this token at a time. 00488 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1); 00489 // This one to ensure an atomic transaction across all tokens. Note 00490 // that this order is crucial too. It's resource coloring for other 00491 // threads which may be calling this same token. 00492 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1); 00493 00494 // Does _anyone_ own the token? 00495 if (this->owner () == 0) 00496 { 00497 // there are no waiters, so queue as the first waiter (the owner.) 00498 this->waiters_.enqueue (caller, -1); 00499 return 0; // success 00500 } 00501 00502 // Does the caller already own it? 00503 if (this->is_owner (caller->client_id ())) 00504 { 00505 // Recursive acquisition. 00506 caller->nesting_level (1); 00507 return 0; // success 00508 } 00509 00510 // Check for deadlock. 00511 if (!ignore_deadlock 00512 && ACE_Token_Manager::instance ()->check_deadlock (caller->proxy ()) == 1) 00513 { 00514 errno = EDEADLK; 00515 ACE_RETURN (-1); 00516 } 00517 00518 // Someone owns it. Sorry, you're getting queued up at the end of 00519 // the waiter queue. 00520 this->waiters_.enqueue (caller, -1); 00521 00522 if (notify) 00523 this->owner ()->call_sleep_hook (); 00524 00525 errno = EWOULDBLOCK; 00526 ACE_RETURN (-1); 00527 00528 ACE_NOTREACHED (return -1); 00529 } |
|
Dump the state of the class.
Reimplemented from ACE_Tokens. Definition at line 451 of file Local_Tokens.cpp. References ACE_BEGIN_DUMP, ACE_DEBUG, ACE_END_DUMP, ACE_LIB_TEXT, ACE_TRACE, ACE_Tokens::dump(), ACE_Null_Mutex::dump(), and LM_DEBUG.
00452 { 00453 #if defined (ACE_HAS_DUMP) 00454 ACE_TRACE ("ACE_Mutex_Token::dump"); 00455 ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); 00456 ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("ACE_Mutex_Token::dump:\n"))); 00457 ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("lock_\n"))); 00458 lock_.dump (); 00459 ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("base:\n"))); 00460 ACE_Tokens::dump (); 00461 ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("ACE_Mutex_Token::dump end.\n"))); 00462 ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); 00463 #endif /* ACE_HAS_DUMP */ 00464 } |
|
Returns 1 if is an owner of this token. 0 otherwise.
Implements ACE_Tokens. Definition at line 678 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().
00679 { 00680 ACE_TRACE ("ACE_Mutex_Token::is_owner"); 00681 // If there is an owner, return whether it is <id>. 00682 if ((this->owner () != 0) && 00683 this->owner ()->equal_client_id (id)) 00684 return 1; 00685 else 00686 return 0; 00687 } |
|
Returns 1 if is waiting for this token. 0 otherwise.
Implements ACE_Tokens. Definition at line 656 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(), and ACE_Tokens::owner().
00657 { 00658 ACE_TRACE ("ACE_Mutex_Token::is_waiting_for"); 00659 // If there is no owner, or <id> is the owner, return false. 00660 if ((this->owner () == 0) || this->is_owner (id)) 00661 return 0; 00662 00663 // Step through each waiter looking for <id>. 00664 ACE_TPQ_Iterator iterator (waiters_); 00665 iterator.advance (); 00666 for (ACE_TPQ_Entry *temp = 0; 00667 iterator.next (temp) != 0; 00668 iterator.advance ()) 00669 { 00670 if (temp->equal_client_id (id)) 00671 return 1; 00672 } 00673 00674 return 0; 00675 } |
|
Returns a stack of the current owners. Returns -1 on error, 0 on success. If is non-zero, returns 1 if id is an owner. Implements ACE_Tokens. Definition at line 639 of file Local_Tokens.cpp. References ACE_TCHAR, ACE_TRACE, ACE_TPQ_Entry::equal_client_id(), and ACE_Tokens::owner().
00641 { 00642 ACE_TRACE ("ACE_Mutex_Token::owners"); 00643 if (this->owner () != 0) 00644 { 00645 stack.push (this->owner ()); 00646 // If an <id> is specified, return whether it is the owner being 00647 // returned. 00648 if (id != 0) 00649 return this->owner ()->equal_client_id (id); 00650 } 00651 00652 return 0; 00653 } |
|
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 606 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_TOKEN_CONST::MUTEX, ACE_TPQ_Entry::nesting_level(), ACE_Tokens::owner(), ACE_TPQ_Entry::proxy(), ACE_Tokens::remove(), and ACE_Token_Proxy::token_acquired().
00607 { 00608 ACE_TRACE ("ACE_Mutex_Token::release"); 00609 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1); 00610 00611 // Does anyone own the token? 00612 if (this->owner () == 0) 00613 { 00614 errno = EACCES; 00615 ACE_RETURN (-1); 00616 } 00617 00618 // Is the caller the owner. 00619 if (this->is_owner (caller->client_id ())) 00620 { 00621 // Check the nesting level. 00622 if (caller->nesting_level () > 0) 00623 caller->nesting_level (-1); 00624 else 00625 { 00626 this->waiters_.dequeue (); 00627 // Notify new owner. 00628 if (this->owner () != 0) 00629 this->owner ()->proxy ()->token_acquired (this->owner ()); 00630 } 00631 } 00632 else 00633 this->remove (caller); 00634 00635 return 0; 00636 } |
|
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 == -1 and there are other threads waiting to obtain the token we are queued at the end of the list of waiters. If > -1 then it indicates how many entries to skip over before inserting our thread into the list of waiters (e.g., == 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 567 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_TOKEN_CONST::MUTEX, ACE_Tokens::owner(), ACE_TPQ_Entry::proxy(), ACE_Token_Proxy_Queue::size(), and ACE_Token_Proxy::token_acquired().
00569 { 00570 ACE_TRACE ("ACE_Mutex_Token::renew"); 00571 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1); 00572 00573 // Verify that the caller is the owner. 00574 if (this->is_owner (caller->client_id ()) == 0) 00575 { 00576 errno = EACCES; 00577 ACE_RETURN (-1); 00578 } 00579 00580 // The caller is the owner, so check to see if there are any 00581 // waiters. If not, we just keep the token. == 1 means that there 00582 // is only the owner. 00583 if (this->waiters_.size () == 1 || requeue_position == 0) 00584 return 0; 00585 00586 // Requeue the caller. 00587 this->waiters_.dequeue (); 00588 00589 this->waiters_.enqueue (caller, requeue_position); 00590 00591 // Notify new owner. 00592 if (this->owner () != 0) 00593 this->owner ()->proxy ()->token_acquired (this->owner ()); 00594 00595 // Tell the caller that the operation would block. 00596 errno = EWOULDBLOCK; 00597 ACE_RETURN (-1); 00598 00599 ACE_NOTREACHED (return -1); 00600 } |
|
Same as acquire, but fails if would block.
Implements ACE_Tokens. Definition at line 532 of file Local_Tokens.cpp. References ACE_GUARD_RETURN, ACE_RETURN, ACE_TRACE, ACE_TPQ_Entry::client_id(), ACE_Token_Proxy_Queue::enqueue(), EWOULDBLOCK, is_owner(), ACE_TOKEN_CONST::MUTEX, ACE_TPQ_Entry::nesting_level(), and ACE_Tokens::owner().
00533 { 00534 ACE_TRACE ("ACE_Mutex_Token::tryacquire"); 00535 // We need to acquire two locks. This one to ensure that only one 00536 // thread uses this token at a time. 00537 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1); 00538 // This one to ensure an atomic transaction across all tokens. Note 00539 // that this order is crucial too. It's resource coloring for other 00540 // threads which may be calling this same token. 00541 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1); 00542 00543 // Does _anyone_ own the token? 00544 if (this->owner () == 0) 00545 { 00546 this->waiters_.enqueue (caller, -1); 00547 return 0; // success 00548 } 00549 // Does the caller already own it? 00550 if (this->is_owner (caller->client_id ())) 00551 { 00552 // recursive acquisition 00553 caller->nesting_level (1); 00554 return 0; // success 00555 } 00556 else 00557 // Someone owns it. Fail. 00558 { 00559 errno = EWOULDBLOCK; 00560 ACE_RETURN (-1); 00561 } 00562 00563 ACE_NOTREACHED (return -1); 00564 } |
|
Returns ACE_Tokens::MUTEX.
Implements ACE_Tokens. Definition at line 690 of file Local_Tokens.cpp. References ACE_TRACE.
00691 { 00692 ACE_TRACE ("ACE_Mutex_Token::type"); 00693 return (int) ACE_Tokens::MUTEX; 00694 } |
|
ACE_Mutex_Token used to lock internal data structures.
Definition at line 574 of file Local_Tokens.h. |