5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2003 - 2005 Pekka Riikonen
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.
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.
20 /****h* silcutil/SilcStack Interface
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
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.
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:
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_sunformat, silc_buffer_sstrformat,
54 /****s* silcutil/SilcStackAPI/SilcStack
58 * typedef struct SilcStackStruct *SilcStack;
62 * This context represents the stack and it is allocated by
63 * silc_stack_alloc and is destroyed with silc_stack_free functions.
64 * The context is given as argument to all routines that use this
65 * stack allocation library.
68 typedef struct SilcStackStruct *SilcStack;
70 /****s* silcutil/SilcStackAPI/SilcStackFrame
74 * typedef struct SilcStackFrameStruct SilcStackFrame;
78 * Static stack frame context that optionally can be used as stack
79 * frame in SilcStack. By default silc_stack_push use pre-allocated
80 * stack frame (or allocates new one if all frames are reserved), but
81 * user may also use staticly allocated SilcStackFrame instead. This
82 * is recommended when using SilcStack in recursive routine and the
83 * recursion may become deep. Using static frame assures that during
84 * recursion frames never run out and silc_stack_push never allocates
85 * any memory. In other normal usage staticly allocated SilcStackFrame
86 * is not needed, unless performance is critical.
89 typedef struct SilcStackFrameStruct SilcStackFrame;
91 /****f* silcutil/SilcStackAPI/silc_stack_alloc
95 * SilcStack silc_stack_alloc(SilcUInt32 stack_size);
99 * Allocates new data stack that can be used as stack for fast memory
100 * allocation by various routines. Returns the pointer to the stack
101 * that must be freed with silc_stack_free function when it is not
102 * needed anymore. If the `stack_size' is zero (0) by default a
103 * 1 kilobyte (1024 bytes) stack is allocated. If the `stack_size'
104 * is non-zero the byte value must be multiple by 8.
107 SilcStack silc_stack_alloc(SilcUInt32 stack_size);
109 /****f* silcutil/SilcStackAPI/silc_stack_free
113 * void silc_stack_free(SilcStack stack);
117 * Frees the data stack context. The stack cannot be used anymore after
118 * this and all allocated memory are freed.
121 void silc_stack_free(SilcStack stack);
123 /****f* silcutil/SilcStackAPI/silc_stack_push
127 * SilcUInt32 silc_stack_push(SilcStack stack, SilcStackFrame *frame);
131 * Push the top of the stack down which becomes the new top of the stack.
132 * For every silc_stack_push call there must be silc_stack_pop call. All
133 * allocations between these two calls will be done from the top of the
134 * stack and all allocated memory is freed after the next silc_stack_pop
135 * is called. This returns so called stack pointer for the new stack
136 * frame, which the caller may use to check that all calls to
137 * silc_stack_pop has been made. This call may do a small memory
138 * allocation in some cases, but usually it does not allocate any memory.
139 * If this returns zero (0) the system is out of memory.
141 * If the `frame' is non-NULL then that SilcStackFrame is used as
142 * stack frame. Usually `frame' is set to NULL by user. Staticly
143 * allocated SilcStackFrame should be used when using silc_stack_push
144 * in recursive function and the recursion may become deep. In this
145 * case using staticly allocated SilcStackFrame is recommended since
146 * it assures that frames never run out and silc_stack_push never
147 * allocates any memory. If your routine is not recursive then
148 * setting `frame' to NULL is recommended, unless performance is
151 * This function is used when a routine is doing frequent allocations
152 * from the stack. If the stack is not pushed and later popped all
153 * allocations are made from the stack and the stack eventually runs out
154 * (it gets enlarged by normal memory allocation). By pushing and then
155 * later popping the frequent allocations does not consume the stack.
157 * If `stack' is NULL this call has no effect.
161 * All memory allocations in silc_foo_parse_packet will be done in
162 * a fresh stack frame and that data is freed after the parsing is
165 * silc_stack_push(stack, NULL);
166 * silc_foo_parse_packet(packet, stack);
167 * silc_stack_pop(stack);
169 * Another example with recursion and using staticly allocated
170 * SilcStackFrame. After popping the staticly allocated frame can
171 * be reused if necessary.
173 * void silc_foo_this_function(SilcStack stack)
175 * SilcStackFrame frame;
177 * silc_stack_push(stack, &frame);
178 * silc_foo_this_function(stack); // Call recursively
179 * silc_stack_pop(stack);
184 SilcUInt32 silc_stack_push(SilcStack stack, SilcStackFrame *frame);
186 /****f* silcutil/SilcStackAPI/silc_stack_pop
190 * SilcUInt32 silc_stack_pop(SilcStack stack);
194 * Pop the top of the stack upwards which reveals the previous stack frame
195 * and becomes the top of the stack. After popping, memory allocated in
196 * the old frame is freed. For each silc_stack_push call there must be
197 * silc_stack_pop call to free all memory (in reality any memory is not
198 * freed but within the stack it is). This returns the stack pointer of
199 * old frame after popping and caller may check that it is same as
200 * returned by the silc_stack_push. If it they differ, some routine
201 * has called silc_stack_push but has not called silc_stack_pop, or
202 * silc_stack_pop has been called too many times. Application should
203 * treat this as a fatal error, as it is a bug in the application code.
205 * If `stack' is NULL this call has no effect.
209 * This example saves the stack pointer which is checked when popping
210 * the current stack frame. If the stack pointer differs then someone
211 * has pushed the stack frame but forgot to pop it (or has called it
214 * sp = silc_stack_push(stack, NULL);
215 * silc_foo_parse_packet(packet, stack);
216 * if (silc_stack_pop(stack) != sp)
217 * fatal("corrupted stack");
220 SilcUInt32 silc_stack_pop(SilcStack stack);
222 #include "silcstack_i.h"
224 #endif /* SILCSTACK_H */