Author: rfm
Date: Sat May 16 12:31:08 2015
New Revision: 38506

URL: http://svn.gna.org/viewcvs/gnustep?rev=38506&view=rev
Log:
Expose GSIOThread, add easier customisation of FIFO, make IOThread pool a little
safer with checks for finished/cancelled thread and lock protection of count.


Modified:
    libs/performance/trunk/GSFIFO.h
    libs/performance/trunk/GSFIFO.m
    libs/performance/trunk/GSIOThreadPool.h
    libs/performance/trunk/GSIOThreadPool.m

Modified: libs/performance/trunk/GSFIFO.h
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/performance/trunk/GSFIFO.h?rev=38506&r1=38505&r2=38506&view=diff
==============================================================================
--- libs/performance/trunk/GSFIFO.h     (original)
+++ libs/performance/trunk/GSFIFO.h     Sat May 16 12:31:08 2015
@@ -193,6 +193,8 @@
  * The GSFIFOSingleConsumerNNN boolean is NO by default.<br />
  * The GSFIFOSingleProducerNNN boolean is NO by default.<br />
  * The GSFIFOBoundariesNNN array is missing by default.<br />
+ * If no default is found for the specific named FIFO, the default set
+ * for a FIFO with an empty name is used.
  */
 - (id) initWithName: (NSString*)n;
 

Modified: libs/performance/trunk/GSFIFO.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/performance/trunk/GSFIFO.m?rev=38506&r1=38505&r2=38506&view=diff
==============================================================================
--- libs/performance/trunk/GSFIFO.m     (original)
+++ libs/performance/trunk/GSFIFO.m     Sat May 16 12:31:08 2015
@@ -570,6 +570,7 @@
 {
   NSUserDefaults       *defs = [NSUserDefaults standardUserDefaults];
   NSString             *key;
+  NSInteger             i;
   uint16_t             g;
   uint16_t             t;
   BOOL                 mc;
@@ -577,19 +578,27 @@
   NSArray              *b;
 
   key = [NSString stringWithFormat: @"GSFIFOCapacity%@", n];
-  if ([defs integerForKey: key] > 0)
-    {
-      c = [defs integerForKey: key];
-    }
+  if (nil == [defs objectForKey: key]) key = @"GSFIFOCapacity";
+  i = [defs integerForKey: key];
+  if (i > 0)
+    {
+      c = i;
+    }
+
   key = [NSString stringWithFormat: @"GSFIFOGranularity%@", n];
+  if (nil == [defs objectForKey: key]) key = @"GSFIFOGranularity";
   g = [defs integerForKey: key];
   key = [NSString stringWithFormat: @"GSFIFOTimeout%@", n];
+  if (nil == [defs objectForKey: key]) key = @"GSFIFOTimeout";
   t = [defs integerForKey: key];
   key = [NSString stringWithFormat: @"GSFIFOSingleConsumer%@", n];
+  if (nil == [defs objectForKey: key]) key = @"GSFIFOSingleConsumer";
   mc = (YES == [defs boolForKey: key]) ? NO : YES;
   key = [NSString stringWithFormat: @"GSFIFOSingleProducer%@", n];
+  if (nil == [defs objectForKey: key]) key = @"GSFIFOSingleProducer";
   mp = (YES == [defs boolForKey: key]) ? NO : YES;
   key = [NSString stringWithFormat: @"GSFIFOBoundaries%@", n];
+  if (nil == [defs objectForKey: key]) key = @"GSFIFOBoundaries";
   b = [defs arrayForKey: key];
 
   return [self initWithCapacity: c

Modified: libs/performance/trunk/GSIOThreadPool.h
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/performance/trunk/GSIOThreadPool.h?rev=38506&r1=38505&r2=38506&view=diff
==============================================================================
--- libs/performance/trunk/GSIOThreadPool.h     (original)
+++ libs/performance/trunk/GSIOThreadPool.h     Sat May 16 12:31:08 2015
@@ -23,13 +23,32 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
    */
 #import <Foundation/NSObject.h>
+#import <Foundation/NSThread.h>
 
 #if !defined (GNUSTEP) && (MAC_OS_X_VERSION_MAX_ALLOWED<=MAC_OS_X_VERSION_10_4)
 typedef unsigned int NSUInteger;
 #endif
 
-@class NSThread;
 @class NSLock;
+@class NSTimer;
+
+/** This is the class for threads in the pool.<br />
+ * Each thread runs a runloop and is kept 'alive' waiting for a timer in
+ * the far future, but can be terminated earlier using the -terminate:
+ * method (which is called when the pool size is changed and the pool
+ * wishes to stop an idle thread).<br />
+ */
+@interface     GSIOThread : NSThread
+{
+@private
+  NSTimer      *_timer;                /** Pool termination timer */
+  NSUInteger   _count;                 /** Number of times acquired */ 
+}
+/** Terminates the thread by the specified date (as soon as possible if
+ * the date is nil or is in the past).
+ */
+- (void) terminate: (NSDate*)when;
+@end
 
 /** This class provides a thread pool for performing methods which need to
  * make use of a runloop for I/O and/or timers.<br />
@@ -61,7 +80,9 @@
  */
 + (GSIOThreadPool*) sharedPool;
 
-/** Selects a thread from the pool to be used for some job.
+/** Selects a thread from the pool to be used for some job.<br />
+ * This method selectes the least used thread in the pool (ie the
+ * one with the lowest acquire count).
  */
 - (NSThread*) acquireThread;
 
@@ -94,7 +115,10 @@
  */
 - (NSTimeInterval) timeout;
 
-/** Releases a thread previously selected from the pool.
+/** Releases a thread previously selected from the pool.  This decreases the
+ * acquire count for the thread.  If a thread has a zero acquire count, it is
+ * a candidatre for termination and removal from the pool if/when the pool
+ * has its size changed.
  */
 - (void) unacquireThread: (NSThread*)aThread;
 

Modified: libs/performance/trunk/GSIOThreadPool.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/performance/trunk/GSIOThreadPool.m?rev=38506&r1=38505&r2=38506&view=diff
==============================================================================
--- libs/performance/trunk/GSIOThreadPool.m     (original)
+++ libs/performance/trunk/GSIOThreadPool.m     Sat May 16 12:31:08 2015
@@ -31,30 +31,71 @@
 #import <Foundation/NSUserDefaults.h>
 #import        "GSIOThreadPool.h"
 
-@interface     GSIOThread : NSThread
-{
-  NSTimer      *timer;
-  @public
-  NSUInteger   count;
-}
-- (void) exit: (NSTimer*)t;
-- (void) run;
-- (void) terminate: (NSDate*)when;
+/* Protect changes to a thread's counter
+ */
+static NSLock   *countLock = nil;
+
+@interface     GSIOThread (Private)
+- (NSUInteger) _count;
+- (void) _finish: (NSTimer*)t;
+- (void) _run;
+- (void) _setCount: (NSUInteger)c;
 @end
 
+@implementation        GSIOThread (Private)
+
++ (void) initialize
+{
+  if (nil == countLock)
+    {
+      countLock = [NSLock new];
+    }
+}
+
+- (NSUInteger) _count
+{
+  return _count;
+}
+
+/* Force termination of this thread.
+ */
+- (void) _finish: (NSTimer*)t
+{
+  _timer = nil;
+  [NSThread exit];
+}
+
+/* Run the thread's main runloop until terminated.
+ */
+- (void) _run
+{
+  NSDate               *when = [NSDate distantFuture];
+  NSTimeInterval       delay = [when timeIntervalSinceNow];
+
+  _timer = [NSTimer scheduledTimerWithTimeInterval: delay
+                                           target: self
+                                         selector: @selector(_finish:)
+                                         userInfo: nil
+                                          repeats: NO];
+  [[NSRunLoop currentRunLoop] run];
+}
+
+- (void) _setCount: (NSUInteger)c
+{
+  if (NSNotFound != _count)
+    {
+      _count = c;
+    }
+}
+
+@end
+
 @implementation        GSIOThread
-
-/* Force termination of this thread.
- */
-- (void) exit: (NSTimer*)t
-{
-  [NSThread exit];
-}
 
 #if defined(GNUSTEP) || (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4)
 - (id) init
 {
-  self = [super initWithTarget: self selector: @selector(run) object: nil];
+  self = [super initWithTarget: self selector: @selector(_run) object: nil];
   if (nil != self)
     {
       [self start];
@@ -63,40 +104,38 @@
 }
 #endif
 
-/* Run the thread's main runloop until terminated.
- */
-- (void) run
-{
-  NSDate               *when = [NSDate distantFuture];
-  NSTimeInterval       delay = [when timeIntervalSinceNow];
-
-  timer = [NSTimer scheduledTimerWithTimeInterval: delay
-                                          target: self
-                                        selector: @selector(exit:)
-                                        userInfo: nil
-                                         repeats: NO];
-  [[NSRunLoop currentRunLoop] run];
-}
-
 /* End execution of the thread by the specified date.
  */
 - (void) terminate: (NSDate*)when
 {
-  NSTimeInterval       delay = [when timeIntervalSinceNow];
-
-  [timer invalidate];
+  NSTimeInterval       delay = 0.0;
+
+  if ([when isKindOfClass: [NSDate class]])
+    {
+      delay = [when timeIntervalSinceNow];
+    }
+  [_timer invalidate];
+
+  [countLock lock];
+  if (0 == _count || delay <= 0.0)
+    {
+      _count = NSNotFound;      // Mark as terminating
+      _timer = nil;
+      delay = 0.0;
+    }
+  [countLock unlock];
+
   if (delay > 0.0)
     {
-      timer = [NSTimer scheduledTimerWithTimeInterval: delay
-                                              target: self
-                                            selector: @selector(exit:)
-                                            userInfo: nil
-                                             repeats: NO];
+      _timer = [NSTimer scheduledTimerWithTimeInterval: delay
+                                               target: self
+                                             selector: @selector(_finish:)
+                                             userInfo: nil
+                                              repeats: NO];
     }
   else
     {
-      timer = nil;
-      [self exit: nil];
+      [self _finish: nil];
     }
 }
 @end
@@ -119,11 +158,20 @@
     {
       GSIOThread       *o = [a objectAtIndex: c];
 
-      if (o->count < l)
-       {
-         t = o;
-         l = o->count;
-       }
+      if ([o isExecuting])
+        {
+          NSUInteger    i;
+
+          if ((i = [o _count]) < l)
+            {
+              t = o;
+              l = i;
+            }
+        }
+      else if ([o isCancelled] || [o isFinished])
+        {
+          [a removeObjectAtIndex: c];
+        }
     }
   return t;
 }
@@ -153,6 +201,7 @@
 - (NSThread*) acquireThread
 {
   GSIOThread   *t;
+  NSUInteger    c;
 
   [poolLock lock];
   if (0 == maxThreads)
@@ -160,14 +209,17 @@
       [poolLock unlock];
       return [NSThread mainThread];
     }
+  [countLock lock];
   t = best(threads);
-  if (nil == t || (t->count > 0 && [threads count] < maxThreads))
+  if (nil == t || ((c = [t _count]) > 0 && [threads count] < maxThreads))
     {
       t = [GSIOThread new];
       [threads addObject: t];
       [t release];
-    }
-  t->count++;
+      c = 0;
+    }
+  [t _setCount: c + 1];
+  [countLock unlock];
   [poolLock unlock];
   return t;
 }
@@ -179,7 +231,7 @@
   [poolLock lock];
   if ([threads indexOfObjectIdenticalTo: aThread] != NSNotFound)
     {
-      count = ((GSIOThread*)aThread)->count;
+      count = [((GSIOThread*)aThread) _count];
     }
   [poolLock unlock];
   return count;
@@ -250,15 +302,20 @@
   [poolLock lock];
   if ([threads indexOfObjectIdenticalTo: aThread] != NSNotFound)
     {
-      if (0 == ((GSIOThread*)aThread)->count)
+      NSUInteger        c;
+
+      [countLock lock];
+      c = [((GSIOThread*)aThread) _count];
+      if (0 == c)
        {
+          [countLock unlock];
          [poolLock unlock];
          [NSException raise: NSInternalInconsistencyException
                      format: @"-unacquireThread: called too many times"];
        }
-      ((GSIOThread*)aThread)->count--;
-      if (0 == ((GSIOThread*)aThread)->count
-        && [threads count] > maxThreads)
+      [((GSIOThread*)aThread) _setCount: --c];
+      [countLock unlock];
+      if (0 == c && [threads count] > maxThreads)
         {
           [aThread retain];
           [threads removeObjectIdenticalTo: aThread];


_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs

Reply via email to