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

Reply via email to