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

Reply via email to