mirror of
https://github.com/gnustep/libs-performance.git
synced 2025-02-24 12:21:23 +00:00
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:
parent
0c664e3100
commit
dd2dc9ef19
5 changed files with 641 additions and 317 deletions
|
@ -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>
|
2010-09-23 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* performance/GSThreadPool.h:
|
* performance/GSThreadPool.h:
|
||||||
|
|
266
GSLinkedList.h
266
GSLinkedList.h
|
@ -24,107 +24,247 @@
|
||||||
*/
|
*/
|
||||||
#import <Foundation/NSObject.h>
|
#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
|
* avoid the need to constantly re-invent it (as the OpenStep/Cocoa
|
||||||
* APIs do not provide this). The emphasis is on speed of operation
|
* APIs do not provide this). The emphasis is on speed of operation
|
||||||
* so instance variables are directly accessible and functions are
|
* so instance variables are directly accessible and inline functions
|
||||||
* provided to manipulate them, but you can/should avoid these direct
|
* are provided to manipulate them (without error cehcking), but you
|
||||||
* access features unless speed is really critical.<br />
|
* can/should avoid these direct access features unless speed is
|
||||||
* A list is handled simply as a pointer to the link whose 'prev'
|
* really critical.<br />
|
||||||
* pointer is nil. <br />
|
* A list may either be 'normal' ... (where the head/tail ends of
|
||||||
* While the item value of a link is retaned by the link, links in a
|
* the list have a nil pointer to the previous/next link) or 'circular'
|
||||||
* list are not retained, so you must manage retain/relase yourself.
|
* 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
|
@interface GSLinkedList : NSObject
|
||||||
{
|
{
|
||||||
@public
|
@public
|
||||||
GSLinkedList *next; // Not retained
|
GSListLink *head; // First link in the list.
|
||||||
GSLinkedList *prev; // Not retained
|
GSListLink *tail; // Last link in the list.
|
||||||
NSObject *item;
|
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
|
/** Returns the number of links in the list.
|
||||||
* receiver onwards, returning the link containing object or nil
|
*/
|
||||||
|
- (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 />
|
* if it is not found.<br />
|
||||||
* The comparison is performed using the -isEqual: method of object.<br />
|
* The comparison is performed using the [NSObject-isEqual:] method
|
||||||
* This method will <em>not</em> find links containins nil items.
|
* 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
|
/** Searches the linked list returning the link containing object or nil
|
||||||
* onwards, returning the link containing object or nil if it is not found.
|
* 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.
|
* 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.
|
/** 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 />
|
/** Inserts other immediately before the receiver.<br />
|
||||||
* The item may be nil.
|
* 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;
|
- (void) removeLink: (GSListLink*)link;
|
||||||
|
|
||||||
/** 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;
|
|
||||||
|
|
||||||
/** Returns the last link in the list.
|
/** Returns the last link in the list.
|
||||||
*/
|
*/
|
||||||
- (id) tail;
|
- (GSListLink*) tail;
|
||||||
|
|
||||||
@end
|
@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
|
extern GSListLink*
|
||||||
GSLinkedListAppend(GSLinkedList *link, GSLinkedList *list);
|
GSLinkedListFindEqual(NSObject *object, GSLinkedList *list,
|
||||||
|
GSListLink *from, BOOL back);
|
||||||
|
|
||||||
/** Searches from list to the end looking for the first link containing
|
/** 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
|
extern GSListLink*
|
||||||
GSLinkedListFindEqual(NSObject *object, GSLinkedList *list);
|
GSLinkedListFindIdentical(NSObject *object, GSLinkedList *list,
|
||||||
|
GSListLink *from, BOOL back);
|
||||||
|
|
||||||
/** Searches from list to the end looking for the first link containing
|
/** Inserts link immediately after at.<br />
|
||||||
* object (as determiend by direct pointer comparison).
|
* Updates the head, tail and count variables of list.<br />
|
||||||
*/
|
* Does not retain link.
|
||||||
extern id
|
|
||||||
GSLinkedListFindIdentical(NSObject *object, GSLinkedList *list);
|
|
||||||
|
|
||||||
/** Inserts link immediately before at.
|
|
||||||
*/
|
*/
|
||||||
extern void
|
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
|
/** Inserts link immediately before at.<br />
|
||||||
* or nil if there is no next item.
|
* Updates the head, tail and count variables of list.<br />
|
||||||
|
* Does not retain link.
|
||||||
*/
|
*/
|
||||||
extern id
|
extern void
|
||||||
GSLinkedListRemove(GSLinkedList *link);
|
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
|
#endif
|
||||||
|
|
476
GSLinkedList.m
476
GSLinkedList.m
|
@ -23,186 +23,430 @@
|
||||||
#import <Foundation/NSException.h>
|
#import <Foundation/NSException.h>
|
||||||
#import "GSLinkedList.h"
|
#import "GSLinkedList.h"
|
||||||
|
|
||||||
@implementation GSLinkedList
|
@implementation GSListLink
|
||||||
- (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);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
if (next || prev)
|
NSAssert(nil != owner, NSInternalInconsistencyException);
|
||||||
{
|
|
||||||
[NSException raise: NSInternalInconsistencyException
|
|
||||||
format: @"[%@-%@] receiver is still in a list",
|
|
||||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
|
|
||||||
}
|
|
||||||
[item release];
|
[item release];
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) findEqual: (NSObject*)object;
|
- (id) initCircular
|
||||||
{
|
{
|
||||||
return GSLinkedListFindEqual(object, self);
|
if ((self = [super init]) != nil)
|
||||||
}
|
|
||||||
|
|
||||||
- (id) findIdentical: (NSObject*)object;
|
|
||||||
{
|
|
||||||
return GSLinkedListFindIdentical(object, self);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) head
|
|
||||||
{
|
|
||||||
GSLinkedList *link = self;
|
|
||||||
|
|
||||||
while (nil != link->prev)
|
|
||||||
{
|
{
|
||||||
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
|
[NSException raise: NSInvalidArgumentException
|
||||||
format: @"[%@-%@] nil argument",
|
format: @"[%@-%@] nil argument",
|
||||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
|
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
|
[NSException raise: NSInvalidArgumentException
|
||||||
format: @"[%@-%@] other link is still in a list",
|
format: @"[%@-%@] other link is still in a list",
|
||||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
|
||||||
}
|
}
|
||||||
GSLinkedListInsert(other, self);
|
GSLinkedListInsertAfter(link, self, tail);
|
||||||
}
|
[link retain];
|
||||||
|
|
||||||
- (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;
|
|
||||||
}
|
}
|
||||||
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
|
@end
|
||||||
|
|
||||||
void
|
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;
|
else
|
||||||
list->next = link;
|
{
|
||||||
|
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
|
void
|
||||||
GSLinkedListInsert(GSLinkedList *link, GSLinkedList *at)
|
GSLinkedListInsertAfter(GSListLink *link, GSLinkedList *list, GSListLink *at)
|
||||||
{
|
{
|
||||||
link->next = at;
|
if (nil == list->head)
|
||||||
if (nil != at->prev)
|
|
||||||
{
|
{
|
||||||
at->prev->next = link;
|
list->head = list->tail = link;
|
||||||
link->prev = at->prev;
|
|
||||||
}
|
}
|
||||||
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
|
void
|
||||||
GSLinkedListRemove(GSLinkedList *link)
|
GSLinkedListRemove(GSListLink *link, GSLinkedList *list)
|
||||||
{
|
{
|
||||||
GSLinkedList *next = link->next;
|
if (list->head == link)
|
||||||
|
|
||||||
if (nil != link->next)
|
|
||||||
{
|
{
|
||||||
link->next->prev = link->prev;
|
list->head = link->next;
|
||||||
}
|
if (nil != list->head)
|
||||||
if (nil != link->prev)
|
|
||||||
{
|
{
|
||||||
link->prev->next = link->next;
|
list->head->previous = nil;
|
||||||
}
|
}
|
||||||
link->next = nil;
|
}
|
||||||
link->prev = nil;
|
else
|
||||||
return next;
|
{
|
||||||
|
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
|
GSListLink*
|
||||||
GSLinkedListFindEqual(NSObject *object, GSLinkedList *list)
|
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)
|
if (nil != object)
|
||||||
{
|
{
|
||||||
BOOL (*imp)(id, SEL, id);
|
BOOL (*imp)(id, SEL, id);
|
||||||
|
|
||||||
imp = (BOOL(*)(id,SEL,id))[object methodForSelector: @selector(isEqual:)];
|
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;
|
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;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,7 @@
|
||||||
*/
|
*/
|
||||||
#import <Foundation/NSObject.h>
|
#import <Foundation/NSObject.h>
|
||||||
|
|
||||||
@class GSOperation;
|
@class GSLinkedList;
|
||||||
@class GSThreadLink;
|
|
||||||
@class NSLock;
|
@class NSLock;
|
||||||
|
|
||||||
/** This class provides a thread pool for performing methods
|
/** This class provides a thread pool for performing methods
|
||||||
|
@ -41,16 +40,11 @@
|
||||||
BOOL shutdown;
|
BOOL shutdown;
|
||||||
BOOL suspended;
|
BOOL suspended;
|
||||||
NSUInteger maxThreads;
|
NSUInteger maxThreads;
|
||||||
NSUInteger threadCount;
|
GSLinkedList *idle;
|
||||||
NSUInteger activeCount;
|
GSLinkedList *live;
|
||||||
GSThreadLink *idle;
|
|
||||||
GSThreadLink *live;
|
|
||||||
NSUInteger maxOperations;
|
NSUInteger maxOperations;
|
||||||
NSUInteger operationCount;
|
GSLinkedList *operations;
|
||||||
GSOperation *operations;
|
GSLinkedList *unused;
|
||||||
GSOperation *lastOperation;
|
|
||||||
NSUInteger unusedCount;
|
|
||||||
GSOperation *unused;
|
|
||||||
NSUInteger processed;
|
NSUInteger processed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
177
GSThreadPool.m
177
GSThreadPool.m
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
@class GSThreadPool;
|
@class GSThreadPool;
|
||||||
|
|
||||||
@interface GSOperation : GSLinkedList
|
@interface GSOperation : GSListLink
|
||||||
{
|
{
|
||||||
@public
|
@public
|
||||||
SEL sel;
|
SEL sel;
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface GSThreadLink : GSLinkedList
|
@interface GSThreadLink : GSListLink
|
||||||
{
|
{
|
||||||
@public
|
@public
|
||||||
GSThreadPool *pool; // Not retained
|
GSThreadPool *pool; // Not retained
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
GSOperation *op;
|
GSOperation *op;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GSThreadLink
|
@implementation GSThreadLink
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
|
@ -44,7 +45,7 @@
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
;
|
|
||||||
@interface GSThreadPool (Internal)
|
@interface GSThreadPool (Internal)
|
||||||
- (void) _any;
|
- (void) _any;
|
||||||
- (void) _dead: (GSThreadLink*)link;
|
- (void) _dead: (GSThreadLink*)link;
|
||||||
|
@ -58,36 +59,34 @@
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
|
GSThreadLink *link;
|
||||||
|
|
||||||
[poolLock lock];
|
[poolLock lock];
|
||||||
while (nil != operations)
|
[operations release];
|
||||||
|
operations = nil;
|
||||||
|
[unused release];
|
||||||
|
unused = nil;
|
||||||
|
if (nil != idle)
|
||||||
{
|
{
|
||||||
id link = operations;
|
while (nil != (link = (GSThreadLink*)idle->head))
|
||||||
|
|
||||||
operations = [link remove];
|
|
||||||
[link release];
|
|
||||||
}
|
|
||||||
while (nil != unused)
|
|
||||||
{
|
{
|
||||||
id link = operations;
|
GSLinkedListRemove(link, idle);
|
||||||
|
|
||||||
unused = [link remove];
|
|
||||||
[link release];
|
|
||||||
}
|
|
||||||
while (nil != idle)
|
|
||||||
{
|
|
||||||
GSThreadLink *link = idle;
|
|
||||||
|
|
||||||
idle = [link remove];
|
|
||||||
[link->lock lock];
|
[link->lock lock];
|
||||||
[link->lock unlockWithCondition: 1];
|
[link->lock unlockWithCondition: 1];
|
||||||
}
|
}
|
||||||
while (nil != live)
|
[idle release];
|
||||||
|
idle = nil;
|
||||||
|
}
|
||||||
|
if (nil != live)
|
||||||
{
|
{
|
||||||
GSThreadLink *link = live;
|
while (nil != (link = (GSThreadLink*)live->head))
|
||||||
|
{
|
||||||
live = [link remove];
|
GSLinkedListRemove(link, live);
|
||||||
link->pool = nil;
|
link->pool = nil;
|
||||||
}
|
}
|
||||||
|
[live release];
|
||||||
|
live = nil;
|
||||||
|
}
|
||||||
[poolLock unlock];
|
[poolLock unlock];
|
||||||
[poolLock release];
|
[poolLock release];
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
|
@ -100,8 +99,8 @@
|
||||||
[poolLock lock];
|
[poolLock lock];
|
||||||
result = [NSString stringWithFormat:
|
result = [NSString stringWithFormat:
|
||||||
@"%@ queue: %u(%u) threads: %u(%u) active: %u processed: %u",
|
@"%@ queue: %u(%u) threads: %u(%u) active: %u processed: %u",
|
||||||
[super description], operationCount, maxOperations,
|
[super description], operations->count, maxOperations,
|
||||||
threadCount, maxThreads, activeCount, processed];
|
idle->count + live->count, maxThreads, live->count, processed];
|
||||||
[poolLock unlock];
|
[poolLock unlock];
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -123,15 +122,8 @@
|
||||||
NSUInteger counter;
|
NSUInteger counter;
|
||||||
|
|
||||||
[poolLock lock];
|
[poolLock lock];
|
||||||
counter = operationCount;
|
counter = operations->count;
|
||||||
while (nil != operations)
|
[operations empty];
|
||||||
{
|
|
||||||
id o = operations;
|
|
||||||
|
|
||||||
operations = [o remove];
|
|
||||||
operationCount--;
|
|
||||||
[o release];
|
|
||||||
}
|
|
||||||
[poolLock unlock];
|
[poolLock unlock];
|
||||||
return counter;
|
return counter;
|
||||||
}
|
}
|
||||||
|
@ -141,6 +133,10 @@
|
||||||
if ((self = [super init]) != nil)
|
if ((self = [super init]) != nil)
|
||||||
{
|
{
|
||||||
poolLock = [NSRecursiveLock new];
|
poolLock = [NSRecursiveLock new];
|
||||||
|
idle = [GSLinkedList new];
|
||||||
|
live = [GSLinkedList new];
|
||||||
|
operations = [GSLinkedList new];
|
||||||
|
unused = [GSLinkedList new];
|
||||||
[self setOperations: 100];
|
[self setOperations: 100];
|
||||||
[self setThreads: 2];
|
[self setThreads: 2];
|
||||||
}
|
}
|
||||||
|
@ -149,12 +145,12 @@
|
||||||
|
|
||||||
- (BOOL) isEmpty
|
- (BOOL) isEmpty
|
||||||
{
|
{
|
||||||
return (nil == operations) ? YES : NO;
|
return (0 == operations->count) ? YES : NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) isIdle
|
- (BOOL) isIdle
|
||||||
{
|
{
|
||||||
return (nil == live) ? YES : NO;
|
return (0 == live->count) ? YES : NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) isSuspended
|
- (BOOL) isSuspended
|
||||||
|
@ -201,9 +197,9 @@
|
||||||
format: @"Nil receiver"];
|
format: @"Nil receiver"];
|
||||||
}
|
}
|
||||||
[poolLock lock];
|
[poolLock lock];
|
||||||
if (operationCount < maxOperations && maxThreads > 0)
|
if (operations->count < maxOperations && maxThreads > 0)
|
||||||
{
|
{
|
||||||
GSOperation *op = unused;
|
GSOperation *op = (GSOperation*)unused->head;
|
||||||
|
|
||||||
if (nil == op)
|
if (nil == op)
|
||||||
{
|
{
|
||||||
|
@ -211,23 +207,13 @@
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unused = [op remove]; // Re-use an old one
|
GSLinkedListRemove(op, unused); // Re-use an old one
|
||||||
unusedCount--;
|
|
||||||
}
|
}
|
||||||
[op setItem: aReceiver];
|
[op setItem: aReceiver];
|
||||||
op->sel = aSelector;
|
op->sel = aSelector;
|
||||||
op->arg = [anArgument retain];
|
op->arg = [anArgument retain];
|
||||||
|
|
||||||
if (nil == operations)
|
GSLinkedListInsertAfter(op, operations, operations->tail);
|
||||||
{
|
|
||||||
operations = lastOperation = op;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
[lastOperation append: op];
|
|
||||||
}
|
|
||||||
lastOperation = op;
|
|
||||||
operationCount++;
|
|
||||||
[self _any];
|
[self _any];
|
||||||
[poolLock unlock];
|
[poolLock unlock];
|
||||||
}
|
}
|
||||||
|
@ -276,17 +262,16 @@
|
||||||
}
|
}
|
||||||
[poolLock lock];
|
[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
|
/* Remove thread link from the idle list, then start up the
|
||||||
* thread using the condition lock ... the thread will see
|
* thread using the condition lock ... the thread will see
|
||||||
* that it has no operation to work with and will terminate
|
* that it has no operation to work with and will terminate
|
||||||
* itsself and release the link.
|
* itsself and release the link.
|
||||||
*/
|
*/
|
||||||
idle = [idle remove];
|
GSLinkedListRemove(link, idle);
|
||||||
threadCount--;
|
|
||||||
[link->lock lock];
|
[link->lock lock];
|
||||||
[link->lock unlockWithCondition: 1];
|
[link->lock unlockWithCondition: 1];
|
||||||
}
|
}
|
||||||
|
@ -313,30 +298,27 @@
|
||||||
{
|
{
|
||||||
GSOperation *op;
|
GSOperation *op;
|
||||||
|
|
||||||
while (nil != (op = operations))
|
while (nil != (op = (GSOperation*)operations->head))
|
||||||
{
|
{
|
||||||
GSThreadLink *link = idle;
|
GSThreadLink *link = (GSThreadLink*)idle->head;
|
||||||
|
|
||||||
if (nil == link)
|
if (nil == link)
|
||||||
{
|
{
|
||||||
if (maxThreads > threadCount)
|
if (maxThreads > idle->count + live->count)
|
||||||
{
|
{
|
||||||
NSThread *thread;
|
NSThread *thread;
|
||||||
|
|
||||||
/* Create a new link, add it to the idle list, and start the
|
/* Create a new link, add it to the idle list, and start the
|
||||||
* thread which will work withn it.
|
* thread which will work withn it.
|
||||||
*/
|
*/
|
||||||
threadCount++;
|
|
||||||
link = [GSThreadLink new];
|
link = [GSThreadLink new];
|
||||||
link->pool = self;
|
link->pool = self;
|
||||||
thread = [[NSThread alloc] initWithTarget: self
|
thread = [[NSThread alloc] initWithTarget: self
|
||||||
selector: @selector(_run:)
|
selector: @selector(_run:)
|
||||||
object: link];
|
object: link];
|
||||||
[link release]; // Retained by thread
|
|
||||||
[link setItem: thread];
|
[link setItem: thread];
|
||||||
[thread release]; // Retained by link
|
[thread release]; // Retained by link
|
||||||
[idle insert: link];
|
GSLinkedListInsertAfter(link, idle, idle->tail);
|
||||||
idle = link;
|
|
||||||
[thread start];
|
[thread start];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -344,16 +326,9 @@
|
||||||
break; // No idle thread to perform operation
|
break; // No idle thread to perform operation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
operations = [op remove];
|
GSLinkedListRemove(op, operations);
|
||||||
operationCount--;
|
GSLinkedListRemove(link, idle);
|
||||||
if (nil == operations)
|
GSLinkedListInsertAfter(link, live, live->tail);
|
||||||
{
|
|
||||||
lastOperation = nil;
|
|
||||||
}
|
|
||||||
idle = [link remove];
|
|
||||||
[live insert: link];
|
|
||||||
live = link;
|
|
||||||
activeCount++;
|
|
||||||
link->op = op;
|
link->op = op;
|
||||||
[link->lock lock];
|
[link->lock lock];
|
||||||
[link->lock unlockWithCondition: 1];
|
[link->lock unlockWithCondition: 1];
|
||||||
|
@ -364,29 +339,9 @@
|
||||||
- (void) _dead: (GSThreadLink*)link
|
- (void) _dead: (GSThreadLink*)link
|
||||||
{
|
{
|
||||||
[poolLock lock];
|
[poolLock lock];
|
||||||
if (nil == link->next)
|
if (link->owner != nil)
|
||||||
{
|
{
|
||||||
if (link == live)
|
GSLinkedListRemove(link, link->owner);
|
||||||
{
|
|
||||||
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--;
|
|
||||||
}
|
}
|
||||||
[poolLock unlock];
|
[poolLock unlock];
|
||||||
}
|
}
|
||||||
|
@ -399,28 +354,17 @@
|
||||||
BOOL madeIdle = YES;
|
BOOL madeIdle = YES;
|
||||||
|
|
||||||
[poolLock lock];
|
[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
|
madeIdle = NO; // Made dead instead
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[idle insert: link];
|
GSLinkedListInsertAfter(link, idle, idle->tail);
|
||||||
idle = link;
|
|
||||||
}
|
}
|
||||||
[poolLock unlock];
|
[poolLock unlock];
|
||||||
return madeIdle;
|
return madeIdle;
|
||||||
|
@ -437,7 +381,7 @@
|
||||||
|
|
||||||
[poolLock lock];
|
[poolLock lock];
|
||||||
processed++;
|
processed++;
|
||||||
if (unusedCount < maxOperations)
|
if (unused->count < maxOperations)
|
||||||
{
|
{
|
||||||
if (nil != op->arg)
|
if (nil != op->arg)
|
||||||
{
|
{
|
||||||
|
@ -445,23 +389,16 @@
|
||||||
op->arg = nil;
|
op->arg = nil;
|
||||||
}
|
}
|
||||||
[op setItem: nil];
|
[op setItem: nil];
|
||||||
[unused insert: op];
|
GSLinkedListInsertAfter(op, unused, unused->tail);
|
||||||
unused = op;
|
|
||||||
unusedCount++;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[op release];
|
[op release];
|
||||||
}
|
}
|
||||||
link->op = operations;
|
link->op = (GSOperation*)operations->head;
|
||||||
if (nil != link->op)
|
if (nil != link->op)
|
||||||
{
|
{
|
||||||
operations = [operations remove];
|
GSLinkedListRemove(link->op, operations);
|
||||||
operationCount--;
|
|
||||||
if (nil == operations)
|
|
||||||
{
|
|
||||||
lastOperation = nil;
|
|
||||||
}
|
|
||||||
more = YES;
|
more = YES;
|
||||||
}
|
}
|
||||||
[poolLock unlock];
|
[poolLock unlock];
|
||||||
|
|
Loading…
Reference in a new issue