improve linked list api

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/performance/trunk@31440 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2010-09-29 14:04:18 +00:00
parent 0c664e3100
commit dd2dc9ef19
5 changed files with 641 additions and 317 deletions

View file

@ -1,3 +1,12 @@
2010-09-29 Richard Frith-Macdonald <rfm@gnu.org>
* GSLinkedList.h:
* GSLinkedList.m:
Revise structure and API for greater flexibility.
* GSThreadPool.h
* GSThreadPool.m
Modify for new linked list api.
2010-09-23 Richard Frith-Macdonald <rfm@gnu.org>
* performance/GSThreadPool.h:

View file

@ -24,107 +24,247 @@
*/
#import <Foundation/NSObject.h>
/** GSLinkedList provides simple doubly linked list functionality to
@class GSLinkedList;
/** GSListLink provides simple doubly linked list functionality to
* avoid the need to constantly re-invent it (as the OpenStep/Cocoa
* APIs do not provide this). The emphasis is on speed of operation
* so instance variables are directly accessible and functions are
* provided to manipulate them, but you can/should avoid these direct
* access features unless speed is really critical.<br />
* A list is handled simply as a pointer to the link whose 'prev'
* pointer is nil. <br />
* While the item value of a link is retaned by the link, links in a
* list are not retained, so you must manage retain/relase yourself.
* so instance variables are directly accessible and inline functions
* are provided to manipulate them (without error cehcking), but you
* can/should avoid these direct access features unless speed is
* really critical.<br />
* A list may either be 'normal' ... (where the head/tail ends of
* the list have a nil pointer to the previous/next link) or 'circular'
* in which case the list is not terminated. <br />
* The GSListLink item carries a minimal payload of a single item which
* is retained by the link.<br />
* The GSListLink owner is an optional pointer to an object which 'owns'
* the link ... a GSLinkedList instance may use this to check link
* ownership when manipulating links.
*/
@interface GSListLink : NSObject
{
@public
GSListLink *next; // Not retained
GSListLink *previous; // Not retained
GSLinkedList *owner; // Not retained
NSObject *item;
}
/** Initialise the receiver as a link for a circular linked list.
*/
- (id) initCircular;
/** Return the next item in the list containing the receiver,
* or nil if there are no more items.
*/
- (GSListLink*) next;
/** Return the list which owns the receiver or nil if the receiver is
* not in a list.
*/
- (GSLinkedList*) owner;
/** Return the previous item in the list containing the receiver,
* or nil if there are no more items.
*/
- (GSListLink*) previous;
/** Set an item value by retaining it and releasing any previous value.
*/
- (void) setItem: (NSObject*)anItem;
@end
/** Inserts link after at in a circular list.<br />
* Arguments must not be nil and link must not be in a list
* (ie its next and previous pointers must point to itsself).
*/
static inline void
GSLinkCircularInsertAfter(GSListLink *link, GSListLink *at)
{
link->next = at->next;
link->previous = at;
link->next->previous = link;
link->previous->next = link;
}
/** Inserts link before at in a circular list.<br />
* Arguments must not be nil and link must not be in a list
* (ie its next and previous pointers must point to itsself).
*/
static inline void
GSLinkCircularInsertBefore(GSListLink *link, GSListLink *at)
{
link->next = at;
link->previous = at->previous;
link->next->previous = link;
link->previous->next = link;
}
/** Removes link from any list it is in.<br />
* The link argument must not be nil.
*/
static inline void
GSLinkCircularRemove(GSListLink *link)
{
link->next->previous = link->previous;
link->previous->next = link->next;
link->next = link->previous = link;
}
/** Inserts link after at in a normal list.<br />
* Arguments must not be nil and link must not be in a list
* (ie its next and previous pointers must both be nil).
*/
static inline void
GSLinkInsertAfter(GSListLink *link, GSListLink *at)
{
if (nil != at->next)
{
at->next->previous = link;
}
link->previous = at;
at->next = link;
}
/** Inserts link before at in a normal list.<br />
* Arguments must not be nil and link must not be in a list
* (ie its next and previous pointers must both be nil).
*/
static inline void
GSLinkInsertBefore(GSListLink *link, GSListLink *at)
{
if (nil != at->previous)
{
at->previous->next = link;
}
link->next = at;
at->previous = link;
}
/** Removes link from the list it is in.<br />
* The link argument must not be nil.
*/
static inline void
GSLinkRemove(GSListLink *link)
{
if (nil != link->next)
{
link->next->previous = link->previous;
}
if (nil != link->previous)
{
link->previous->next = link->next;
}
link->next = link->previous = nil;
}
/** GSLinkedList manages a list of GSListLink objects.
*/
@interface GSLinkedList : NSObject
{
@public
GSLinkedList *next; // Not retained
GSLinkedList *prev; // Not retained
NSObject *item;
GSListLink *head; // First link in the list.
GSListLink *tail; // Last link in the list.
NSUInteger count; // Number of links in the list.
}
/** Appends other at the end of the linked list contining the receiver.
/** Appends link at the end of the linked list managed by the receiver.<br />
* Retains the link.
*/
- (void) append: (GSLinkedList*)other;
- (void) append: (GSListLink*)link;
/** Searches the linked list containing the receiver from the
* receiver onwards, returning the link containing object or nil
/** Returns the number of links in the list.
*/
- (NSUInteger) count;
/** Remove all links from the list and release them all.
*/
- (void) empty;
/** Searches the linked list returning the link containing object or nil
* if it is not found.<br />
* The comparison is performed using the -isEqual: method of object.<br />
* This method will <em>not</em> find links containins nil items.
* The comparison is performed using the [NSObject-isEqual:] method
* of object.<br />
* If start is nil then the whole list is searched.<br />
* This method will <em>not</em> find links containing nil items.
*/
- (id) findEqual: (NSObject*)object;
- (GSListLink*) findEqual: (NSObject*)object
from: (GSListLink*)start
back: (BOOL)aFlag;
/** Searches the linked list containing the receiver, from the receiver
* onwards, returning the link containing object or nil if it is not found.
/** Searches the linked list returning the link containing object or nil
* if it is not found.<br />
* If start is nil then the whole list is searched.<br />
* A direct pointer comparison is used to determine equality.
*/
- (id) findIdentical: (NSObject*)object;
- (GSListLink*) findIdentical: (NSObject*)object
from: (GSListLink*)start
back: (BOOL)aFlag;
/** Returns the first link in the list.
*/
- (id) head;
- (GSListLink*) head;
/** Inserts other immediately before the receiver.
/** Inserts other immediately after the receiver.<br />
* Retains the link.
*/
- (void) insert: (GSLinkedList*)other;
- (void) insert: (GSListLink*)link after: (GSListLink*)at;
/** Returns the item in the link represented by the receiver.<br />
* The item may be nil.
/** Inserts other immediately before the receiver.<br />
* Retains the link.
*/
- (NSObject*) item;
- (void) insert: (GSListLink*)link before: (GSListLink*)at;
/** Returns the next link in the list, or nil if the receiver is at the tail.
/** Removes the link from the receiver.<br />
* releases the link.
*/
- (id) next;
/** Returns the previous link in the list, or nil if the receiver is at the
* head.
*/
- (id) previous;
/** Removes the receiver from the linked list containing it.<br />
* Returns the link which was next after the receiver.
*/
- (id) remove;
/** Replaces any existing item in the receiver with the supplied object.<br />
* The item may be nil.
*/
- (void) setItem: (NSObject*)object;
- (void) removeLink: (GSListLink*)link;
/** Returns the last link in the list.
*/
- (id) tail;
- (GSListLink*) tail;
@end
/** Appends link at the end of the list.
/** Searches from list to the end looking for the first link containing
* object (as determined by using object's [NSObject-isEqual:] method).<br />
* If from is nil the list is search from head or tail as appropriate
* to the direction in which it is searched.
*/
extern void
GSLinkedListAppend(GSLinkedList *link, GSLinkedList *list);
extern GSListLink*
GSLinkedListFindEqual(NSObject *object, GSLinkedList *list,
GSListLink *from, BOOL back);
/** Searches from list to the end looking for the first link containing
* object (as determiend by using object's -isEqual: method).
* object (as determined by direct pointer comparison).<br />
* If from is nil the list is search from head or tail as appropriate
* to the direction in which it is searched.
*/
extern id
GSLinkedListFindEqual(NSObject *object, GSLinkedList *list);
extern GSListLink*
GSLinkedListFindIdentical(NSObject *object, GSLinkedList *list,
GSListLink *from, BOOL back);
/** Searches from list to the end looking for the first link containing
* object (as determiend by direct pointer comparison).
*/
extern id
GSLinkedListFindIdentical(NSObject *object, GSLinkedList *list);
/** Inserts link immediately before at.
/** Inserts link immediately after at.<br />
* Updates the head, tail and count variables of list.<br />
* Does not retain link.
*/
extern void
GSLinkedListInsert(GSLinkedList *link, GSLinkedList *at);
GSLinkedListInsertAfter(GSListLink *link, GSLinkedList *list, GSListLink *at);
/** Removes link from it list and returns the next item in the list
* or nil if there is no next item.
/** Inserts link immediately before at.<br />
* Updates the head, tail and count variables of list.<br />
* Does not retain link.
*/
extern id
GSLinkedListRemove(GSLinkedList *link);
extern void
GSLinkedListInsertBefore(GSListLink *link, GSLinkedList *list, GSListLink *at);
/** Removes link from the list.<br />
* Updates the head, tail and count variables of list.<br />
* Does not release link.
*/
extern void
GSLinkedListRemove(GSListLink *link, GSLinkedList *list);
#endif

View file

@ -23,186 +23,430 @@
#import <Foundation/NSException.h>
#import "GSLinkedList.h"
@implementation GSLinkedList
- (void) append: (GSLinkedList*)other
{
if (nil == other)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] nil argument",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
if (other->next || other->prev)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] other link is still in a list",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
GSLinkedListAppend(other, self);
}
@implementation GSListLink
- (void) dealloc
{
if (next || prev)
{
[NSException raise: NSInternalInconsistencyException
format: @"[%@-%@] receiver is still in a list",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
NSAssert(nil != owner, NSInternalInconsistencyException);
[item release];
[super dealloc];
}
- (id) findEqual: (NSObject*)object;
- (id) initCircular
{
return GSLinkedListFindEqual(object, self);
}
- (id) findIdentical: (NSObject*)object;
{
return GSLinkedListFindIdentical(object, self);
}
- (id) head
{
GSLinkedList *link = self;
while (nil != link->prev)
if ((self = [super init]) != nil)
{
link = link->prev;
next = previous = self;
}
return link;
return self;
}
- (void) insert: (GSLinkedList*)other
- (id) item
{
if (nil == other)
return item;
}
- (GSListLink*) next
{
if (next == self)
{
return nil;
}
return next;
}
- (GSLinkedList*) owner
{
return owner;
}
- (GSListLink*) previous
{
if (previous == self)
{
return nil;
}
return previous;
}
- (void) setItem: (NSObject*)anItem
{
id o = item;
item = [anItem retain];
[o release];
}
@end
@implementation GSLinkedList
- (void) append: (GSListLink*)link
{
if (nil == link)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] nil argument",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
if (other->next || other->prev)
if (self == link->owner)
{
if (link != tail)
{
GSLinkedListRemove(link, self);
GSLinkedListInsertAfter(link, self, tail);
}
}
else
{
if (nil != link->owner || nil != link->next || nil != link->previous)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] other link is still in a list",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
GSLinkedListInsert(other, self);
}
- (NSObject*) item
{
return item;
}
- (id) next
{
return next;
}
- (id) previous
{
return prev;
}
- (id) remove
{
return GSLinkedListRemove(self);
}
- (void) setItem: (NSObject*)object
{
id o = item;
item = [object retain];
[o release];
}
- (id) tail
{
GSLinkedList *link = self;
while (nil != link->next)
{
link = link->next;
GSLinkedListInsertAfter(link, self, tail);
[link retain];
}
return link;
}
- (NSUInteger) count
{
return count;
}
- (void) dealloc
{
count = 0;
tail = nil;
while (nil != head)
{
GSListLink *link = head;
head = link->next;
head->next = head->previous = nil;
head->owner = nil;
[head release];
}
[super dealloc];
}
- (void) empty
{
GSListLink *link;
while (nil != (link = head))
{
head = link->next;
link->owner = nil;
link->next = link->previous = nil;
[link release];
}
tail = nil;
count = 0;
}
- (GSListLink*) findEqual: (NSObject*)object
from: (GSListLink*)start
back: (BOOL)aFlag
{
if (nil != start && start->owner != self)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] start link is not in this list",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
return GSLinkedListFindEqual(object, self, start, aFlag);
}
- (GSListLink*) findIdentical: (NSObject*)object
from: (GSListLink*)start
back: (BOOL)aFlag
{
if (nil != start && start->owner != self)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] start link is not in this list",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
return GSLinkedListFindIdentical(object, self, start, aFlag);
}
- (GSListLink*) head
{
return head;
}
- (void) insert: (GSListLink*)link after: (GSListLink*)at
{
if (nil == link)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] nil link argument",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
if (nil == at)
{
at = tail;
}
if (at->owner != self)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] 'at' link is not in this list",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
if (at == link)
{
return;
}
if (link->owner == self)
{
GSLinkedListRemove(link, self);
GSLinkedListInsertAfter(link, self, at);
}
else
{
if (nil != link->owner || nil != link->next || nil != link->previous)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] other link is still in a list",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
GSLinkedListInsertAfter(link, self, at);
[link retain];
}
}
- (void) insert: (GSListLink*)link before: (GSListLink*)at
{
if (nil == link)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] nil link argument",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
if (nil == at)
{
at = head;
}
if (at->owner != self)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] 'at' link is not in this list",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
if (at == link)
{
return;
}
if (link->owner == self)
{
GSLinkedListRemove(link, self);
GSLinkedListInsertBefore(link, self, at);
}
else
{
if (nil != link->owner || nil != link->next || nil != link->previous)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] other link is still in a list",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
GSLinkedListInsertBefore(link, self, at);
[link retain];
}
}
- (void) removeLink: (GSListLink*)link
{
if (nil == link)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] nil link argument",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
if (link->owner != self)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] link is not in this list",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
GSLinkedListRemove(link, self);
[link release];
}
- (GSListLink*) tail
{
return tail;
}
@end
void
GSLinkedListAppend(GSLinkedList *link, GSLinkedList *list)
GSLinkedListInsertBefore(GSListLink *link, GSLinkedList *list, GSListLink *at)
{
while (nil != list->next)
if (nil == list->head)
{
list = list->next;
list->head = list->tail = link;
}
link->prev = list;
list->next = link;
else
{
link->previous = at->previous;
if (nil == link->previous)
{
list->head = link;
}
else
{
link->previous->next = link;
}
at->previous = link;
link->next = at;
}
link->owner = list;
list->count++;
}
void
GSLinkedListInsert(GSLinkedList *link, GSLinkedList *at)
GSLinkedListInsertAfter(GSListLink *link, GSLinkedList *list, GSListLink *at)
{
link->next = at;
if (nil != at->prev)
if (nil == list->head)
{
at->prev->next = link;
link->prev = at->prev;
list->head = list->tail = link;
}
at->prev = link;
else
{
link->next = at->next;
if (nil == link->next)
{
list->tail = link;
}
else
{
link->next->previous = link;
}
at->next = link;
link->previous = at;
}
link->owner = list;
list->count++;
}
id
GSLinkedListRemove(GSLinkedList *link)
void
GSLinkedListRemove(GSListLink *link, GSLinkedList *list)
{
GSLinkedList *next = link->next;
if (nil != link->next)
if (list->head == link)
{
link->next->prev = link->prev;
}
if (nil != link->prev)
list->head = link->next;
if (nil != list->head)
{
link->prev->next = link->next;
list->head->previous = nil;
}
link->next = nil;
link->prev = nil;
return next;
}
else
{
link->previous->next = link->next;
}
if (list->tail == link)
{
list->tail = link->previous;
if (nil != list->tail)
{
list->tail->next = nil;
}
}
else
{
link->next->previous = link->previous;
}
link->next = link->previous = nil;
link->owner = nil;
list->count--;
}
id
GSLinkedListFindEqual(NSObject *object, GSLinkedList *list)
GSListLink*
GSLinkedListFindEqual(NSObject *object, GSLinkedList *list,
GSListLink *from, BOOL back)
{
if (nil == from)
{
if (YES == back)
{
from = list->tail;
}
else
{
from = list->head;
}
}
if (nil != object)
{
BOOL (*imp)(id, SEL, id);
imp = (BOOL(*)(id,SEL,id))[object methodForSelector: @selector(isEqual:)];
while (nil != list)
if (YES == back)
{
if (YES == (*imp)(object, @selector(isEqual:), list->item))
while (nil != from)
{
return list;
if (YES == (*imp)(object, @selector(isEqual:), from->item))
{
return from;
}
from = from->previous;
}
}
else
{
while (nil != from)
{
if (YES == (*imp)(object, @selector(isEqual:), from->item))
{
return from;
}
from = from->next;
}
list = list->next;
}
}
return nil;
}
id
GSLinkedListFindIdentical(NSObject *object, GSLinkedList *list)
GSListLink*
GSLinkedListFindIdentical(NSObject *object, GSLinkedList *list,
GSListLink *from, BOOL back)
{
while (nil != list)
if (nil == from)
{
if (object == list->item)
if (YES == back)
{
return list;
from = list->tail;
}
else
{
from = list->head;
}
}
if (YES == back)
{
while (nil != from)
{
if (object == from->item)
{
return from;
}
from = from->previous;
}
}
else
{
while (nil != from)
{
if (object == from->item)
{
return from;
}
from = from->next;
}
list = list->next;
}
return nil;
}

View file

@ -24,8 +24,7 @@
*/
#import <Foundation/NSObject.h>
@class GSOperation;
@class GSThreadLink;
@class GSLinkedList;
@class NSLock;
/** This class provides a thread pool for performing methods
@ -41,16 +40,11 @@
BOOL shutdown;
BOOL suspended;
NSUInteger maxThreads;
NSUInteger threadCount;
NSUInteger activeCount;
GSThreadLink *idle;
GSThreadLink *live;
GSLinkedList *idle;
GSLinkedList *live;
NSUInteger maxOperations;
NSUInteger operationCount;
GSOperation *operations;
GSOperation *lastOperation;
NSUInteger unusedCount;
GSOperation *unused;
GSLinkedList *operations;
GSLinkedList *unused;
NSUInteger processed;
}

View file

@ -5,7 +5,7 @@
@class GSThreadPool;
@interface GSOperation : GSLinkedList
@interface GSOperation : GSListLink
{
@public
SEL sel;
@ -20,7 +20,7 @@
}
@end
@interface GSThreadLink : GSLinkedList
@interface GSThreadLink : GSListLink
{
@public
GSThreadPool *pool; // Not retained
@ -28,6 +28,7 @@
GSOperation *op;
}
@end
@implementation GSThreadLink
- (void) dealloc
{
@ -44,7 +45,7 @@
return self;
}
@end
;
@interface GSThreadPool (Internal)
- (void) _any;
- (void) _dead: (GSThreadLink*)link;
@ -58,36 +59,34 @@
- (void) dealloc
{
GSThreadLink *link;
[poolLock lock];
while (nil != operations)
[operations release];
operations = nil;
[unused release];
unused = nil;
if (nil != idle)
{
id link = operations;
operations = [link remove];
[link release];
}
while (nil != unused)
while (nil != (link = (GSThreadLink*)idle->head))
{
id link = operations;
unused = [link remove];
[link release];
}
while (nil != idle)
{
GSThreadLink *link = idle;
idle = [link remove];
GSLinkedListRemove(link, idle);
[link->lock lock];
[link->lock unlockWithCondition: 1];
}
while (nil != live)
[idle release];
idle = nil;
}
if (nil != live)
{
GSThreadLink *link = live;
live = [link remove];
while (nil != (link = (GSThreadLink*)live->head))
{
GSLinkedListRemove(link, live);
link->pool = nil;
}
[live release];
live = nil;
}
[poolLock unlock];
[poolLock release];
[super dealloc];
@ -100,8 +99,8 @@
[poolLock lock];
result = [NSString stringWithFormat:
@"%@ queue: %u(%u) threads: %u(%u) active: %u processed: %u",
[super description], operationCount, maxOperations,
threadCount, maxThreads, activeCount, processed];
[super description], operations->count, maxOperations,
idle->count + live->count, maxThreads, live->count, processed];
[poolLock unlock];
return result;
}
@ -123,15 +122,8 @@
NSUInteger counter;
[poolLock lock];
counter = operationCount;
while (nil != operations)
{
id o = operations;
operations = [o remove];
operationCount--;
[o release];
}
counter = operations->count;
[operations empty];
[poolLock unlock];
return counter;
}
@ -141,6 +133,10 @@
if ((self = [super init]) != nil)
{
poolLock = [NSRecursiveLock new];
idle = [GSLinkedList new];
live = [GSLinkedList new];
operations = [GSLinkedList new];
unused = [GSLinkedList new];
[self setOperations: 100];
[self setThreads: 2];
}
@ -149,12 +145,12 @@
- (BOOL) isEmpty
{
return (nil == operations) ? YES : NO;
return (0 == operations->count) ? YES : NO;
}
- (BOOL) isIdle
{
return (nil == live) ? YES : NO;
return (0 == live->count) ? YES : NO;
}
- (BOOL) isSuspended
@ -201,9 +197,9 @@
format: @"Nil receiver"];
}
[poolLock lock];
if (operationCount < maxOperations && maxThreads > 0)
if (operations->count < maxOperations && maxThreads > 0)
{
GSOperation *op = unused;
GSOperation *op = (GSOperation*)unused->head;
if (nil == op)
{
@ -211,23 +207,13 @@
}
else
{
unused = [op remove]; // Re-use an old one
unusedCount--;
GSLinkedListRemove(op, unused); // Re-use an old one
}
[op setItem: aReceiver];
op->sel = aSelector;
op->arg = [anArgument retain];
if (nil == operations)
{
operations = lastOperation = op;
}
else
{
[lastOperation append: op];
}
lastOperation = op;
operationCount++;
GSLinkedListInsertAfter(op, operations, operations->tail);
[self _any];
[poolLock unlock];
}
@ -276,17 +262,16 @@
}
[poolLock lock];
}
while (maxThreads < threadCount && idle != nil)
while (maxThreads < idle->count + live->count && idle->count > 0)
{
GSThreadLink *link = idle;
GSThreadLink *link = (GSThreadLink*)idle->head;
/* Remove thread link from the idle list, then start up the
* thread using the condition lock ... the thread will see
* that it has no operation to work with and will terminate
* itsself and release the link.
*/
idle = [idle remove];
threadCount--;
GSLinkedListRemove(link, idle);
[link->lock lock];
[link->lock unlockWithCondition: 1];
}
@ -313,30 +298,27 @@
{
GSOperation *op;
while (nil != (op = operations))
while (nil != (op = (GSOperation*)operations->head))
{
GSThreadLink *link = idle;
GSThreadLink *link = (GSThreadLink*)idle->head;
if (nil == link)
{
if (maxThreads > threadCount)
if (maxThreads > idle->count + live->count)
{
NSThread *thread;
/* Create a new link, add it to the idle list, and start the
* thread which will work withn it.
*/
threadCount++;
link = [GSThreadLink new];
link->pool = self;
thread = [[NSThread alloc] initWithTarget: self
selector: @selector(_run:)
object: link];
[link release]; // Retained by thread
[link setItem: thread];
[thread release]; // Retained by link
[idle insert: link];
idle = link;
GSLinkedListInsertAfter(link, idle, idle->tail);
[thread start];
}
else
@ -344,16 +326,9 @@
break; // No idle thread to perform operation
}
}
operations = [op remove];
operationCount--;
if (nil == operations)
{
lastOperation = nil;
}
idle = [link remove];
[live insert: link];
live = link;
activeCount++;
GSLinkedListRemove(op, operations);
GSLinkedListRemove(link, idle);
GSLinkedListInsertAfter(link, live, live->tail);
link->op = op;
[link->lock lock];
[link->lock unlockWithCondition: 1];
@ -364,29 +339,9 @@
- (void) _dead: (GSThreadLink*)link
{
[poolLock lock];
if (nil == link->next)
if (link->owner != nil)
{
if (link == live)
{
live = [link remove];
threadCount--;
}
else if (link == idle)
{
idle = [link remove];
threadCount--;
}
else
{
// Already dead ... don't change threadCount.
}
}
else
{
if (link == live) live = [link remove];
else if (link == idle) idle = [link remove];
else [link remove];
threadCount--;
GSLinkedListRemove(link, link->owner);
}
[poolLock unlock];
}
@ -399,28 +354,17 @@
BOOL madeIdle = YES;
[poolLock lock];
if (link == live)
if (link->owner != nil)
{
live = [link remove];
GSLinkedListRemove(link, link->owner);
}
else if (link == idle)
if (idle->count + live->count > maxThreads)
{
idle = [link remove];
}
else
{
[link remove];
}
activeCount--;
if (threadCount > maxThreads)
{
threadCount--;
madeIdle = NO; // Made dead instead
}
else
{
[idle insert: link];
idle = link;
GSLinkedListInsertAfter(link, idle, idle->tail);
}
[poolLock unlock];
return madeIdle;
@ -437,7 +381,7 @@
[poolLock lock];
processed++;
if (unusedCount < maxOperations)
if (unused->count < maxOperations)
{
if (nil != op->arg)
{
@ -445,23 +389,16 @@
op->arg = nil;
}
[op setItem: nil];
[unused insert: op];
unused = op;
unusedCount++;
GSLinkedListInsertAfter(op, unused, unused->tail);
}
else
{
[op release];
}
link->op = operations;
link->op = (GSOperation*)operations->head;
if (nil != link->op)
{
operations = [operations remove];
operationCount--;
if (nil == operations)
{
lastOperation = nil;
}
GSLinkedListRemove(link->op, operations);
more = YES;
}
[poolLock unlock];