mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +00:00
Locking simplifications
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@39958 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
1213e12424
commit
6713bb48d6
3 changed files with 29 additions and 40 deletions
|
@ -1,3 +1,10 @@
|
|||
2016-07-02 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSKeyValueObserving.m: Remove some unnecessary locking
|
||||
* Source/NSOperation.m: Simplify handling of finishing of operation
|
||||
to avoid occasional deadlock if an operation finishes in one thread
|
||||
while in another thread we are waiting for it.
|
||||
|
||||
2016-07-01 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/GSICUString.m: For immutable strings, cache the string
|
||||
|
|
|
@ -1370,7 +1370,7 @@ cifframe_callback(ffi_cif *cif, void *retp, void **args, void *user)
|
|||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) observeValueForKeyPath: (NSString *)keyPath
|
||||
- (void) oberveValueForKeyPath: (NSString *)keyPath
|
||||
ofObject: (id)anObject
|
||||
change: (NSDictionary *)change
|
||||
context: (void *)context
|
||||
|
@ -1533,10 +1533,8 @@ cifframe_callback(ffi_cif *cif, void *retp, void **args, void *user)
|
|||
- (void) removeObserver: (NSObject*)anObserver forKeyPath: (NSString*)aPath
|
||||
{
|
||||
GSKVOInfo *info;
|
||||
id forwarder;
|
||||
id forwarder;
|
||||
|
||||
setup();
|
||||
[kvoLock lock];
|
||||
/*
|
||||
* Get the observation information and remove this observation.
|
||||
*/
|
||||
|
@ -1553,7 +1551,6 @@ cifframe_callback(ffi_cif *cif, void *retp, void **args, void *user)
|
|||
IF_NO_GC(AUTORELEASE(info);)
|
||||
[self setObservationInfo: nil];
|
||||
}
|
||||
[kvoLock unlock];
|
||||
if ([aPath rangeOfString:@"."].location != NSNotFound)
|
||||
[forwarder finalize];
|
||||
}
|
||||
|
|
|
@ -201,6 +201,8 @@ static NSArray *empty = nil;
|
|||
{
|
||||
NSOperation *op;
|
||||
|
||||
[self removeObserver: self
|
||||
forKeyPath: @"isFinished"];
|
||||
while ((op = [internal->dependencies lastObject]) != nil)
|
||||
{
|
||||
[self removeDependency: op];
|
||||
|
@ -239,6 +241,11 @@ static NSArray *empty = nil;
|
|||
internal->threadPriority = 0.5;
|
||||
internal->ready = YES;
|
||||
internal->lock = [NSRecursiveLock new];
|
||||
internal->cond = [[NSConditionLock alloc] initWithCondition: 0];
|
||||
[self addObserver: self
|
||||
forKeyPath: @"isFinished"
|
||||
options: NSKeyValueObservingOptionNew
|
||||
context: NULL];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -280,13 +287,6 @@ static NSArray *empty = nil;
|
|||
{
|
||||
[internal->lock lock];
|
||||
|
||||
/* We only observe isFinished changes, and we can remove self as an
|
||||
* observer once we know the operation has finished since it can never
|
||||
* become unfinished.
|
||||
*/
|
||||
[object removeObserver: self
|
||||
forKeyPath: @"isFinished"];
|
||||
|
||||
if (object == self)
|
||||
{
|
||||
/* We have finished and need to unlock the condition lock so that
|
||||
|
@ -294,8 +294,18 @@ static NSArray *empty = nil;
|
|||
*/
|
||||
[internal->cond lock];
|
||||
[internal->cond unlockWithCondition: 1];
|
||||
[internal->lock unlock];
|
||||
return;
|
||||
}
|
||||
else if (NO == internal->ready)
|
||||
|
||||
/* We only observe isFinished changes, and we can remove self as an
|
||||
* observer once we know the operation has finished since it can never
|
||||
* become unfinished.
|
||||
*/
|
||||
[object removeObserver: self
|
||||
forKeyPath: @"isFinished"];
|
||||
|
||||
if (NO == internal->ready)
|
||||
{
|
||||
NSEnumerator *en;
|
||||
NSOperation *op;
|
||||
|
@ -482,33 +492,8 @@ static NSArray *empty = nil;
|
|||
|
||||
- (void) waitUntilFinished
|
||||
{
|
||||
if (NO == [self isFinished])
|
||||
{
|
||||
[internal->lock lock];
|
||||
if (nil == internal->cond)
|
||||
{
|
||||
/* Set up condition to wait on and observer to unblock.
|
||||
*/
|
||||
internal->cond = [[NSConditionLock alloc] initWithCondition: 0];
|
||||
[self addObserver: self
|
||||
forKeyPath: @"isFinished"
|
||||
options: NSKeyValueObservingOptionNew
|
||||
context: NULL];
|
||||
/* Some other thread could have marked us as finished while we
|
||||
* were setting up ... so we can fake the observation if needed.
|
||||
*/
|
||||
if (YES == [self isFinished])
|
||||
{
|
||||
[self observeValueForKeyPath: @"isFinished"
|
||||
ofObject: self
|
||||
change: nil
|
||||
context: nil];
|
||||
}
|
||||
}
|
||||
[internal->lock unlock];
|
||||
[internal->cond lockWhenCondition: 1]; // Wait for finish
|
||||
[internal->cond unlockWithCondition: 1]; // Signal any other watchers
|
||||
}
|
||||
[internal->cond lockWhenCondition: 1]; // Wait for finish
|
||||
[internal->cond unlockWithCondition: 1]; // Signal any other watchers
|
||||
}
|
||||
@end
|
||||
|
||||
|
|
Loading…
Reference in a new issue