mirror of
https://github.com/gnustep/libs-performance.git
synced 2025-02-16 00:21:29 +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>
|
||||
|
||||
* GSFIFO.m: Implement methods that allow waiting on an empty
|
||||
|
|
|
@ -254,7 +254,18 @@ extern GSListLink*
|
|||
GSLinkedListFindIdentical(NSObject *object, GSLinkedList *list,
|
||||
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 />
|
||||
* 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 />
|
||||
* Does not retain link.
|
||||
*/
|
||||
|
@ -262,12 +273,23 @@ extern void
|
|||
GSLinkedListInsertAfter(GSListLink *link, GSLinkedList *list, GSListLink *at);
|
||||
|
||||
/** 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 />
|
||||
* Does not retain link.
|
||||
*/
|
||||
extern void
|
||||
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.
|
||||
*/
|
||||
extern void
|
||||
|
@ -285,4 +307,80 @@ GSLinkedListMoveToTail(GSListLink *link, GSLinkedList *list);
|
|||
extern void
|
||||
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
|
||||
|
|
183
GSLinkedList.m
183
GSLinkedList.m
|
@ -361,31 +361,6 @@ GSLinkedListFindIdentical(NSObject *object, GSLinkedList *list,
|
|||
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
|
||||
GSLinkedListInsertAfter(GSListLink *link, GSLinkedList *list, GSListLink *at)
|
||||
{
|
||||
|
@ -395,6 +370,10 @@ GSLinkedListInsertAfter(GSListLink *link, GSLinkedList *list, GSListLink *at)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (nil == at)
|
||||
{
|
||||
at = list->tail;
|
||||
}
|
||||
link->next = at->next;
|
||||
if (nil == link->next)
|
||||
{
|
||||
|
@ -411,6 +390,35 @@ GSLinkedListInsertAfter(GSListLink *link, GSLinkedList *list, GSListLink *at)
|
|||
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
|
||||
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