Sun Mar 11 15:22:42 CET 2007 Jochen Eisinger <coffee@silcnet.org>
[silc.git] / lib / silcutil / silcstack.h
1 /*
2
3   silcstack.h
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2003 - 2006 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.  Basicly 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 can be used to allocate both aligned and unaligned memory so
33  * it is suitable for allocating structures and is optimal for allocating
34  * strings and data buffers.  SilcStack also supports stack pushing and
35  * popping allowing to push the stack, allocate memory and then pop it
36  * to free the allocated memory.  The freeing does not actually do any
37  * real memory freeing so it is optimized for performance.
38  *
39  * A basic set of utility functions are provided for application that wish
40  * to use the SilcStack as their primary memory allocation source.  The
41  * following functions support SilcStack:
42  *
43  * silc_smalloc, silc_smalloc_ua, silc_scalloc, silc_srealloc, silc_smemdup,
44  * silc_sstrdup, silc_buffer_salloc, silc_buffer_salloc_size,
45  * silc_buffer_srealloc, silc_buffer_srealloc_size, silc_buffer_scopy,
46  * silc_buffer_sclone, silc_buffer_sformat, silc_buffer_sformat_vp,
47  * silc_buffer_sstrformat, silc_buffer_senlarge, silc_mp_sinit
48  *
49  * The data stack is not thread-safe.  If the same stack context must be
50  * used in multithreaded environment concurrency control must be employed.
51  *
52  ***/
53
54 #ifndef SILCSTACK_H
55 #define SILCSTACK_H
56
57 /****s* silcutil/SilcStackAPI/SilcStack
58  *
59  * NAME
60  *
61  *    typedef struct SilcStackStruct *SilcStack;
62  *
63  * DESCRIPTION
64  *
65  *    This context represents the stack and it is allocated by
66  *    silc_stack_alloc and is destroyed with silc_stack_free functions.
67  *    The context is given as argument to all routines that use this
68  *    stack allocation library.
69  *
70  ***/
71 typedef struct SilcStackStruct *SilcStack;
72
73 /****s* silcutil/SilcStackAPI/SilcStackFrame
74  *
75  * NAME
76  *
77  *    typedef struct SilcStackFrameStruct SilcStackFrame;
78  *
79  * DESCRIPTION
80  *
81  *    Static stack frame context that optionally can be used as stack
82  *    frame in SilcStack.  By default silc_stack_push use pre-allocated
83  *    stack frame (or allocates new one if all frames are reserved), but
84  *    user may also use staticly allocated SilcStackFrame instead.  This
85  *    is recommended when using SilcStack in recursive routine and the
86  *    recursion may become deep.  Using static frame assures that during
87  *    recursion frames never run out and silc_stack_push never allocates
88  *    any memory.  In other normal usage staticly allocated SilcStackFrame
89  *    is not needed, unless performance is critical.
90  *
91  ***/
92 typedef struct SilcStackFrameStruct SilcStackFrame;
93
94 /****f* silcutil/SilcStackAPI/silc_stack_alloc
95  *
96  * SYNOPSIS
97  *
98  *    SilcStack silc_stack_alloc(SilcUInt32 stack_size);
99  *
100  * DESCRIPTION
101  *
102  *    Allocates new data stack that can be used as stack for fast memory
103  *    allocation by various routines.  Returns the pointer to the stack
104  *    that must be freed with silc_stack_free function when it is not
105  *    needed anymore.  If the `stack_size' is zero (0) by default a
106  *    1 kilobyte (1024 bytes) stack is allocated.  If the `stack_size'
107  *    is non-zero the byte value must be multiple by 8.
108  *
109  ***/
110 SilcStack silc_stack_alloc(SilcUInt32 stack_size);
111
112 /****f* silcutil/SilcStackAPI/silc_stack_free
113  *
114  * SYNOPSIS
115  *
116  *    void silc_stack_free(SilcStack stack);
117  *
118  * DESCRIPTION
119  *
120  *    Frees the data stack context.  The stack cannot be used anymore after
121  *    this and all allocated memory are freed.
122  *
123  ***/
124 void silc_stack_free(SilcStack stack);
125
126 /****f* silcutil/SilcStackAPI/silc_stack_push
127  *
128  * SYNOPSIS
129  *
130  *    SilcUInt32 silc_stack_push(SilcStack stack, SilcStackFrame *frame);
131  *
132  * DESCRIPTION
133  *
134  *    Push the top of the stack down which becomes the new top of the stack.
135  *    For every silc_stack_push call there must be silc_stack_pop call.  All
136  *    allocations between these two calls will be done from the top of the
137  *    stack and all allocated memory is freed after the next silc_stack_pop
138  *    is called.  This returns so called stack pointer for the new stack
139  *    frame, which the caller may use to check that all calls to
140  *    silc_stack_pop has been made.  This call may do a small memory
141  *    allocation in some cases, but usually it does not allocate any memory.
142  *    If this returns zero (0) the system is out of memory.
143  *
144  *    If the `frame' is non-NULL then that SilcStackFrame is used as
145  *    stack frame.  Usually `frame' is set to NULL by user.  Staticly
146  *    allocated SilcStackFrame should be used when using silc_stack_push
147  *    in recursive function and the recursion may become deep.  In this
148  *    case using staticly allocated SilcStackFrame is recommended since
149  *    it assures that frames never run out and silc_stack_push never
150  *    allocates any memory.  If your routine is not recursive then
151  *    setting `frame' to NULL is recommended, unless performance is
152  *    critical.
153  *
154  *    This function is used when a routine is doing frequent allocations
155  *    from the stack.  If the stack is not pushed and later popped all
156  *    allocations are made from the stack and the stack eventually runs out
157  *    (it gets enlarged by normal memory allocation).  By pushing and then
158  *    later popping the frequent allocations does not consume the stack.
159  *
160  *    If `stack' is NULL this call has no effect.
161  *
162  * EXAMPLE
163  *
164  *    All memory allocations in silc_foo_parse_packet will be done in
165  *    a fresh stack frame and that data is freed after the parsing is
166  *    completed.
167  *
168  *    silc_stack_push(stack, NULL);
169  *    silc_foo_parse_packet(packet, stack);
170  *    silc_stack_pop(stack);
171  *
172  *    Another example with recursion and using staticly allocated
173  *    SilcStackFrame.  After popping the staticly allocated frame can
174  *    be reused if necessary.
175  *
176  *    void silc_foo_this_function(SilcStack stack)
177  *    {
178  *      SilcStackFrame frame;
179  *      ...
180  *      silc_stack_push(stack, &frame);
181  *      silc_foo_this_function(stack);   // Call recursively
182  *      silc_stack_pop(stack);
183  *      ...
184  *    }
185  *
186  ***/
187 SilcUInt32 silc_stack_push(SilcStack stack, SilcStackFrame *frame);
188
189 /****f* silcutil/SilcStackAPI/silc_stack_pop
190  *
191  * SYNOPSIS
192  *
193  *    SilcUInt32 silc_stack_pop(SilcStack stack);
194  *
195  * DESCRIPTION
196  *
197  *    Pop the top of the stack upwards which reveals the previous stack frame
198  *    and becomes the top of the stack.  After popping, memory allocated in
199  *    the old frame is freed.  For each silc_stack_push call there must be
200  *    silc_stack_pop call to free all memory (in reality any memory is not
201  *    freed but within the stack it is).  This returns the stack pointer of
202  *    old frame after popping and caller may check that it is same as
203  *    returned by the silc_stack_push.  If it they differ, some routine
204  *    has called silc_stack_push but has not called silc_stack_pop, or
205  *    silc_stack_pop has been called too many times.  Application should
206  *    treat this as a fatal error, as it is a bug in the application code.
207  *
208  *    If `stack' is NULL this call has no effect.
209  *
210  * EXAMPLE
211  *
212  *    This example saves the stack pointer which is checked when popping
213  *    the current stack frame.  If the stack pointer differs then someone
214  *    has pushed the stack frame but forgot to pop it (or has called it
215  *    too many times).
216  *
217  *    sp = silc_stack_push(stack, NULL);
218  *    silc_foo_parse_packet(packet, stack);
219  *    if (silc_stack_pop(stack) != sp)
220  *      fatal("corrupted stack");
221  *
222  ***/
223 SilcUInt32 silc_stack_pop(SilcStack stack);
224
225 #include "silcstack_i.h"
226
227 #endif /* SILCSTACK_H */