SILC Runtime Toolkit 1.2 Beta 1
[runtime.git] / lib / silcutil / silcstack.h
1 /*
2
3   silcstack.h
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2003 - 2008 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 /****h* silcutil/Memory Pool Interface
21  *
22  * DESCRIPTION
23  *
24  * SilcStack is a pre-allocated memory pool system which allows fast memory
25  * allocation for routines and applications that frequently allocate small
26  * amounts of memory.  Other advantage of this system is that there are no
27  * memory leaks, as long as the stack is freed eventually.  Since the stack
28  * is usually allocated only once this is not an issue.
29  *
30  * SilcStack supports stack pushing and popping allowing to push the stack,
31  * allocate memory and then pop it to free the allocated memory.  The freeing
32  * does not actually do any real memory freeing so it is optimized for
33  * performance.  The memory alignment may also be specified by user for
34  * the stack.  This allows the caller to use special alignment for memory
35  * allocations, if needed.
36  *
37  * SilcStack is also a full featured memory pool which allows user to group
38  * together multiple stacks.  Child stacks may be created from a parent stack
39  * without consuming the parent stack.  When the child is freed, its memory
40  * is returned back to the parent and can be used again by other childs.
41  * It is also possible to create child stacks from another child stack.
42  *
43  * A basic set of utility functions are provided for application that wish
44  * to use the SilcStack as their primary memory allocation source.  The
45  * following functions (among many others) support SilcStack:
46  *
47  * silc_smalloc, silc_smalloc, silc_scalloc, silc_srealloc, silc_smemdup,
48  * silc_sfree, silc_sstrdup, silc_buffer_salloc, silc_buffer_salloc_size,
49  * silc_buffer_srealloc, silc_buffer_srealloc_size, silc_buffer_scopy,
50  * silc_buffer_sclone, silc_buffer_sformat, silc_buffer_sformat_vp,
51  * silc_buffer_sstrformat, silc_buffer_senlarge, silc_dlist_sinit,
52  * silc_hash_table_alloc
53  *
54  * The SilcStack is not thread-safe so that same context could be used for
55  * allocations from multiple threads.  It is however safe to create and use
56  * child stacks in a different thread from the parent stack.  Each thread
57  * should allocate their own SilcStack, however they may be child stacks.
58  *
59  ***/
60
61 #ifndef SILCSTACK_H
62 #define SILCSTACK_H
63
64 /****s* silcutil/SilcStack
65  *
66  * NAME
67  *
68  *    typedef struct SilcStackStruct *SilcStack;
69  *
70  * DESCRIPTION
71  *
72  *    This context represents the stack and it is allocated by
73  *    silc_stack_alloc and is destroyed with silc_stack_free functions.
74  *    The context is given as argument to all routines that use this
75  *    stack allocation library.
76  *
77  ***/
78 typedef struct SilcStackStruct *SilcStack;
79
80 /****s* silcutil/SilcStackFrame
81  *
82  * NAME
83  *
84  *    typedef struct SilcStackFrameStruct SilcStackFrame;
85  *
86  * DESCRIPTION
87  *
88  *    Static stack frame context that optionally can be used as stack
89  *    frame in SilcStack.  By default silc_stack_push use pre-allocated
90  *    stack frame, but user may also use statically allocated SilcStackFrame
91  *    instead.  This is recommended when using SilcStack in recursive routine
92  *    and the recursion may become deep.  Using static frame assures that
93  *    during recursion frames never run out.
94  *
95  ***/
96 typedef struct SilcStackFrameStruct SilcStackFrame;
97
98 /****f* silcutil/SilcStackOomHandler
99  *
100  * SYNOPSIS
101  *
102  *    typedef void (*SilcStackOomHandler)(SilcStack stack, void *context);
103  *
104  * DESCRIPTION
105  *
106  *    Callback of this type can be given to silc_stack_set_oom_handler
107  *    to set Out of Memory handler to `stack'.  If memory allocation from
108  *    `stack' fails this callback is called to indicate error.  The `context'
109  *    is the context given to silc_stack_set_oom_handler.
110  *
111  ***/
112 typedef void (*SilcStackOomHandler)(SilcStack stack, void *context);
113
114 /****f* silcutil/silc_stack_alloc
115  *
116  * SYNOPSIS
117  *
118  *    SilcStack silc_stack_alloc(SilcUInt32 stack_size, SilcStack parent);
119  *
120  * DESCRIPTION
121  *
122  *    Allocates new data stack that can be used as stack for fast memory
123  *    allocation by various routines.  Returns the pointer to the stack
124  *    that must be freed with silc_stack_free function when it is not
125  *    needed anymore.  If the `stack_size' is zero (0) by default a
126  *    1 kilobyte (1024 bytes) stack is allocated.
127  *
128  *    If `parent' is non-NULL the created stack is a child of the `parent'
129  *    stack.  All of childs the memory is allocated from the `parent' and
130  *    will be returned back to the parent when the child is freed.  Note
131  *    that, even though child allocates memory from the parent, the parent's
132  *    stack is not consumed.
133  *
134  *    Returns NULL on error and sets silc_errno.
135  *
136  ***/
137 SilcStack silc_stack_alloc(SilcUInt32 stack_size, SilcStack parent);
138
139 /****f* silcutil/silc_stack_free
140  *
141  * SYNOPSIS
142  *
143  *    void silc_stack_free(SilcStack stack);
144  *
145  * DESCRIPTION
146  *
147  *    Frees the data stack context.  The stack cannot be used anymore after
148  *    this and all allocated memory are freed.
149  *
150  *    If `stack' is a child stack, its memory is returned back to its
151  *    parent.  If `stack' is NULL this function does nothing.
152  *
153  ***/
154 void silc_stack_free(SilcStack stack);
155
156 /****f* silcutil/silc_stack_push
157  *
158  * SYNOPSIS
159  *
160  *    SilcUInt32 silc_stack_push(SilcStack stack, SilcStackFrame *frame);
161  *
162  * DESCRIPTION
163  *
164  *    Push the top of the stack and add new stack frame on top of the stack.
165  *    For every silc_stack_push call there must be silc_stack_pop call.  All
166  *    allocations between these two calls will be done from the top of the
167  *    stack and all allocated memory is freed after the next silc_stack_pop
168  *    is called.  This returns so called stack pointer for the new stack
169  *    frame, which the caller may use to check that all calls to
170  *    silc_stack_pop has been made.
171  *
172  *    If the `frame' is non-NULL then that SilcStackFrame is used as
173  *    stack frame.  Usually `frame' is set to NULL by user.  Statically
174  *    allocated SilcStackFrame should be used when using silc_stack_push
175  *    in recursive function and the recursion may become deep.  In this
176  *    case using statically allocated SilcStackFrame is recommended since
177  *    it assures that frames never run out.  If your routine is not recursive
178  *    then setting `frame' to NULL is recommended.
179  *
180  *    This function is used when a routine is doing frequent allocations
181  *    from the stack.  If the stack is not pushed and later popped all
182  *    allocations are made from the stack and the stack eventually runs out
183  *    (it gets enlarged by normal memory allocation).  By pushing and then
184  *    later popping the frequent allocations does not consume the stack.
185  *
186  *    If `stack' is NULL this call has no effect.  This function does not
187  *    allocate any memory.
188  *
189  * EXAMPLE
190  *
191  *    All memory allocations in silc_foo_parse_packet will be done in
192  *    a fresh stack frame and that data is freed after the parsing is
193  *    completed.
194  *
195  *    silc_stack_push(stack, NULL);
196  *    silc_foo_parse_packet(packet, stack);
197  *    silc_stack_pop(stack);
198  *
199  *    Another example with recursion and using statically allocated
200  *    SilcStackFrame.  After popping the statically allocated frame can
201  *    be reused if necessary.
202  *
203  *    void silc_foo_this_function(SilcStack stack)
204  *    {
205  *      SilcStackFrame frame;
206  *      ...
207  *      silc_stack_push(stack, &frame);
208  *      silc_foo_this_function(stack);   // Call recursively
209  *      silc_stack_pop(stack);
210  *      ...
211  *    }
212  *
213  ***/
214 SilcUInt32 silc_stack_push(SilcStack stack, SilcStackFrame *frame);
215
216 /****f* silcutil/silc_stack_pop
217  *
218  * SYNOPSIS
219  *
220  *    SilcUInt32 silc_stack_pop(SilcStack stack);
221  *
222  * DESCRIPTION
223  *
224  *    Pop the top of the stack to remove the previous stack frame and use
225  *    previous frame as top of the stack.  After popping, memory allocated in
226  *    the old frame is freed.  For each silc_stack_push call there must be
227  *    silc_stack_pop call to free all memory (in reality any memory is not
228  *    freed but within the stack it is).  This returns the stack pointer of
229  *    old frame after popping and caller may check that it is same as
230  *    returned by the silc_stack_push.  If it they differ, some routine
231  *    has called silc_stack_push but has not called silc_stack_pop, or
232  *    silc_stack_pop has been called too many times.  Application should
233  *    treat this as a fatal error, as it is a bug in the application code.
234  *
235  *    If `stack' is NULL this call has no effect.   This function does not
236  *    allocate any memory.
237  *
238  * EXAMPLE
239  *
240  *    This example saves the stack pointer which is checked when popping
241  *    the current stack frame.  If the stack pointer differs then someone
242  *    has pushed the stack frame but forgot to pop it (or has called it
243  *    too many times).
244  *
245  *    sp = silc_stack_push(stack, NULL);
246  *    silc_foo_parse_packet(packet, stack);
247  *    if (silc_stack_pop(stack) != sp)
248  *      fatal("corrupted stack");
249  *
250  ***/
251 SilcUInt32 silc_stack_pop(SilcStack stack);
252
253 /****f* silcutil/silc_stack_malloc
254  *
255  * SYNOPSIS
256  *
257  *    void *silc_stack_malloc(SilcStack stack, SilcUInt32 size);
258  *
259  * DESCRIPTION
260  *
261  *    Low level memory allocation routine.  Allocates memory block of size of
262  *    `size' from the `stack'.  The allocated memory is aligned so it can be
263  *    used to allocate memory for structures, for example.  Returns the
264  *    allocated memory address or NULL if memory could not be allocated from
265  *    the `stack'.
266  *
267  * NOTES
268  *
269  *    This function should be used only if low level memory allocation with
270  *    SilcStack is needed.  Instead, silc_smalloc and silc_scalloc could
271  *    be used.
272  *
273  ***/
274 void *silc_stack_malloc(SilcStack stack, SilcUInt32 size);
275
276 /****f* silcutil/silc_stack_realloc
277  *
278  * SYNOPSIS
279  *
280  *    void *silc_stack_realloc(SilcStack stack, SilcUInt32 old_size,
281  *                             void *ptr, SilcUInt32 size);
282  *
283  * DESCRIPTION
284  *
285  *    Attempts to reallocate memory by changing the size of the `ptr' into
286  *    `size'.  This routine works only if the previous allocation to `stack'
287  *    was `ptr'.  If there is another memory allocation between allocating
288  *    `ptr' and this call this routine will return NULL (and silc_errno is
289  *    set to SILC_ERR_INVALID_ARGUMENT).  NULL is also returned if the `size'
290  *    does not fit into the current stack block.  If NULL is returned the old
291  *    memory remains intact.
292  *
293  * NOTES
294  *
295  *    This function should be used only if low level memory allocation with
296  *    SilcStack is needed.  Instead, silc_srealloc could be used which can
297  *    handle failed reallocation by allocating new block.
298  *
299  ***/
300 void *silc_stack_realloc(SilcStack stack, SilcUInt32 old_size,
301                          void *ptr, SilcUInt32 size);
302
303 /****f* silcutil/silc_stack_set_oom_handler
304  *
305  * SYNOPSIS
306  *
307  *    void silc_stack_set_oom_handler(SilcStack stack,
308  *                                    SilcStackOomHandler oom_handler,
309  *                                    void *context);
310  *
311  * DESCRIPTION
312  *
313  *    Sets Out of Memory handler `oom_handler' to `stack' to be called
314  *    if memory allocation from `stack' fails.  The `context' is delivered
315  *    to `oom_handler'.
316  *
317  *    Usually Out of Memory handler is set only when failed memory allocation
318  *    is a fatal error.  In this case the application would abort() inside
319  *    the `oom_handler'.  It may also be set if in case of failed allocation
320  *    application wants to do clean up properly.
321  *
322  ***/
323 void silc_stack_set_oom_handler(SilcStack stack,
324                                 SilcStackOomHandler oom_handler,
325                                 void *context);
326
327 /****f* silcutil/silc_stack_set_alignment
328  *
329  * SYNOPSIS
330  *
331  *    void silc_stack_set_alignment(SilcStack stack, SilcUInt32 alignment);
332  *
333  * DESCRIPTION
334  *
335  *    Sets/changes the memory alignment in the `stack' to `alignment' which
336  *    is the alignment in bytes.  By default, the SilcStack will use alignment
337  *    suited for the platform where it is used.  This function can be used
338  *    to change this alignment, if such change is needed.  You may check the
339  *    current alignment by calling silc_stack_get_alignment.
340  *
341  * NOTES
342  *
343  *    It is not mandatory to call this function.  By default the SilcStack
344  *    will always use alignment suited for the used platform.  This function
345  *    should be called only if the alignment needs to be changed to something
346  *    other than the default on the used platform.  For example, some
347  *    hardware device, such as crypto accelerator, may require special
348  *    alignment.
349  *
350  ***/
351 void silc_stack_set_alignment(SilcStack stack, SilcUInt32 alignment);
352
353 /****f* silcutil/silc_stack_get_alignment
354  *
355  * SYNOPSIS
356  *
357  *    SilcUInt32 silc_stack_get_alignment(SilcStack stack);
358  *
359  * DESCRIPTION
360  *
361  *    Returns the memory alignment used with `stack'.  The alignment is in
362  *    bytes.
363  *
364  ***/
365 SilcUInt32 silc_stack_get_alignment(SilcStack stack);
366
367 /****f* silcutil/silc_stack_purge
368  *
369  * SYNOPSIS
370  *
371  *    SilcBool silc_stack_purge(SilcStack stack);
372  *
373  * DESCRIPTION
374  *
375  *    Purges the `stack' from extra unused memory.  This purges only `stack'
376  *    and not its parent if `stack' is a child.  This purges only large
377  *    allocations.  The 1024, 2048, 4096 and 8192 bytes of allocations remain.
378  *    Call this multiple times to purge even more.  Returns FALSE when there
379  *    is no more to purge.  This does not purge memory blocks that currently
380  *    have allocations.  No memory allocations from the stack are lost, so
381  *    this is always safe to call.
382  *
383  ***/
384 SilcBool silc_stack_purge(SilcStack stack);
385
386 /****f* silcutil/silc_stack_set_global
387  *
388  * SYNOPSIS
389  *
390  *    void silc_stack_set_global(SilcStack stack);
391  *
392  * DESCRIPTION
393  *
394  *    Sets global SilcStack `stack' that can be retrieved at any time
395  *    by using silc_stack_get_global.  The global stack is global only
396  *    to the current thread.  Each thread can have their own global stack.
397  *    If each thread must have own stack this must be called in each
398  *    thread.  If the global stack has been set already, new call will
399  *    replace the old one.
400  *
401  *    This routine is provided only as a convenience function to store
402  *    program's or thread's stack in one global place.  It is not mandatory
403  *    to call this function in order to use SilcStack.
404  *
405  ***/
406 void silc_stack_set_global(SilcStack stack);
407
408 /****f* silcutil/silc_stack_get_global
409  *
410  * SYNOPSIS
411  *
412  *    SilcStack silc_stack_get_global(void);
413  *
414  * DESCRIPTION
415  *
416  *    Returns the thread's global stack that was set by calling the
417  *    silc_stack_set_global or NULL if global stack has not been set.
418  *
419  ***/
420 SilcStack silc_stack_get_global(void);
421
422 #include "silcstack_i.h"
423
424 #endif /* SILCSTACK_H */