]> mj.ucw.cz Git - libucw.git/commitdiff
Doc: Documented growing arrays, generic allocators and related things
authorMartin Mares <mj@ucw.cz>
Tue, 28 Jan 2014 21:39:20 +0000 (22:39 +0100)
committerMartin Mares <mj@ucw.cz>
Tue, 28 Jan 2014 21:39:20 +0000 (22:39 +0100)
ucw/alloc.h
ucw/doc/Makefile
ucw/doc/alloc.txt [new file with mode: 0644]
ucw/doc/conf.txt
ucw/doc/gary.txt [new file with mode: 0644]
ucw/doc/growbuf.txt
ucw/doc/index.txt
ucw/doc/relnotes.txt
ucw/gary.h

index 6292471944dccf0d79887c137c52c781166dd825..2c59928385419dcd4337f4aacc81aee36eebba92 100644 (file)
@@ -7,6 +7,10 @@
 #ifndef _UCW_ALLOC_H
 #define _UCW_ALLOC_H
 
+/**
+ * This structure describes a generic allocator. It provides pointers
+ * to three functions, which handle the actual (re)allocations.
+ **/
 struct ucw_allocator {
   void * (*alloc)(struct ucw_allocator *alloc, size_t size);
   void * (*realloc)(struct ucw_allocator *alloc, void *ptr, size_t old_size, size_t new_size);
@@ -15,7 +19,18 @@ struct ucw_allocator {
 
 /* alloc-std.c */
 
+/**
+ * [[std]]
+ * This allocator uses xmalloc(), xrealloc() and xfree(). The memory
+ * it allocates is left unitialized.
+ **/
 extern struct ucw_allocator ucw_allocator_std;
+
+/**
+ * [[zeroing]]
+ * This allocator uses xmalloc(), xrealloc() and xfree(). All memory
+ * is zeroed upon allocation.
+ **/
 extern struct ucw_allocator ucw_allocator_zeroed;
 
 #endif
index 962f168dbedeb7513134fe35ea0e9ae4276d4946..05cf5647cd46a2e452b58432598e0559307bf777 100644 (file)
@@ -2,7 +2,7 @@
 
 DIRS+=ucw/doc
 
-UCW_DOCS=basics log fastbuf index config configure install basecode hash docsys conf mempool eltpool mainloop generic growbuf unaligned lists chartype unicode prime binsearch heap binheap compress sort hashtable relnotes trans string time daemon signal varint opt
+UCW_DOCS=basics log fastbuf index config configure install basecode hash docsys conf mempool eltpool mainloop generic growbuf unaligned lists chartype unicode prime binsearch heap binheap compress sort hashtable relnotes trans string time daemon signal varint opt alloc gary
 UCW_INDEX=$(o)/ucw/doc/def_index.html
 UCW_DOCS_HTML=$(addprefix $(o)/ucw/doc/,$(addsuffix .html,$(UCW_DOCS)))
 
diff --git a/ucw/doc/alloc.txt b/ucw/doc/alloc.txt
new file mode 100644 (file)
index 0000000..adb233f
--- /dev/null
@@ -0,0 +1,24 @@
+Generic allocators
+==================
+
+Sometimes, we want to define data structures, whose memory allocation can be
+parametrized. If we wish to squeeze out the last bit of performance, we
+tie the structure to a certain allocator in compile time (as we do for
+  <<hashtable:,hash tables>>). If performance is not so critical, allocators
+can be swapped in run time.
+
+This module defines a generic interface to memory allocators. You can use
+the following pre-defined allocators, or define some of your own.
+
+* <<std,Standard malloc-based allocator>>
+* <<zeroing,Zeroing malloc-based allocator>>
+* <<mempool:fun_mp_get_allocator,Memory pools>>
+
+These data structures accept an allocator (more will come later):
+
+* Growing arrays
+
+ucw/alloc.h
+-----------
+
+!!ucw/alloc.h
index fbfa642970cc7febf61a70459216e5c79f73773d..695f78fe70e81c27eaffbd15a56db8621d338ec5 100644 (file)
@@ -153,8 +153,8 @@ For example, you can have an static array of five unsigned integers:
 *Dynamic arrays*::
   Similar to static array, but you provide pointer
   to pointer to the given item (eg. if you want dynamic array of
-  integers, you give `**int`). The parser allocates a growing array
-  (see `gary.h`) of the required size.
+  integers, you give `**int`). The parser allocates a <<gary:,growing array>>
+  of the required size.
 +
 If you want dynamic array of strings, you would use:
 +
diff --git a/ucw/doc/gary.txt b/ucw/doc/gary.txt
new file mode 100644 (file)
index 0000000..e7c78a1
--- /dev/null
@@ -0,0 +1,18 @@
+Growing arrays
+==============
+
+This module provides growing arrays with items of an arbitrary type.
+(Alternatively, you might want to use <<mempool:gbuf,growing mempool buffers>>,
+or the somewhat obsolete <<growbuf:,growing buffers>>.)
+
+From the user's point of view, the array is represented as a pointer to
+its first element, so it can be indexed by the usual `[]` operator. Please
+keep in mind that this pointer can change, whenever the array is resized.
+
+Additional book-keeping information is stored before the first element
+and it can be accessed using the macros below.
+
+ucw/gary.h
+----------
+
+!!ucw/gary.h
index 218f7d24a1002b7774a211f1f522b043049f42aa..c59c10b2b615bcdb68ce201501a219b332755a50 100644 (file)
@@ -1,13 +1,12 @@
 Growing buffers
 ===============
 
+*This module is obsolete. Please use <<gary:,growing arrays>> instead.*
+
 It is quite usual situation when you need an array of items and you
 don not know how large it will be in the time you allocate it. Then
 you need some kind of dynamically growing buffer.
 
-You can either use <<mempool:gbuf,mempools>>, which has similar
-functionality, or this module.
-
 - <<gbuf,Generic growing buffers>>
 - <<bbuf,Growing buffers for byte-sized items>>
 
index 33002353d9714c8a88196dd9a314905169b0be81..de58ab967f52b462dd6b5bfb511b8a2610cce050 100644 (file)
@@ -24,13 +24,15 @@ Modules
 - <<conf:,Configuration and command line parser>>
 - <<mempool:,Memory pools>>
 - <<eltpool:,Fixed-sized allocators>>
+- <<alloc:,Generic allocators>>
 - <<mainloop:,Mainloop>>
 - <<unaligned:,Unaligned data>>
 - <<lists:,Linked lists>>
+- <<gary:,Growing arrays>>
 - <<heap:,Binary heaps>>
 - <<binheap:,Binomial heaps>>
 - <<hashtable:,Hash tables>>
-- <<growbuf:,Growing buffers>>
+- <<growbuf:,Growing buffers>> (obsolete)
 - <<chartype:,Single-byte characters>>
 - <<unicode:,Multi-byte characters>>
 - <<varint:,Encoding of integers>>
@@ -54,8 +56,6 @@ Other features
 
 Yet undocumented modules
 ------------------------
-- Allocators
-  * `gary.h`
 - Trie
   * `trie.h`
 - Red-black trees
index 9cab40588f69818bf52c028ce1e57a99577ae9a3..88dd5ba810f185df19e8f945182f21d0cfd4af3b 100644 (file)
@@ -17,7 +17,7 @@ Release notes
   our <<conf:,configuration file parser>>. The <<conf:getopt_h,getopt>> module
   has been obsoleted
 * `<stdbool.h>` is automatically included by `<ucw/lib.h>`.
-* *Incompatible:* It turned out that almost all users of the growing array
+* *Incompatible:* It turned out that almost all users of the <<gary:,growing array>>
   module push/pop individual elements. Therefore, we have removed the second
   argument (item count) of `GARY_PUSH` and `GARY_POP`. If you want to push/pop
   multiple elements at once, use `GARY_PUSH_MULTI` and `GARY_POP_MULTI`.
@@ -28,6 +28,9 @@ Release notes
   operation was renamed to `HEAP_DELETE_MIN`. New operations `HEAP_REPLACE` and
   `HEAP_REPLACE_MIN` have been added. If you need to track positions of elements
   in the heap, please check the notes at individual functions.
+* <<alloc:,Generic allocators>> have been introduced, providing an abstract
+  way of memory allocation. <<gary:,Growing arrays>> are now based on such
+  allocators, which allows for example growing arrays in memory pools.
 * The <<conf:,configuration file parser>> has been improved:
 ** Multiple instances of the configuration parser are supported.
 ** *Incompatible:* As there may be more instances, we can no longer use
@@ -42,6 +45,10 @@ Release notes
    <<conf:fun_cf_open_group,`cf_open_group()`>>,
    <<conf:fun_cf_close_group,`cf_close_group()`>>, and
    <<conf:fun_cf_revert,`cf_revert()`>>.
+** *Incompatible:* Dynamic configuration arrays have been re-implemented in
+   terms of our generic <<gary:,growing arrays>>. This makes them easier to
+   use and most of the interface has been preserved. The only exception is
+   static allocation via the DARY_ALLOC() macro, which is no longer available.
 * <<daemon:,Daemon helpers>> have been added including a new `daemon-control`
   utility. The old `daemon-helper` utility has been obsoleted and it is not
   compiled by default.
@@ -91,7 +98,7 @@ Release notes
   mechanism for tracking resources and reporting errors. It is still considered
   experimental, so the API can change in future releases.
 
-* Added a growing array module `gary.h`, similar to `gbuf.h`, but with
+* Added a <<gary:,growing array>> module `gary.h`, similar to `gbuf.h`, but with
   a much more convenient interface.
 
 * The <<lists:,Circular linked lists>> can recognize unlinked nodes,
index 6610e7997b1fe9039e6fd89c205b89dd30b9559e..2c4c4edd513ecd999180189adeec5563f032ec55 100644 (file)
@@ -27,17 +27,58 @@ struct gary_hdr {
 #define GARY_HDR(ptr) ((struct gary_hdr *)((byte*)(ptr) - GARY_HDR_SIZE))
 #define GARY_BODY(ptr) ((byte *)(ptr) + GARY_HDR_SIZE)
 
+/**
+ * Create a new growing array, initially containing @n elements,
+ * and let @ptr point to its first element. The memory used by the
+ * array is allocated by xmalloc().
+ **/
 #define GARY_INIT(ptr, n) (ptr) = gary_init(sizeof(*(ptr)), (n), &ucw_allocator_std)
+
+/**
+ * Create a growing array like GARY_INIT() does, but all newly
+ * allocated elements will be automatically zeroed.
+ **/
 #define GARY_INIT_ZERO(ptr, n) (ptr) = gary_init(sizeof(*(ptr)), (n), &ucw_allocator_zeroed)
+
+/**
+ * Create a growing array like GARY_INIT() does, but based upon the given
+ * <<alloc:,generic allocator>>.
+ **/
 #define GARY_INIT_ALLOC(ptr, n, a) (ptr) = gary_init(sizeof(*(ptr)), (n), (a))
+
+/**
+ * Create a growing array, initially containing 0 elements, but with enough
+ * space to keep @n of them without needing reallocation. The @ptr variable
+ * will point to the first element of the array.
+ **/
 #define GARY_INIT_SPACE(ptr, n) do { GARY_INIT(ptr, n); (GARY_HDR(ptr))->num_elts = 0; } while (0)
+
+/** A combination of GARY_INIT_ZERO() and GARY_INIT_SPACE(). **/
 #define GARY_INIT_SPACE_ZERO(ptr, n) do { GARY_INIT_ZERO(ptr, n); (GARY_HDR(ptr))->num_elts = 0; } while (0)
+
+/** A combination of GARY_INIT_ALLOC() and GARY_INIT_SPACE(). **/
 #define GARY_INIT_SPACE_ALLOC(ptr, n, a) do { GARY_INIT_ALLOC(ptr, n, a); (GARY_HDR(ptr))->num_elts = 0; } while (0)
+
+/** Destroy a growing array and free memory used by it. If @ptr is NULL, nothing happens. **/
 #define GARY_FREE(ptr) gary_free(ptr)
+
+/** Return the current number elements of the given growing array. **/
 #define GARY_SIZE(ptr) (GARY_HDR(ptr)->num_elts)
+
+/**
+ * Resize the given growing array to @n elements.
+ * The @ptr can change, if the array has to be re-allocated.
+ **/
 #define GARY_RESIZE(ptr, n) ((ptr) = gary_set_size((ptr), (n)))
-#define GARY_INIT_OR_RESIZE(ptr, n) (ptr) = (ptr) ? gary_set_size((ptr), (n)) : gary_init(sizeof(*(ptr)), (n), 0)
 
+/** Create a new growing array, or resize it if it already exists. **/
+#define GARY_INIT_OR_RESIZE(ptr, n) (ptr) = (ptr) ? gary_set_size((ptr), (n)) : gary_init(sizeof(*(ptr)), (n), &ucw_allocator_std)
+
+/**
+ * Push @n elements to a growing array. That is, make space for @n more elements
+ * at the end of the array and return a pointer to the first of these elements.
+ * The @ptr can change, if the array has to be re-allocated.
+ **/
 #define GARY_PUSH_MULTI(ptr, n) ({                                     \
   struct gary_hdr *_h = GARY_HDR(ptr);                                 \
   typeof(*(ptr)) *_c = &(ptr)[_h->num_elts];                           \
@@ -46,10 +87,30 @@ struct gary_hdr {
   if (_h->num_elts > _h->have_space)                                   \
     (ptr) = gary_push_helper((ptr), _n, (byte **) &_c);                        \
   _c; })
+
+/**
+ * Push a single element at the end of a growing array and return a pointer to it.
+ * The @ptr can change, if the array has to be re-allocated.
+ **/
 #define GARY_PUSH(ptr) GARY_PUSH_MULTI(ptr, 1)
 
+/**
+ * Pop @n elements from the end of a growing array.
+ * The @ptr can change, if the array has to be re-allocated.
+ **/
 #define GARY_POP_MULTI(ptr, n) GARY_HDR(ptr)->num_elts -= (n)
+
+/**
+ * Pop a single element from the end of a growing array.
+ * The @ptr can change, if the array has to be re-allocated.
+ **/
 #define GARY_POP(ptr) GARY_POP_MULTI(ptr, 1)
+
+/**
+ * Fix size of a growing array, returning all unused memory to the
+ * system (or more precisely, to the underlying allocator).
+ * The @ptr can change.
+ **/
 #define GARY_FIX(ptr) (ptr) = gary_fix((ptr))
 
 /* Internal functions */