discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: NSConditionLock


From: David Chisnall
Subject: Re: NSConditionLock
Date: Mon, 12 Dec 2011 15:31:34 +0000

I think you are misunderstanding what NSCondition does.

The -wait method releases the lock and waits for it to be signalled.  When it 
is signalled, it atomically acquires the lock when the thread that owns it.

On 12 Dec 2011, at 15:20, Thomas Davie wrote:

> The way I read this is that while the thread making the call should block, 
> other threads attempting to access the lock while the condition is not met 
> should not block.

Correct.  The -wait call will atomically release the lock and sleep.  It will 
return when the condition has been signalled.

> Here's GNUstep's implementation:
>> - (void) lockWhenCondition: (NSInteger)value
>> {
>>   [_condition lock];
>>   while (value != _condition_value)
>>     {
>>       [_condition wait];
>>     }
>> }
> 
> I'm pretty sure this doesn't match the right semantics if:
> 
> The lock is initialised with a condition that isn't 5
> Thread 1 calls [lock lockWhenCondition:5];

Acquires the lock, checks the condition.  The condition is false.  Atomically 
releases the lock and sleeps.

> Thread 2 calls [lock lock];

Acquires the lock.

> Thread 2 calls [lock unlockWithCondition:5];

Signals the condition variable.  The -wait call is then blocked attempting to 
acquire the lock.  Releases the lock.  The -wait call returns (with the lock).  
Thread 1 proceeds.

> My expectation here would be for thread 1 to block at it's call to 
> lockWhenCondition:, then for thread 2 to acquire the lock, then for it to 
> give up the lock, and for thread 1 to unblock.

Yes, that's correct.

> The actual results with GNUstep's implementation are for thread 1 to not get 
> the lock, but for it to become locked, then for thread 2 to block because 
> thread 1 has the lock, and for the program to deadlock.

Do you have a complete test case that demonstrates this?  I'm pretty sure that 
the -base test suite has a test that looks like this and it passes...

> Wouldn't an implementation more like this be appropriate (note though that 
> this too is buggy as it violate's NSCondition's API contract that wait must 
> only be called while locked)?

That is a VERY important constraint!  Violating is means calling a pthread API 
with undefined behaviour!  The -wait call atomically releases and reacquires 
the lock after a signal - that is the entire point of it.  Calling it without 
the lock being held is nonsense.

> 
>> - (void) lockWhenCondition: (NSInteger)value
> {
>   while (1)
>   {
>     [_condition lock];

Now we hold the lock.

>     if (value != _condition_value)
>     {
>       return;
>     }

Now we're returning, while holding the lock, even though the condition doesn't 
hold?

>     [_condition unlock];

Now we're releasing the lock.  If the condition is now signalled then we lose 
the signal and the next line blocks forever.

>     [_condition wait];

Now we block, atomically releasing the lock (that we don't hold, so entering 
some undefined behaviour) and waiting for the signal that we just missed.

David

-- Sent from my brain


reply via email to

[Prev in Thread] Current Thread [Next in Thread]