Author: rfm
Date: Wed Jul 29 10:07:44 2015
New Revision: 38845
URL: http://svn.gna.org/viewcvs/gnustep?rev=38845&view=rev
Log:
New class
Modified:
libs/performance/trunk/ChangeLog
libs/performance/trunk/GSLinkedList.h
libs/performance/trunk/GSLinkedList.m
Modified: libs/performance/trunk/ChangeLog
URL:
http://svn.gna.org/viewcvs/gnustep/libs/performance/trunk/ChangeLog?rev=38845&r1=38844&r2=38845&view=diff
==============================================================================
--- libs/performance/trunk/ChangeLog (original)
+++ libs/performance/trunk/ChangeLog Wed Jul 29 10:07:44 2015
@@ -1,3 +1,11 @@
+2015-07-29 Richard Frith-Macdonald <[email protected]>
+
+ * 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 <[email protected]>
* GSFIFO.m: Implement methods that allow waiting on an empty
Modified: libs/performance/trunk/GSLinkedList.h
URL:
http://svn.gna.org/viewcvs/gnustep/libs/performance/trunk/GSLinkedList.h?rev=38845&r1=38844&r2=38845&view=diff
==============================================================================
--- libs/performance/trunk/GSLinkedList.h (original)
+++ libs/performance/trunk/GSLinkedList.h Wed Jul 29 10:07:44 2015
@@ -254,7 +254,18 @@
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,11 +273,22 @@
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.
*/
@@ -285,4 +307,80 @@
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
Modified: libs/performance/trunk/GSLinkedList.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/performance/trunk/GSLinkedList.m?rev=38845&r1=38844&r2=38845&view=diff
==============================================================================
--- libs/performance/trunk/GSLinkedList.m (original)
+++ libs/performance/trunk/GSLinkedList.m Wed Jul 29 10:07:44 2015
@@ -362,6 +362,35 @@
}
void
+GSLinkedListInsertAfter(GSListLink *link, GSLinkedList *list, GSListLink *at)
+{
+ if (nil == list->head)
+ {
+ list->head = list->tail = link;
+ }
+ else
+ {
+ if (nil == at)
+ {
+ at = list->tail;
+ }
+ 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++;
+}
+
+void
GSLinkedListInsertBefore(GSListLink *link, GSLinkedList *list, GSListLink *at)
{
if (nil == list->head)
@@ -370,6 +399,10 @@
}
else
{
+ if (nil == at)
+ {
+ at = list->head;
+ }
link->previous = at->previous;
if (nil == link->previous)
{
@@ -381,31 +414,6 @@
}
at->previous = link;
link->next = at;
- }
- link->owner = list;
- list->count++;
-}
-
-void
-GSLinkedListInsertAfter(GSListLink *link, GSLinkedList *list, GSListLink *at)
-{
- if (nil == list->head)
- {
- list->head = list->tail = 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++;
@@ -487,3 +495,128 @@
}
}
+@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;
+ }
+}
+
_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs