Resource pools simplify storage management.
Resource pools also speed up memory management. For example, here are some memory allocation statistics from a run of `sendmail -q` that delivered 3 messages:
The second number in each pair is the size of a memory block; the first number is the number of blocks of that size. We can see that sendmail allocates large numbers of 2 byte blocks. These memory blocks can be allocated and freed more quickly using resource pools, because:18 1 82 12 87 24 7 42 2 84 3046 2 18 13 6 25 89 44 2 88 728 3 15 14 2 26 14 48 1 91 31 4 9 15 3 27 104 52 3 92 103 5 394 16 80 28 8 56 2 96 125 6 16 17 1 31 2 60 1 100 45 7 14 18 59 32 10 64 9 108 130 8 6 19 1 33 6 68 3 135 40 9 111 20 7 34 1 72 10 140 37 10 7 21 54 36 10 76 34 11 4 22 38 40 5 80
#include <sm/rpool.h> typedef void (*SM_RPOOL_RFREE_T)(void *rcontext); typedef struct sm_rpool SM_RPOOL_T; typedef ... SM_RPOOL_ATTACH_T; SM_RPOOL_T * sm_rpool_new_x( SM_RPOOL_T *parent); void sm_rpool_free( SM_RPOOL_T *rpool); void * sm_rpool_malloc_x( SM_RPOOL_T *rpool, size_t size); SM_RPOOL_ATTACH_T sm_rpool_attach_x( SM_RPOOL_T *rpool, SM_RPOOL_RFREE_T rfree, void *rcontext); void sm_rpool_detach( SM_RPOOL_ATTACH_T); void sm_rpool_setsizes( SM_RPOOL_T *rpool, size_t poolsize, size_t bigobjectsize);
If parent != NULL then the new rpool will be added as a resource to the specified parent rpool, so that when the parent is freed, the child is also freed. However, even if a parent is specified, you can free the rpool at any time, and it will be automatically disconnected from the parent.
poolsize is the number of bytes of pool memory that will be available in the next pool object to be allocated. If you happen to know the total number of bytes of memory that you will allocate from an rpool using sm_rpool_malloc_x (including alignment padding), then you can pass that value as the poolsize, and only a single pool will be allocated during the lifetime of the rpool. poolsize is an optimization, not a hard limit: if you allocate more than this number of bytes from the rpool, then more than one memory pool may be allocated by the rpool to satisfy your requests.
bigobjectsize is a value <= poolsize. It is used when an sm_rpool_malloc_x request exceeds the number of bytes available in the current pool. If the request is > bigobjectsize then the request will be satisfied by allocating a new block just for this specific request, and the current pool is not affected. If the request is <= bigobjectsize then the current pool is closed and a new memory pool is allocated, from which the request is satisfied. Consequently, no more than bigobjectsize-1 bytes will ever be wasted at the end of a given pool.
If poolsize or bigobjectsize are 0, then suitable default values are chosen.
The return value is a magic cookie which, if passed to sm_rpool_detach, disconnects the object from the resource pool, which prevents the object's free function from being called when the rpool is freed.