Author: rfm
Date: Sat Jul 2 20:56:02 2016
New Revision: 39958
URL: http://svn.gna.org/viewcvs/gnustep?rev=39958&view=rev
Log:
Locking simplifications
Modified:
libs/base/trunk/ChangeLog
libs/base/trunk/Source/NSKeyValueObserving.m
libs/base/trunk/Source/NSOperation.m
Modified: libs/base/trunk/ChangeLog
URL:
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/ChangeLog?rev=39958&r1=39957&r2=39958&view=diff
==============================================================================
--- libs/base/trunk/ChangeLog (original)
+++ libs/base/trunk/ChangeLog Sat Jul 2 20:56:02 2016
@@ -1,3 +1,10 @@
+2016-07-02 Richard Frith-Macdonald <[email protected]>
+
+ * 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 <[email protected]>
* Source/GSICUString.m: For immutable strings, cache the string
Modified: libs/base/trunk/Source/NSKeyValueObserving.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/Source/NSKeyValueObserving.m?rev=39958&r1=39957&r2=39958&view=diff
==============================================================================
--- libs/base/trunk/Source/NSKeyValueObserving.m (original)
+++ libs/base/trunk/Source/NSKeyValueObserving.m Sat Jul 2 20:56:02 2016
@@ -1370,7 +1370,7 @@
[super dealloc];
}
-- (void) observeValueForKeyPath: (NSString *)keyPath
+- (void) oberveValueForKeyPath: (NSString *)keyPath
ofObject: (id)anObject
change: (NSDictionary *)change
context: (void *)context
@@ -1533,10 +1533,8 @@
- (void) removeObserver: (NSObject*)anObserver forKeyPath: (NSString*)aPath
{
GSKVOInfo *info;
- id forwarder;
-
- setup();
- [kvoLock lock];
+ id forwarder;
+
/*
* Get the observation information and remove this observation.
*/
@@ -1553,7 +1551,6 @@
IF_NO_GC(AUTORELEASE(info);)
[self setObservationInfo: nil];
}
- [kvoLock unlock];
if ([aPath rangeOfString:@"."].location != NSNotFound)
[forwarder finalize];
}
Modified: libs/base/trunk/Source/NSOperation.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/Source/NSOperation.m?rev=39958&r1=39957&r2=39958&view=diff
==============================================================================
--- libs/base/trunk/Source/NSOperation.m (original)
+++ libs/base/trunk/Source/NSOperation.m Sat Jul 2 20:56:02 2016
@@ -201,6 +201,8 @@
{
NSOperation *op;
+ [self removeObserver: self
+ forKeyPath: @"isFinished"];
while ((op = [internal->dependencies lastObject]) != nil)
{
[self removeDependency: op];
@@ -239,6 +241,11 @@
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;
}
@@ -279,6 +286,17 @@
context: (void *)context
{
[internal->lock lock];
+
+ if (object == self)
+ {
+ /* We have finished and need to unlock the condition lock so that
+ * any waiting thread can continue.
+ */
+ [internal->cond lock];
+ [internal->cond unlockWithCondition: 1];
+ [internal->lock unlock];
+ return;
+ }
/* We only observe isFinished changes, and we can remove self as an
* observer once we know the operation has finished since it can never
@@ -287,15 +305,7 @@
[object removeObserver: self
forKeyPath: @"isFinished"];
- if (object == self)
- {
- /* We have finished and need to unlock the condition lock so that
- * any waiting thread can continue.
- */
- [internal->cond lock];
- [internal->cond unlockWithCondition: 1];
- }
- else if (NO == internal->ready)
+ if (NO == internal->ready)
{
NSEnumerator *en;
NSOperation *op;
@@ -482,33 +492,8 @@
- (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
_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs