188 lines
6.1 KiB
HTML
188 lines
6.1 KiB
HTML
<html>
|
|
<head>
|
|
<title>libsm : Resource Pools</title>
|
|
</head>
|
|
<body>
|
|
|
|
<a href="index.html">Back to libsm overview</a>
|
|
|
|
<center>
|
|
<h1> libsm : Resource Pools </h1>
|
|
<br> $Id: rpool.html,v 1.4 2000/12/07 17:33:09 dmoen Exp $
|
|
</center>
|
|
|
|
<h2> Introduction </h2>
|
|
|
|
A resource pool is an object that owns a collection of objects
|
|
that can be freed all at once.
|
|
|
|
<p>
|
|
Resource pools simplify storage management.
|
|
|
|
<p>
|
|
Resource pools also speed up memory management.
|
|
For example, here are some memory allocation statistics from a
|
|
run of <tt>`sendmail -q`</tt> that delivered 3 messages:
|
|
<blockquote><pre>
|
|
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
|
|
</pre></blockquote>
|
|
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:
|
|
<ul>
|
|
<li>
|
|
When you allocate a small block from a resource pool, the rpool
|
|
implementation carves off a chunk of a large preallocated block,
|
|
and hands you a pointer to it.
|
|
<li>
|
|
When you free a resource pool, only a small number of large
|
|
blocks need to be freed.
|
|
</ul>
|
|
|
|
<h2> Synopsis </h2>
|
|
|
|
<pre>
|
|
#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);
|
|
</pre>
|
|
|
|
<h2> Description </h2>
|
|
|
|
<dl>
|
|
<dt>
|
|
<tt> SM_RPOOL_T *sm_rpool_new_x(SM_RPOOL_T *parent) </tt>
|
|
<dd>
|
|
Create a new resource pool object.
|
|
Raise an exception if there is insufficient heap space.
|
|
Initially, no memory is allocated for memory pools or resource lists.
|
|
<p>
|
|
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.
|
|
<p>
|
|
<dt>
|
|
<tt> void *sm_rpool_malloc_x(SM_RPOOL_T *rpool, size_t size) </tt>
|
|
<dd>
|
|
Allocate a block of memory from a memory pool owned by the rpool.
|
|
Raise an exception if there is insufficient heap space.
|
|
A series of small allocation requests can be satisfied allocating
|
|
them from the same memory pool, which reduces the number of calls
|
|
to malloc.
|
|
All of the memory allocated by sm_rpool_malloc_x is freed when
|
|
the rpool is freed, and not before then.
|
|
<p>
|
|
<dt>
|
|
<tt> void sm_rpool_setsizes(SM_RPOOL_T *rpool, size_t poolsize, size_t bigobjectsize) </tt>
|
|
<dd>
|
|
Set memory pool parameters.
|
|
You can safely call this function at any time, but an especially
|
|
good time to call it is immediately after creating the rpool,
|
|
before any pooled objects have been allocated using sm_rpool_malloc_x.
|
|
<p>
|
|
<tt>poolsize</tt> 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.
|
|
<tt>poolsize</tt> 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.
|
|
<p>
|
|
<tt>bigobjectsize</tt> is a value <= <tt>poolsize</tt>.
|
|
It is used when an <tt>sm_rpool_malloc_x</tt> request exceeds
|
|
the number of bytes available in the current pool.
|
|
If the request is > <tt>bigobjectsize</tt> 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 <= <tt>bigobjectsize</tt> then the current
|
|
pool is closed and a new memory pool is allocated, from which the
|
|
request is satisfied.
|
|
Consequently, no more than <tt>bigobjectsize-1</tt> bytes will
|
|
ever be wasted at the end of a given pool.
|
|
<p>
|
|
If poolsize or bigobjectsize are 0, then suitable default values
|
|
are chosen.
|
|
<p>
|
|
<dt>
|
|
<tt> SM_RPOOL_ATTACH_T sm_rpool_attach_x(SM_RPOOL_T *rpool, SM_RPOOL_RFREE_T rfree, void *rcontext) </tt>
|
|
<dd>
|
|
Attach an object to a resource pool, along with its free function.
|
|
When the rpool is freed, the specified object will also be freed.
|
|
Raise an exception if there is insufficient heap space.
|
|
<p>
|
|
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.
|
|
<p>
|
|
<dt>
|
|
<tt> void sm_rpool_detach(SM_RPOOL_ATTACH_T a) </tt>
|
|
<dd>
|
|
The argument is a magic cookie returned by <tt>sm_rpool_attach_t</tt>,
|
|
and refers to the object that was attached to an rpool by a specific
|
|
call to <tt>sm_rpool_attach_t</tt>.
|
|
Disconnect the object from the resource pool,
|
|
which prevents the object's free function from being called when
|
|
the rpool is freed.
|
|
<p>
|
|
<dt>
|
|
<tt> void sm_rpool_free(SM_RPOOL_T *rpool) </tt>
|
|
<dd>
|
|
Free an rpool object.
|
|
All memory allocated using sm_rpool_malloc_x
|
|
and all objects attached using sm_rpool_attach_x
|
|
are freed at this time.
|
|
If the rpool has a parent rpool, it is detached from its parent.
|
|
</dl>
|
|
|
|
</body>
|
|
</html>
|