tango.core.sync.Mutex.tryLock

Sean Kelly sean at f4.ca
Sun Jul 29 08:35:43 PDT 2007


Jason House wrote:
> Sean Kelly wrote:
>> Jason House wrote:
>>> tryLock does not seem to work as I expected.  I thought it returns if 
>>> it was successful or not.  What could possibly cause the code below 
>>> to fail?  I'm using linux.
>>>
>>> myMutex.tryLock();
>>> assert(myMutex.tryLock() == false); // fails
>>
>> Locks in Tango are recursive, so you're guaranteed to succeed if you 
>> already hold the lock.
> 
> Does that mean that the mutex locking and unlocking calls are thread 
> aware?  A given thread can repeatedly lock a mutex but must then unlock 
> it the same number of times before the mutex is released for another 
> thread to access it?

Yes.  And for what it's worth, this is largely an artifact of the OS 
implementations.  Windows mutexes can only be recursive, though the 
feature must be enabled on some POSIX implementations.  So Tango uses 
recursive mutexes largely for consistency, though I personally find them 
to be far more useful anyway (D 'synchronized' blocks are recursive as 
well).

> I was trying to be creative with some queue structures.  I wanted to add 
> a blocking version of pop.  If nothing is in the queue, wait for that to 
> change...  I was thinking that if I had a mutex that was automatically 
> locked when the queue was empty, then I could implement blocking by 
> quickly grabbing, then releasing a mutex.  For an empty queue, the lock 
> would sit and wait.
> 
> It sounds like I can't use tango's Mutex class for this purpose because 
> the push's and pop's are done by different threads.  In fact, push calls 
> are done by lots of threads.  Is there anything in tango.core.sync that 
> I should be using for this purpose?

You should look at Condition.  Use is something like this:

auto myMutex = new Mutex;
auto myCondition = new Condition( myMutex );

Thread A (producer):

synchronized( myMutex ) {
     myQueue.push( data );
     myCond.notify();
}

Thread B (consumer):

synchronized( myMutex ) {
     while( myQueue.isEmpty )
         myCond.wait();
}

In essence, Conditions are associated with a specific mutex, which is 
atomically unlocked when wait() is called.  Thus, when thread B waits it 
allows thread A to enter the protected region to add more data to the 
queue.  When wait unblocks it atomically acquires the mutex again, by 
which time thread A will have exited the protected region (earlier 
implementations actually blocked thread A and simply transferred 
control--this was indicated by 'signal' rather than 'notify').


Sean


More information about the Digitalmars-d-learn mailing list