mirror of
https://github.com/gnustep/libs-performance.git
synced 2025-02-21 02:41:01 +00:00
New class
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/performance/trunk@38845 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
e2d66ee254
commit
08cf714574
3 changed files with 264 additions and 25 deletions
|
@ -1,3 +1,11 @@
|
||||||
|
2015-07-29 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* GSLinkedList.h:
|
||||||
|
* GSLinkedList.m:
|
||||||
|
Add GSLinkedStore for a list which controls its own links and stores
|
||||||
|
unused links to avoid having to create/destroy link objects
|
||||||
|
repeatedly.
|
||||||
|
|
||||||
2015-07-17 Niels Grewe <niels.grewe@halbordnung.de>
|
2015-07-17 Niels Grewe <niels.grewe@halbordnung.de>
|
||||||
|
|
||||||
* GSFIFO.m: Implement methods that allow waiting on an empty
|
* GSFIFO.m: Implement methods that allow waiting on an empty
|
||||||
|
|
|
@ -254,7 +254,18 @@ extern GSListLink*
|
||||||
GSLinkedListFindIdentical(NSObject *object, GSLinkedList *list,
|
GSLinkedListFindIdentical(NSObject *object, GSLinkedList *list,
|
||||||
GSListLink *from, BOOL back);
|
GSListLink *from, BOOL back);
|
||||||
|
|
||||||
|
/** Returns the first object in the list.
|
||||||
|
*/
|
||||||
|
static inline id
|
||||||
|
GSLinkedListFirstObject(GSLinkedList *list)
|
||||||
|
{
|
||||||
|
if (nil == list->head)
|
||||||
|
return nil;
|
||||||
|
return list->head->item;
|
||||||
|
}
|
||||||
|
|
||||||
/** Inserts link immediately after at.<br />
|
/** Inserts link immediately after at.<br />
|
||||||
|
* If at is nil, inserts at the end of the list (link becomes tail).<br />
|
||||||
* Updates the head, tail and count variables of list.<br />
|
* Updates the head, tail and count variables of list.<br />
|
||||||
* Does not retain link.
|
* Does not retain link.
|
||||||
*/
|
*/
|
||||||
|
@ -262,12 +273,23 @@ extern void
|
||||||
GSLinkedListInsertAfter(GSListLink *link, GSLinkedList *list, GSListLink *at);
|
GSLinkedListInsertAfter(GSListLink *link, GSLinkedList *list, GSListLink *at);
|
||||||
|
|
||||||
/** Inserts link immediately before at.<br />
|
/** Inserts link immediately before at.<br />
|
||||||
|
* If at is nil, inserts at the start of the list (link becomes head).<br />
|
||||||
* Updates the head, tail and count variables of list.<br />
|
* Updates the head, tail and count variables of list.<br />
|
||||||
* Does not retain link.
|
* Does not retain link.
|
||||||
*/
|
*/
|
||||||
extern void
|
extern void
|
||||||
GSLinkedListInsertBefore(GSListLink *link, GSLinkedList *list, GSListLink *at);
|
GSLinkedListInsertBefore(GSListLink *link, GSLinkedList *list, GSListLink *at);
|
||||||
|
|
||||||
|
/** Returns the last object in the list.
|
||||||
|
*/
|
||||||
|
static inline id
|
||||||
|
GSLinkedListLastObject(GSLinkedList *list)
|
||||||
|
{
|
||||||
|
if (nil == list->tail)
|
||||||
|
return nil;
|
||||||
|
return list->tail->item;
|
||||||
|
}
|
||||||
|
|
||||||
/** Moves the link to the head of the list if it is not already there.
|
/** Moves the link to the head of the list if it is not already there.
|
||||||
*/
|
*/
|
||||||
extern void
|
extern void
|
||||||
|
@ -285,4 +307,80 @@ GSLinkedListMoveToTail(GSListLink *link, GSLinkedList *list);
|
||||||
extern void
|
extern void
|
||||||
GSLinkedListRemove(GSListLink *link, GSLinkedList *list);
|
GSLinkedListRemove(GSListLink *link, GSLinkedList *list);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** This class extends GSLinkedList by providing storage for unused links
|
||||||
|
* and re-using those links when a new link is needed.<br />
|
||||||
|
* This avoids the overhead of allocating/deallocating links and provides
|
||||||
|
* an API more like a mutable array.
|
||||||
|
*/
|
||||||
|
@interface GSLinkStore : GSLinkedList
|
||||||
|
{
|
||||||
|
@public
|
||||||
|
GSListLink *free; /** The unused links */
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds an object at the end of the list (calls -insertObject:after:).
|
||||||
|
*/
|
||||||
|
- (void) addObject: (id)anObject;
|
||||||
|
|
||||||
|
/** Returns the first object in the list or nil if the list is empty.
|
||||||
|
*/
|
||||||
|
- (id) firstObject;
|
||||||
|
|
||||||
|
/** Inserts anObject immediately after the specified link. If at is nil
|
||||||
|
* the object is inserted at the end of the list.
|
||||||
|
*/
|
||||||
|
- (void) insertObject: (id)anObject after: (GSListLink*)at;
|
||||||
|
|
||||||
|
/** Inserts anObject immediately before the specified link. If at is nil
|
||||||
|
* the object is inserted at the start of the list.
|
||||||
|
*/
|
||||||
|
- (void) insertObject: (id)anObject before: (GSListLink*)at;
|
||||||
|
|
||||||
|
/** Returns the last object in the list or nil if the list is empty.
|
||||||
|
*/
|
||||||
|
- (id) lastObject;
|
||||||
|
|
||||||
|
/** Removes any unused links from the list (to release the memory they
|
||||||
|
* occupied).
|
||||||
|
*/
|
||||||
|
- (void) purge;
|
||||||
|
|
||||||
|
/** Removes the first object from the list (or does nothing if the list
|
||||||
|
* is empty).
|
||||||
|
*/
|
||||||
|
- (void) removeFirstObject;
|
||||||
|
|
||||||
|
/** Removes the last object from the list (or does nothing if the list
|
||||||
|
* is empty).
|
||||||
|
*/
|
||||||
|
- (void) removeLastObject;
|
||||||
|
@end
|
||||||
|
|
||||||
|
/** Adds the object at the end of the list.
|
||||||
|
*/
|
||||||
|
extern void
|
||||||
|
GSLinkStoreAddObject(GSLinkStore *list, NSObject *anObject);
|
||||||
|
|
||||||
|
/** Adds the object to the list after the specified link.<br />
|
||||||
|
* Calls GSLinkedListInsertAfter().
|
||||||
|
*/
|
||||||
|
extern void
|
||||||
|
GSLinkStoreInsertObjectAfter(
|
||||||
|
NSObject *anObject, GSLinkStore *list, GSListLink *at);
|
||||||
|
|
||||||
|
/** Adds the object to the list before the specified link.<br />
|
||||||
|
* Calls GSLinkedListInsertBefore().
|
||||||
|
*/
|
||||||
|
extern void
|
||||||
|
GSLinkStoreInsertObjectBefore(
|
||||||
|
NSObject *anObject, GSLinkStore *list, GSListLink *at);
|
||||||
|
|
||||||
|
/** Removes the object held in the specified link.<br />
|
||||||
|
* If at is nil or is not owned by the list, this does nothing.
|
||||||
|
*/
|
||||||
|
extern void
|
||||||
|
GSLinkStoreRemoveObjectAt(GSLinkStore *list, GSListLink *at);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
183
GSLinkedList.m
183
GSLinkedList.m
|
@ -361,31 +361,6 @@ GSLinkedListFindIdentical(NSObject *object, GSLinkedList *list,
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
GSLinkedListInsertBefore(GSListLink *link, GSLinkedList *list, GSListLink *at)
|
|
||||||
{
|
|
||||||
if (nil == list->head)
|
|
||||||
{
|
|
||||||
list->head = list->tail = 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
|
void
|
||||||
GSLinkedListInsertAfter(GSListLink *link, GSLinkedList *list, GSListLink *at)
|
GSLinkedListInsertAfter(GSListLink *link, GSLinkedList *list, GSListLink *at)
|
||||||
{
|
{
|
||||||
|
@ -395,6 +370,10 @@ GSLinkedListInsertAfter(GSListLink *link, GSLinkedList *list, GSListLink *at)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (nil == at)
|
||||||
|
{
|
||||||
|
at = list->tail;
|
||||||
|
}
|
||||||
link->next = at->next;
|
link->next = at->next;
|
||||||
if (nil == link->next)
|
if (nil == link->next)
|
||||||
{
|
{
|
||||||
|
@ -411,6 +390,35 @@ GSLinkedListInsertAfter(GSListLink *link, GSLinkedList *list, GSListLink *at)
|
||||||
list->count++;
|
list->count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GSLinkedListInsertBefore(GSListLink *link, GSLinkedList *list, GSListLink *at)
|
||||||
|
{
|
||||||
|
if (nil == list->head)
|
||||||
|
{
|
||||||
|
list->head = list->tail = link;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (nil == at)
|
||||||
|
{
|
||||||
|
at = list->head;
|
||||||
|
}
|
||||||
|
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
|
||||||
GSLinkedListRemove(GSListLink *link, GSLinkedList *list)
|
GSLinkedListRemove(GSListLink *link, GSLinkedList *list)
|
||||||
{
|
{
|
||||||
|
@ -487,3 +495,128 @@ GSLinkedListMoveToTail(GSListLink *link, GSLinkedList *list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@implementation GSLinkStore
|
||||||
|
|
||||||
|
- (void) addObject: (id)anObject
|
||||||
|
{
|
||||||
|
GSLinkStoreInsertObjectAfter(anObject, self, tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
[self empty];
|
||||||
|
[self purge];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) empty
|
||||||
|
{
|
||||||
|
while (nil != head)
|
||||||
|
{
|
||||||
|
GSLinkStoreRemoveObjectAt(self, head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) firstObject
|
||||||
|
{
|
||||||
|
return GSLinkedListFirstObject(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) insertObject: (id)anObject after: (GSListLink*)at
|
||||||
|
{
|
||||||
|
GSLinkStoreInsertObjectAfter(anObject, self, at);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) insertObject: (id)anObject before: (GSListLink*)at
|
||||||
|
{
|
||||||
|
GSLinkStoreInsertObjectBefore(anObject, self, at);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) lastObject
|
||||||
|
{
|
||||||
|
return GSLinkedListLastObject(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) purge
|
||||||
|
{
|
||||||
|
while (nil != free)
|
||||||
|
{
|
||||||
|
GSListLink *link = free;
|
||||||
|
|
||||||
|
free = link->next;
|
||||||
|
link->next = nil;
|
||||||
|
link->owner = nil;
|
||||||
|
[link release];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) removeFirstObject
|
||||||
|
{
|
||||||
|
if (nil != head)
|
||||||
|
{
|
||||||
|
GSLinkStoreRemoveObjectAt(self, head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) removeLastObject
|
||||||
|
{
|
||||||
|
if (nil != tail)
|
||||||
|
{
|
||||||
|
GSLinkStoreRemoveObjectAt(self, tail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
void
|
||||||
|
GSLinkStoreInsertObjectAfter(
|
||||||
|
NSObject *anObject, GSLinkStore *list, GSListLink *at)
|
||||||
|
{
|
||||||
|
GSListLink *link = list->free;
|
||||||
|
|
||||||
|
if (nil == link)
|
||||||
|
{
|
||||||
|
link = [GSListLink new];
|
||||||
|
link->owner = list;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list->free = link->next;
|
||||||
|
link->next = nil;
|
||||||
|
}
|
||||||
|
link->item = [anObject retain];
|
||||||
|
GSLinkedListInsertAfter(link, list, list->tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GSLinkStoreInsertObjectBefore(
|
||||||
|
NSObject *anObject, GSLinkStore *list, GSListLink *at)
|
||||||
|
{
|
||||||
|
GSListLink *link = list->free;
|
||||||
|
|
||||||
|
if (nil == link)
|
||||||
|
{
|
||||||
|
link = [GSListLink new];
|
||||||
|
link->owner = list;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list->free = link->next;
|
||||||
|
link->next = nil;
|
||||||
|
}
|
||||||
|
link->item = [anObject retain];
|
||||||
|
GSLinkedListInsertBefore(link, list, list->head);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GSLinkStoreRemoveObjectAt(GSLinkStore *list, GSListLink *at)
|
||||||
|
{
|
||||||
|
if (nil != at && at->owner == list)
|
||||||
|
{
|
||||||
|
GSLinkedListRemove(at, list);
|
||||||
|
[at->item release];
|
||||||
|
at->next = list->free;
|
||||||
|
list->free = at;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue