Fix several problems with lockWhenCondition:beforeDate:

First -- it needs to use timeIntervalSince1970 to be using the same reference date required for pthread_cond_timedwait
Second -- lockWhenCondition needs to loop because pthread_cond_timedwait can return prior to delay expiring (but with the wrong condition).
Third -- Internally the lock was incorrectly being unlocked on a delayed acquire (and YES return).  And was incorrectly being unlocked a second time when the timeout expired.

Also, fixed a problem with tryLockWhenCondition:
By calling lockWhenCondition: it would incorrectly report a deadlock (rather than just return no) when we already have the lock.

All these changes are in line with expected and documented behavior for NSLock.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@29472 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Jonathan Gillaspie 2010-02-03 21:15:03 +00:00
parent 367d552a3b
commit d85c001251

View file

@ -297,23 +297,29 @@ MUNLOCK
- (BOOL) waitUntilDate: (NSDate*)limit
{
NSTimeInterval t = [limit timeIntervalSinceReferenceDate];
NSTimeInterval t = [limit timeIntervalSince1970];
double secs, subsecs;
struct timespec timeout;
int retVal = 0;
// Split the float into seconds and fractions of a second
subsecs = modf(t, &secs);
timeout.tv_sec = secs;
// Convert fractions of a second to nanoseconds
timeout.tv_nsec = subsecs * 1e9;
if (0 == pthread_cond_timedwait(&_condition, &_mutex, &timeout))
retVal = pthread_cond_timedwait(&_condition, &_mutex, &timeout);
if (retVal == 0)
{
return YES;
}
else
else if (retVal == EINVAL)
{
return NO;
}
NSLog(@"Invalid arguments to pthread_cond_timedwait");
}
return NO;
}
@end
@ -379,24 +385,19 @@ MUNLOCK
- (BOOL) lockWhenCondition: (NSInteger)condition_to_meet
beforeDate: (NSDate*)limitDate
{
BOOL ret;
[_condition lock];
if (condition_to_meet == _condition_value)
{
return YES;
}
if ([_condition waitUntilDate: limitDate]
&& (condition_to_meet == _condition_value))
{
ret = YES;
while ([_condition waitUntilDate: limitDate]) {
if (condition_to_meet == _condition_value) {
return YES; // KEEP THE LOCK
}
else
{
ret = NO;
}
[_condition unlock];
return ret;
}
// we timed out and no longer have the lock
return NO;
}
MNAME
@ -406,10 +407,18 @@ MNAME
return [_condition tryLock];
}
- (BOOL) tryLockWhenCondition: (NSInteger)value
- (BOOL) tryLockWhenCondition: (NSInteger)condition_to_meet
{
return [self lockWhenCondition: value
beforeDate: [NSDate date]];
if ([_condition tryLock]) {
if (condition_to_meet == _condition_value) {
return YES; // KEEP THE LOCK
}
else {
[_condition unlock];
}
}
return NO;
}
- (void) unlock