190792Sgshapiro<html> 290792Sgshapiro<head> 390792Sgshapiro <title>libsm : Resource Pools</title> 490792Sgshapiro</head> 590792Sgshapiro<body> 690792Sgshapiro 790792Sgshapiro<a href="index.html">Back to libsm overview</a> 890792Sgshapiro 990792Sgshapiro<center> 1090792Sgshapiro <h1> libsm : Resource Pools </h1> 11266711Sgshapiro <br> $Id: rpool.html,v 1.4 2000-12-07 17:33:09 dmoen Exp $ 1290792Sgshapiro</center> 1390792Sgshapiro 1490792Sgshapiro<h2> Introduction </h2> 1590792Sgshapiro 1690792SgshapiroA resource pool is an object that owns a collection of objects 1790792Sgshapirothat can be freed all at once. 1890792Sgshapiro 1990792Sgshapiro<p> 2090792SgshapiroResource pools simplify storage management. 2190792Sgshapiro 2290792Sgshapiro<p> 2390792SgshapiroResource pools also speed up memory management. 2490792SgshapiroFor example, here are some memory allocation statistics from a 2590792Sgshapirorun of <tt>`sendmail -q`</tt> that delivered 3 messages: 2690792Sgshapiro<blockquote><pre> 2790792Sgshapiro 18 1 82 12 87 24 7 42 2 84 2890792Sgshapiro 3046 2 18 13 6 25 89 44 2 88 2990792Sgshapiro 728 3 15 14 2 26 14 48 1 91 3090792Sgshapiro 31 4 9 15 3 27 104 52 3 92 3190792Sgshapiro 103 5 394 16 80 28 8 56 2 96 3290792Sgshapiro 125 6 16 17 1 31 2 60 1 100 3390792Sgshapiro 45 7 14 18 59 32 10 64 9 108 3490792Sgshapiro 130 8 6 19 1 33 6 68 3 135 3590792Sgshapiro 40 9 111 20 7 34 1 72 10 140 3690792Sgshapiro 37 10 7 21 54 36 10 76 3790792Sgshapiro 34 11 4 22 38 40 5 80 3890792Sgshapiro</pre></blockquote> 3990792SgshapiroThe second number in each pair is the size of a memory block; the first 4090792Sgshapironumber is the number of blocks of that size. We can see that sendmail 4190792Sgshapiroallocates large numbers of 2 byte blocks. These memory blocks can be 4290792Sgshapiroallocated and freed more quickly using resource pools, because: 4390792Sgshapiro<ul> 4490792Sgshapiro<li> 4590792Sgshapiro When you allocate a small block from a resource pool, the rpool 4690792Sgshapiro implementation carves off a chunk of a large preallocated block, 4790792Sgshapiro and hands you a pointer to it. 4890792Sgshapiro<li> 4990792Sgshapiro When you free a resource pool, only a small number of large 5090792Sgshapiro blocks need to be freed. 5190792Sgshapiro</ul> 5290792Sgshapiro 5390792Sgshapiro<h2> Synopsis </h2> 5490792Sgshapiro 5590792Sgshapiro<pre> 5690792Sgshapiro#include <sm/rpool.h> 5790792Sgshapiro 5890792Sgshapirotypedef void (*SM_RPOOL_RFREE_T)(void *rcontext); 5990792Sgshapirotypedef struct sm_rpool SM_RPOOL_T; 6090792Sgshapirotypedef ... SM_RPOOL_ATTACH_T; 6190792Sgshapiro 6290792SgshapiroSM_RPOOL_T * 6390792Sgshapirosm_rpool_new_x( 6490792Sgshapiro SM_RPOOL_T *parent); 6590792Sgshapiro 6690792Sgshapirovoid 6790792Sgshapirosm_rpool_free( 6890792Sgshapiro SM_RPOOL_T *rpool); 6990792Sgshapiro 7090792Sgshapirovoid * 7190792Sgshapirosm_rpool_malloc_x( 7290792Sgshapiro SM_RPOOL_T *rpool, 7390792Sgshapiro size_t size); 7490792Sgshapiro 7590792SgshapiroSM_RPOOL_ATTACH_T 7690792Sgshapirosm_rpool_attach_x( 7790792Sgshapiro SM_RPOOL_T *rpool, 7890792Sgshapiro SM_RPOOL_RFREE_T rfree, 7990792Sgshapiro void *rcontext); 8090792Sgshapiro 8190792Sgshapirovoid 8290792Sgshapirosm_rpool_detach( 8390792Sgshapiro SM_RPOOL_ATTACH_T); 8490792Sgshapiro 8590792Sgshapirovoid 8690792Sgshapirosm_rpool_setsizes( 8790792Sgshapiro SM_RPOOL_T *rpool, 8890792Sgshapiro size_t poolsize, 8990792Sgshapiro size_t bigobjectsize); 9090792Sgshapiro</pre> 9190792Sgshapiro 9290792Sgshapiro<h2> Description </h2> 9390792Sgshapiro 9490792Sgshapiro<dl> 9590792Sgshapiro<dt> 9690792Sgshapiro<tt> SM_RPOOL_T *sm_rpool_new_x(SM_RPOOL_T *parent) </tt> 9790792Sgshapiro<dd> 9890792Sgshapiro Create a new resource pool object. 9990792Sgshapiro Raise an exception if there is insufficient heap space. 10090792Sgshapiro Initially, no memory is allocated for memory pools or resource lists. 10190792Sgshapiro <p> 10290792Sgshapiro If parent != NULL then the new rpool will be added as a resource 10390792Sgshapiro to the specified parent rpool, so that when the parent is freed, 10490792Sgshapiro the child is also freed. However, even if a parent is specified, 10590792Sgshapiro you can free the rpool at any time, and it will be automatically 10690792Sgshapiro disconnected from the parent. 10790792Sgshapiro <p> 10890792Sgshapiro<dt> 10990792Sgshapiro<tt> void *sm_rpool_malloc_x(SM_RPOOL_T *rpool, size_t size) </tt> 11090792Sgshapiro<dd> 11190792Sgshapiro Allocate a block of memory from a memory pool owned by the rpool. 11290792Sgshapiro Raise an exception if there is insufficient heap space. 11390792Sgshapiro A series of small allocation requests can be satisfied allocating 11490792Sgshapiro them from the same memory pool, which reduces the number of calls 11590792Sgshapiro to malloc. 11690792Sgshapiro All of the memory allocated by sm_rpool_malloc_x is freed when 11790792Sgshapiro the rpool is freed, and not before then. 11890792Sgshapiro <p> 11990792Sgshapiro<dt> 12090792Sgshapiro<tt> void sm_rpool_setsizes(SM_RPOOL_T *rpool, size_t poolsize, size_t bigobjectsize) </tt> 12190792Sgshapiro<dd> 12290792Sgshapiro Set memory pool parameters. 12390792Sgshapiro You can safely call this function at any time, but an especially 12490792Sgshapiro good time to call it is immediately after creating the rpool, 12590792Sgshapiro before any pooled objects have been allocated using sm_rpool_malloc_x. 12690792Sgshapiro <p> 12790792Sgshapiro <tt>poolsize</tt> is the number of bytes of pool memory 12890792Sgshapiro that will be available in the next pool object to be allocated. 12990792Sgshapiro If you happen to know the total number of bytes of memory that 13090792Sgshapiro you will allocate from an rpool using sm_rpool_malloc_x 13190792Sgshapiro (including alignment padding), then you can pass that value 13290792Sgshapiro as the poolsize, and only a single pool will be allocated 13390792Sgshapiro during the lifetime of the rpool. 13490792Sgshapiro <tt>poolsize</tt> is an optimization, not a hard limit: 13590792Sgshapiro if you allocate more than this number of bytes from the rpool, 13690792Sgshapiro then more than one memory pool may be allocated by the rpool 13790792Sgshapiro to satisfy your requests. 13890792Sgshapiro <p> 13990792Sgshapiro <tt>bigobjectsize</tt> is a value <= <tt>poolsize</tt>. 14090792Sgshapiro It is used when an <tt>sm_rpool_malloc_x</tt> request exceeds 14190792Sgshapiro the number of bytes available in the current pool. 14290792Sgshapiro If the request is > <tt>bigobjectsize</tt> then the request 14390792Sgshapiro will be satisfied by allocating a new block just for this specific 14490792Sgshapiro request, and the current pool is not affected. 14590792Sgshapiro If the request is <= <tt>bigobjectsize</tt> then the current 14690792Sgshapiro pool is closed and a new memory pool is allocated, from which the 14790792Sgshapiro request is satisfied. 14890792Sgshapiro Consequently, no more than <tt>bigobjectsize-1</tt> bytes will 14990792Sgshapiro ever be wasted at the end of a given pool. 15090792Sgshapiro <p> 15190792Sgshapiro If poolsize or bigobjectsize are 0, then suitable default values 15290792Sgshapiro are chosen. 15390792Sgshapiro <p> 15490792Sgshapiro<dt> 15590792Sgshapiro<tt> SM_RPOOL_ATTACH_T sm_rpool_attach_x(SM_RPOOL_T *rpool, SM_RPOOL_RFREE_T rfree, void *rcontext) </tt> 15690792Sgshapiro<dd> 15790792Sgshapiro Attach an object to a resource pool, along with its free function. 15890792Sgshapiro When the rpool is freed, the specified object will also be freed. 15990792Sgshapiro Raise an exception if there is insufficient heap space. 16090792Sgshapiro <p> 16190792Sgshapiro The return value is a magic cookie which, if passed to 16290792Sgshapiro sm_rpool_detach, disconnects the object from the resource pool, 16390792Sgshapiro which prevents the object's free function from being called when 16490792Sgshapiro the rpool is freed. 16590792Sgshapiro <p> 16690792Sgshapiro<dt> 16790792Sgshapiro<tt> void sm_rpool_detach(SM_RPOOL_ATTACH_T a) </tt> 16890792Sgshapiro<dd> 16990792Sgshapiro The argument is a magic cookie returned by <tt>sm_rpool_attach_t</tt>, 17090792Sgshapiro and refers to the object that was attached to an rpool by a specific 17190792Sgshapiro call to <tt>sm_rpool_attach_t</tt>. 17290792Sgshapiro Disconnect the object from the resource pool, 17390792Sgshapiro which prevents the object's free function from being called when 17490792Sgshapiro the rpool is freed. 17590792Sgshapiro <p> 17690792Sgshapiro<dt> 17790792Sgshapiro<tt> void sm_rpool_free(SM_RPOOL_T *rpool) </tt> 17890792Sgshapiro<dd> 17990792Sgshapiro Free an rpool object. 18090792Sgshapiro All memory allocated using sm_rpool_malloc_x 18190792Sgshapiro and all objects attached using sm_rpool_attach_x 18290792Sgshapiro are freed at this time. 18390792Sgshapiro If the rpool has a parent rpool, it is detached from its parent. 18490792Sgshapiro</dl> 18590792Sgshapiro 18690792Sgshapiro</body> 18790792Sgshapiro</html> 188