SILC Runtime Toolkit 1.2 Beta 1
[runtime.git] / lib / silcutil / silcdlist.h
index 87dfb4cce6cb26871b4602d23153cd55a0e8934d..e20cdb38f6b0e5615be1aae76c7187f67abea0e1 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2000 - 2007 Pekka Riikonen
+  Copyright (C) 2000 - 2008 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 
 #include "silclist.h"
 
-/****h* silcutil/SILC Dynamic List Interface
+/****h* silcutil/Dynamic List Interface
  *
  * DESCRIPTION
  *
  * SILC Dynamic List API can be used to add opaque contexts to list that
- * will automatically allocate list entries.  Normal SILC List API cannot
+ * will automatically allocate list entries.  The simpler SilcList cannot
  * be used for this purpose because in that case the context passed to the
  * list must be defined as list structure already.  This is not the case in
  * SilcDList.  But SilcDList is a bit slower than SilcList because it
  * SILC Dynamic List is not thread-safe.  If the same list context must be
  * used in multithreaded environment concurrency control must be employed.
  *
+ * EXAMPLE
+ *
+ * SilcDList list = silc_dlist_init();
+ *
+ * silc_dlist_add(list, entry1);
+ * silc_dlist_add(list, entry2);
+ *
+ * // Traverse the list from the beginning to the end
+ * silc_dlist_start(list)
+ * while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
+ *      ...
+ * }
+ *
+ * silc_dlist_uninit(list);
+ *
  ***/
 
-/****s* silcutil/SilcDListAPI/SilcDList
+/****s* silcutil/SilcDList
  *
  * NAME
  *
@@ -52,6 +67,7 @@
  *
  ***/
 typedef struct SilcDListStruct {
+  SilcStack stack;
   SilcList list;
   void *current;
   void *prev;
@@ -65,7 +81,7 @@ typedef struct SilcDListEntryStruct {
   struct SilcDListEntryStruct *prev;
 } *SilcDListEntry;
 
-/****f* silcutil/SilcDListAPI/silc_dlist_init
+/****f* silcutil/silc_dlist_init
  *
  * SYNOPSIS
  *
@@ -74,7 +90,8 @@ typedef struct SilcDListEntryStruct {
  *
  * DESCRIPTION
  *
- *    Initializes SilcDList.
+ *    Initializes SilcDList.  Returns the SilcDList context or NULL if system
+ *    is out of memory.
  *
  ***/
 
@@ -86,13 +103,47 @@ SilcDList silc_dlist_init(void)
   list = (SilcDList)silc_malloc(sizeof(*list));
   if (!list)
     return NULL;
+  list->stack = list->current = list->prev = NULL;
+  silc_list_init_prev(list->list, struct SilcDListEntryStruct, next, prev);
+
+  return list;
+}
+
+/****f* silcutil/silc_dlist_sinit
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcDList silc_dlist_sinit(SilcStack stack);
+ *
+ * DESCRIPTION
+ *
+ *    Initializes SilcDList.  Returns the SilcDList context or NULL on error.
+ *    This is same as silc_dlist_init but allocates the memory from `stack'
+ *    if `stack' is non-NULL.
+ *
+ ***/
+
+static inline
+SilcDList silc_dlist_sinit(SilcStack stack)
+{
+  SilcDList list;
+
+  if (stack)
+    stack = silc_stack_alloc(0, stack);
+  list = (SilcDList)silc_smalloc(stack, sizeof(*list));
+  if (!list) {
+    silc_stack_free(stack);
+    return NULL;
+  }
+  list->stack = stack;
   list->current = list->prev = NULL;
   silc_list_init_prev(list->list, struct SilcDListEntryStruct, next, prev);
 
   return list;
 }
 
-/****f* silcutil/SilcDListAPI/silc_dlist_uninit
+/****f* silcutil/silc_dlist_uninit
  *
  * SYNOPSIS
  *
@@ -102,7 +153,9 @@ SilcDList silc_dlist_init(void)
  * DESCRIPTION
  *
  *    Uninits and frees all memory. Must be called to free memory. Does NOT
- *    free the contexts saved by caller.
+ *    free the contexts saved by caller.  If the silc_dlist_sinit was used
+ *    with SilcStack this will release all memory allocated by the SilcDList
+ *    back to the SilcStack.
  *
  ***/
 
@@ -111,16 +164,18 @@ void silc_dlist_uninit(SilcDList list)
 {
   if (list) {
     SilcDListEntry e;
+    SilcStack stack = list->stack;
     silc_list_start(list->list);
     while ((e = (SilcDListEntry)silc_list_get(list->list)) != SILC_LIST_END) {
       silc_list_del(list->list, e);
-      silc_free(e);
+      silc_sfree(stack, e);
     }
-    silc_free(list);
+    silc_sfree(stack, list);
+    silc_stack_free(stack);
   }
 }
 
-/****f* silcutil/SilcDListAPI/silc_dlist_count
+/****f* silcutil/silc_dlist_count
  *
  * SYNOPSIS
  *
@@ -139,7 +194,7 @@ int silc_dlist_count(SilcDList list)
   return silc_list_count(list->list);
 }
 
-/****f* silcutil/SilcDListAPI/silc_dlist_start
+/****f* silcutil/silc_dlist_start
  *
  * SYNOPSIS
  *
@@ -160,7 +215,7 @@ void silc_dlist_start(SilcDList list)
   list->current = list->prev = NULL;
 }
 
-/****f* silcutil/SilcDListAPI/silc_dlist_end
+/****f* silcutil/silc_dlist_end
  *
  * SYNOPSIS
  *
@@ -181,7 +236,7 @@ void silc_dlist_end(SilcDList list)
   list->current = list->prev = NULL;
 }
 
-/****f* silcutil/SilcDListAPI/silc_dlist_add
+/****f* silcutil/silc_dlist_add
  *
  * SYNOPSIS
  *
@@ -198,7 +253,7 @@ void silc_dlist_end(SilcDList list)
 static inline
 SilcBool silc_dlist_add(SilcDList list, void *context)
 {
-  SilcDListEntry e = (SilcDListEntry)silc_malloc(sizeof(*e));
+  SilcDListEntry e = (SilcDListEntry)silc_smalloc(list->stack, sizeof(*e));
   if (silc_unlikely(!e))
     return FALSE;
   e->context = context;
@@ -206,7 +261,7 @@ SilcBool silc_dlist_add(SilcDList list, void *context)
   return TRUE;
 }
 
-/****f* silcutil/SilcDList/silc_dlist_insert
+/****f* silcutil/silc_dlist_insert
  *
  * SYNOPSIS
  *
@@ -224,7 +279,7 @@ SilcBool silc_dlist_add(SilcDList list, void *context)
 static inline
 SilcBool silc_dlist_insert(SilcDList list, void *context)
 {
-  SilcDListEntry e = (SilcDListEntry)silc_malloc(sizeof(*e));
+  SilcDListEntry e = (SilcDListEntry)silc_smalloc(list->stack, sizeof(*e));
   if (silc_unlikely(!e))
     return FALSE;
   e->context = context;
@@ -232,7 +287,7 @@ SilcBool silc_dlist_insert(SilcDList list, void *context)
   return TRUE;
 }
 
-/****f* silcutil/SilcDListAPI/silc_dlist_del
+/****f* silcutil/silc_dlist_del
  *
  * SYNOPSIS
  *
@@ -261,13 +316,13 @@ void silc_dlist_del(SilcDList list, void *entry)
        list->current = NULL;
       if (list->prev == e)
        list->prev = NULL;
-      silc_free(e);
+      silc_sfree(list->stack, e);
       break;
     }
   }
 }
 
-/****f* silcutil/SilcDListAPI/silc_dlist_get
+/****f* silcutil/silc_dlist_get
  *
  * SYNOPSIS
  *