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 &lt;sm/rpool.h&gt;
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 &lt;= <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 &gt; <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 &lt;= <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