]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Document allocfree mempools
authorJosef 'Jeff' Sipek <jeff.sipek@dovecot.fi>
Tue, 19 Jun 2018 19:36:43 +0000 (15:36 -0400)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 4 Jul 2018 08:28:51 +0000 (08:28 +0000)
src/lib/mempool-allocfree.c

index 2019ecb410bfbef3db898dc93410ed6f922af8a8..f4af17627f4882d5146ef952cdea50336e848b23 100644 (file)
@@ -6,6 +6,88 @@
 #include "mempool.h"
 #include "llist.h"
 
+/*
+ * As the name implies, allocfree pools support both allocating and freeing
+ * memory.
+ *
+ * Implementation
+ * ==============
+ *
+ * Each allocfree pool contains a pool structure (struct allocfree_pool) to
+ * keep track of allocfree-specific pool information and zero or more blocks
+ * (struct pool_block) that keep track of ranges of memory used to back the
+ * allocations.  The blocks are kept in a doubly-linked list used to keep
+ * track of all allocations that belong to the pool.
+ *
+ * +-----------+
+ * | allocfree |
+ * |    pool   |
+ * +-----+-----+
+ *       |
+ *       | blocks +------------+ next  +------------+ next
+ *       \------->| pool block |<=====>| pool block |<=====>...<====> NULL
+ *                +------------+  prev +------------+  prev
+ *                |   <data>   |       |   <data>   |
+ *                      .                    .
+ *                      .                    .
+ *                      .              |   <data>   |
+ *                      .              +------------+
+ *                |   <data>   |
+ *                +------------+
+ *
+ * Creation
+ * --------
+ *
+ * When an allocfree pool is created the linked list of allocated blocks is
+ * initialized to be empty.
+ *
+ * Allocation & Freeing
+ * --------------------
+ *
+ * Since each allocation (via p_malloc()) corresponds to one block,
+ * allocations are simply a matter of:
+ *
+ *  - allocating enough memory from the system heap (via calloc()) to hold
+ *    the block header and the requested number of bytes,
+ *  - making a note of the user-requested size in the block header,
+ *  - adding the new block to the pool's linked list of blocks, and
+ *  - returning a pointer to the payload area of the block to the caller.
+ *
+ * Freeing memory is simpler.  The passed in pointer is converted to a
+ * struct pool_block pointer.  Then the block is removed from the pool's
+ * linked list and free()d.
+ *
+ * If the pool was created via pool_allocfree_create_clean(), all blocks are
+ * safe_memset() to zero just before being free()d.
+ *
+ * Reallocation
+ * ------------
+ *
+ * Reallocation is done by calling realloc() with a new size that is large
+ * enough to cover the requested number of bytes plus the block header
+ * overhead.
+ *
+ * Clearing
+ * --------
+ *
+ * Clearing the pool is supposed to return the pool to the same state it was
+ * in when it was first created.  To that end, the allocfree pool frees all
+ * the blocks allocated since the pool's creation.  In other words, clearing
+ * is equivalent to (but faster than) calling p_free() for each allocation
+ * in the pool.
+ *
+ * Finally, if the pool was created via pool_allocfree_create_clean(), all
+ * blocks are safe_memset() to zero before being free()d.
+ *
+ * Destruction
+ * -----------
+ *
+ * Destroying a pool first clears it (see above) and then the pool structure
+ * itself is safe_memset() to zero (if pool_allocfree_create_clean() was
+ * used) and free()d.  (The clearing leaves the pool in a minimal state
+ * with no blocks allocated.)
+ */
+
 #define MAX_ALLOC_SIZE SSIZE_T_MAX
 
 struct allocfree_pool {