Added concept of child stacks to SilcStack. Supports now full
[silc.git] / lib / silcutil / silcstack.h
1 /*
2
3   silcstack.h
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2003 - 2007 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/SilcStack Interface
21  *
22  * DESCRIPTION
23  *
24  * Implementation of data stack which can be used to allocate memory from
25  * the stack.  Basically SilcStack is a pre-allocated memory pool system
26  * which allows fast memory allocation for routines and applications that
27  * frequently allocate small amounts of memory.  Other advantage of this
28  * system is that there are no memory leaks, as long as the stack is
29  * freed eventually.  Since the stack is usually allocated only once this
30  * is not an issue.
31  *
32  * SilcStack supports stack pushing and popping allowing to push the stack,
33  * allocate memory and then pop it to free the allocated memory.  The freeing
34  * does not actually do any real memory freeing so it is optimized for
35  * performance.  The memory alignment may also be specified by user for
36  * the stack.  This allows the caller to use special alignment for memory
37  * allocations, if needed.
38  *
39  * SilcStack is also a full featured memory pool which allows user to group
40  * together multiple stacks.  Child stacks may be created from a parent stack
41  * without consuming the parent stack.  When the child is freed, its memory
42  * is returned back to the parent and can be used again by other childs.
43  * It is also possible to create child stacks from another child stack.
44  *
45  * A basic set of utility functions are provided for application that wish
46  * to use the SilcStack as their primary memory allocation source.  The
47  * following functions support SilcStack:
48  *
49  * silc_smalloc, silc_smalloc, silc_scalloc, silc_srealloc, silc_smemdup,
50  * silc_sfree, silc_sstrdup, silc_buffer_salloc, silc_buffer_salloc_size,
51  * silc_buffer_srealloc, silc_buffer_srealloc_size, silc_buffer_scopy,
52  * silc_buffer_sclone, silc_buffer_sformat, silc_buffer_sformat_vp,
53  * silc_buffer_sstrformat, silc_buffer_senlarge, silc_mp_sinit,
54  * silc_dlist_sinit, silc_hash_table_alloc
55  *
56  * The SilcStack context is not thread-safe.  If the same SilcStack must be
57  * used in multithreaded environment concurrency control must be employed.
58  * Each thread should allocate their own SilcStack.
59  *
60  ***/
61
62 #ifndef SILCSTACK_H
63 #define SILCSTACK_H
64
65 /****s* silcutil/SilcStackAPI/SilcStack
66  *
67  * NAME
68  *
69  *    typedef struct SilcStackStruct *SilcStack;
70  *
71  * DESCRIPTION
72  *
73  *    This context represents the stack and it is allocated by
74  *    silc_stack_alloc and is destroyed with silc_stack_free functions.
75  *    The context is given as argument to all routines that use this
76  *    stack allocation library.
77  *
78  ***/
79 typedef struct SilcStackStruct *SilcStack;
80
81 /****s* silcutil/SilcStackAPI/SilcStackFrame
82  *
83  * NAME
84  *
85  *    typedef struct SilcStackFrameStruct SilcStackFrame;
86  *
87  * DESCRIPTION
88  *
89  *    Static stack frame context that optionally can be used as stack
90  *    frame in SilcStack.  By default silc_stack_push use pre-allocated
91  *    stack frame, but user may also use statically allocated SilcStackFrame
92  *    instead.  This is recommended when using SilcStack in recursive routine
93  *    and the recursion may become deep.  Using static frame assures that
94  *    during recursion frames never run out.
95  *
96  ***/
97 typedef struct SilcStackFrameStruct SilcStackFrame;
98
99 /****f* silcutil/SilcStackAPI/silc_stack_alloc
100  *
101  * SYNOPSIS
102  *
103  *    SilcStack silc_stack_alloc(SilcUInt32 stack_size, SilcStack parent);
104  *
105  * DESCRIPTION
106  *
107  *    Allocates new data stack that can be used as stack for fast memory
108  *    allocation by various routines.  Returns the pointer to the stack
109  *    that must be freed with silc_stack_free function when it is not
110  *    needed anymore.  If the `stack_size' is zero (0) by default a
111  *    2 kilobytes (2048 bytes) stack is allocated.  If the `stack_size'
112  *    is non-zero the byte value must be multiple by 8.
113  *
114  *    If `parent' is non-NULL the created stack is a child of the `parent'
115  *    stack.  All of childs the memory is allocated from the `parent' and
116  *    will be returned back to the parent when the child is freed.  Note
117  *    that, even though child allocated memory from the parent, the parent's
118  *    stack is not consumed.
119  *
120  *    Returns NULL on error.
121  *
122  ***/
123 SilcStack silc_stack_alloc(SilcUInt32 stack_size, SilcStack parent);
124
125 /****f* silcutil/SilcStackAPI/silc_stack_free
126  *
127  * SYNOPSIS
128  *
129  *    void silc_stack_free(SilcStack stack);
130  *
131  * DESCRIPTION
132  *
133  *    Frees the data stack context.  The stack cannot be used anymore after
134  *    this and all allocated memory are freed.
135  *
136  *    If `stack' is a child stack, its memory is returned back to its
137  *    parent.
138  *
139  ***/
140 void silc_stack_free(SilcStack stack);
141
142 /****f* silcutil/SilcStackAPI/silc_stack_push
143  *
144  * SYNOPSIS
145  *
146  *    SilcUInt32 silc_stack_push(SilcStack stack, SilcStackFrame *frame);
147  *
148  * DESCRIPTION
149  *
150  *    Push the top of the stack down which becomes the new top of the stack.
151  *    For every silc_stack_push call there must be silc_stack_pop call.  All
152  *    allocations between these two calls will be done from the top of the
153  *    stack and all allocated memory is freed after the next silc_stack_pop
154  *    is called.  This returns so called stack pointer for the new stack
155  *    frame, which the caller may use to check that all calls to
156  *    silc_stack_pop has been made.  This call may do a small memory
157  *    allocation in some cases, but usually it does not allocate any memory.
158  *    If this returns zero (0) the system is out of memory.
159  *
160  *    If the `frame' is non-NULL then that SilcStackFrame is used as
161  *    stack frame.  Usually `frame' is set to NULL by user.  Statically
162  *    allocated SilcStackFrame should be used when using silc_stack_push
163  *    in recursive function and the recursion may become deep.  In this
164  *    case using statically allocated SilcStackFrame is recommended since
165  *    it assures that frames never run out and silc_stack_push never
166  *    allocates any memory.  If your routine is not recursive then
167  *    setting `frame' to NULL is recommended, unless performance is
168  *    critical.
169  *
170  *    This function is used when a routine is doing frequent allocations
171  *    from the stack.  If the stack is not pushed and later popped all
172  *    allocations are made from the stack and the stack eventually runs out
173  *    (it gets enlarged by normal memory allocation).  By pushing and then
174  *    later popping the frequent allocations does not consume the stack.
175  *
176  *    If `stack' is NULL this call has no effect.
177  *
178  * EXAMPLE
179  *
180  *    All memory allocations in silc_foo_parse_packet will be done in
181  *    a fresh stack frame and that data is freed after the parsing is
182  *    completed.
183  *
184  *    silc_stack_push(stack, NULL);
185  *    silc_foo_parse_packet(packet, stack);
186  *    silc_stack_pop(stack);
187  *
188  *    Another example with recursion and using statically allocated
189  *    SilcStackFrame.  After popping the statically allocated frame can
190  *    be reused if necessary.
191  *
192  *    void silc_foo_this_function(SilcStack stack)
193  *    {
194  *      SilcStackFrame frame;
195  *      ...
196  *      silc_stack_push(stack, &frame);
197  *      silc_foo_this_function(stack);   // Call recursively
198  *      silc_stack_pop(stack);
199  *      ...
200  *    }
201  *
202  ***/
203 SilcUInt32 silc_stack_push(SilcStack stack, SilcStackFrame *frame);
204
205 /****f* silcutil/SilcStackAPI/silc_stack_pop
206  *
207  * SYNOPSIS
208  *
209  *    SilcUInt32 silc_stack_pop(SilcStack stack);
210  *
211  * DESCRIPTION
212  *
213  *    Pop the top of the stack upwards which reveals the previous stack frame
214  *    and becomes the top of the stack.  After popping, memory allocated in
215  *    the old frame is freed.  For each silc_stack_push call there must be
216  *    silc_stack_pop call to free all memory (in reality any memory is not
217  *    freed but within the stack it is).  This returns the stack pointer of
218  *    old frame after popping and caller may check that it is same as
219  *    returned by the silc_stack_push.  If it they differ, some routine
220  *    has called silc_stack_push but has not called silc_stack_pop, or
221  *    silc_stack_pop has been called too many times.  Application should
222  *    treat this as a fatal error, as it is a bug in the application code.
223  *
224  *    If `stack' is NULL this call has no effect.
225  *
226  * EXAMPLE
227  *
228  *    This example saves the stack pointer which is checked when popping
229  *    the current stack frame.  If the stack pointer differs then someone
230  *    has pushed the stack frame but forgot to pop it (or has called it
231  *    too many times).
232  *
233  *    sp = silc_stack_push(stack, NULL);
234  *    silc_foo_parse_packet(packet, stack);
235  *    if (silc_stack_pop(stack) != sp)
236  *      fatal("corrupted stack");
237  *
238  ***/
239 SilcUInt32 silc_stack_pop(SilcStack stack);
240
241 /****f* silcutil/SilcStackAPI/silc_stack_malloc
242  *
243  * SYNOPSIS
244  *
245  *    void *silc_stack_malloc(SilcStack stack, SilcUInt32 size);
246  *
247  * DESCRIPTION
248  *
249  *    Low level memory allocation routine.  Allocates memor block of size of
250  *    `size' from the `stack'.  The allocated memory is aligned so it can be
251  *    used to allocate memory for structures, for example.  Returns the
252  *    allocated memory address or NULL if memory could not be allocated from
253  *    the `stack'.
254  *
255  * NOTES
256  *
257  *    This function should be used only if low level memory allocation with
258  *    SilcStack is needed.  Instead, silc_smalloc, could be used.
259  *
260  ***/
261 void *silc_stack_malloc(SilcStack stack, SilcUInt32 size);
262
263 /****f* silcutil/SilcStackAPI/silc_stack_realloc
264  *
265  * SYNOPSIS
266  *
267  *    void *silc_stack_realloc(SilcStack stack, SilcUInt32 old_size,
268  *                             *void *ptr, SilcUInt32 size);
269  *
270  * DESCRIPTION
271  *
272  *    Attempts to reallocate memory by changing the size of the `ptr' into
273  *    `size'.  This routine works only if the previous allocation to `stack'
274  *    was `ptr'.  If there is another memory allocation between allocating
275  *    `ptr' and this call this routine will return NULL.  NULL is also
276  *    returned if the `size' does not fit into the current block.  If NULL
277  *    is returned the old memory remains intact.
278  *
279  * NOTES
280  *
281  *    This function should be used only if low level memory allocation with
282  *    SilcStack is needed.  Instead, silc_srealloc, could be used.
283  *
284  ***/
285 void *silc_stack_realloc(SilcStack stack, SilcUInt32 old_size,
286                          void *ptr, SilcUInt32 size);
287
288 /****f* silcutil/SilcStackAPI/silc_stack_set_alignment
289  *
290  * SYNOPSIS
291  *
292  *    void silc_stack_set_alignment(SilcStack stack, SilcUInt32 alignment);
293  *
294  * DESCRIPTION
295  *
296  *    Sets/changes the memory alignment in the `stack' to `alignment' which
297  *    is the alignment in bytes.  By default, the SilcStack will use alignment
298  *    suited for the platform where it is used.  This function can be used
299  *    change this alignment, if such change is needed.  You may check the
300  *    current alignment by calling silc_stack_get_alignment.
301  *
302  * NOTES
303  *
304  *    It is not mandatory to call this function.  By default the SilcStack
305  *    will always use alignment suited for the used platform.  This function
306  *    should be called only if the alignment needs to be changed to something
307  *    other than the default on the used platform.  For example, some
308  *    hardware device, such as crypto accelerator, may require special
309  *    alignment.
310  *
311  ***/
312 void silc_stack_set_alignment(SilcStack stack, SilcUInt32 alignment);
313
314 /****f* silcutil/SilcStackAPI/silc_stack_get_alignment
315  *
316  * SYNOPSIS
317  *
318  *    SilcUInt32 silc_stack_get_alignment(SilcStack stack);
319  *
320  * DESCRIPTION
321  *
322  *    Returns the memory alignment used with `stack'.  The alignment is in
323  *    bytes.
324  *
325  ***/
326 SilcUInt32 silc_stack_get_alignment(SilcStack stack);
327
328 #include "silcstack_i.h"
329
330 #endif /* SILCSTACK_H */