UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2016 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file stack.h 31 * 32 * Default stack memory allocation implementation. 33 * 34 * @author Mike Becker 35 * @author Olaf Wintermann 36 */ 37 38 #ifndef UCX_STACK_H 39 #define UCX_STACK_H 40 41 #include "ucx.h" 42 #include "allocator.h" 43 44 #ifdef __cplusplus 45 extern "C" { 46 #endif 47 48 49 /** 50 * UCX stack structure. 51 */ 52 typedef struct { 53 /** UcxAllocator based on this stack */ 54 UcxAllocator allocator; 55 56 /** Stack size. */ 57 size_t size; 58 59 /** Pointer to the bottom of the stack */ 60 char *space; 61 62 /** Pointer to the top of the stack */ 63 char *top; 64 } UcxStack; 65 66 /** 67 * Metadata for each UCX stack element. 68 */ 69 struct ucx_stack_metadata { 70 /** 71 * Location of the previous element (<code>NULL</code> if this is the first) 72 */ 73 char *prev; 74 75 /** Size of this element */ 76 size_t size; 77 }; 78 79 /** 80 * Initializes UcxStack structure with memory. 81 * 82 * @param stack a pointer to an uninitialized stack structure 83 * @param space the memory area that shall be managed 84 * @param size size of the memory area 85 * @return a new UcxStack structure 86 */ 87 void ucx_stack_init(UcxStack *stack, char* space, size_t size); 88 89 /** 90 * Allocates stack memory. 91 * 92 * @param stack a pointer to the stack 93 * @param n amount of memory to allocate 94 * @return a pointer to the allocated memory 95 * @see ucx_allocator_malloc() 96 */ 97 void *ucx_stack_malloc(UcxStack *stack, size_t n); 98 99 /** 100 * Alias for #ucx_stack_malloc(). 101 * @param stack a pointer to the stack 102 * @param n amount of memory to allocate 103 * @return a pointer to the allocated memory 104 * @see ucx_stack_malloc 105 */ 106 #define ucx_stack_push(stack, n) ucx_stack_malloc(stack, n) 107 108 /** 109 * Allocates an array of stack memory 110 * 111 * The content of the allocated memory is set to zero. 112 * 113 * @param stack a pointer to the stack 114 * @param nelem amount of elements to allocate 115 * @param elsize amount of memory per element 116 * @return a pointer to the allocated memory 117 * @see ucx_allocator_calloc() 118 */ 119 void *ucx_stack_calloc(UcxStack *stack, size_t nelem, size_t elsize); 120 121 /** 122 * Alias for #ucx_stack_calloc(). 123 * 124 * @param stack a pointer to the stack 125 * @param n amount of elements to allocate 126 * @param elsize amount of memory per element 127 * @return a pointer to the allocated memory 128 * @see ucx_stack_calloc 129 */ 130 #define ucx_stack_pusharr(stack,n,elsize) ucx_stack_calloc(stack,n,elssize) 131 132 /** 133 * Reallocates memory on the stack. 134 * 135 * Shrinking memory is always safe. Extending memory can be very expensive. 136 * 137 * @param stack the stack 138 * @param ptr a pointer to the memory that shall be reallocated 139 * @param n the new size of the memory 140 * @return a pointer to the new location of the memory 141 * @see ucx_allocator_realloc() 142 */ 143 void *ucx_stack_realloc(UcxStack *stack, void *ptr, size_t n); 144 145 /** 146 * Frees memory on the stack. 147 * 148 * Freeing stack memory behaves in a special way. 149 * 150 * If the element, that should be freed, is the top most element of the stack, 151 * it is removed from the stack. Otherwise it is marked as freed. Marked 152 * elements are removed, when they become the top most elements of the stack. 153 * 154 * @param stack a pointer to the stack 155 * @param ptr a pointer to the memory that shall be freed 156 */ 157 void ucx_stack_free(UcxStack *stack, void *ptr); 158 159 160 /** 161 * Returns the size of the top most element. 162 * @param stack a pointer to the stack 163 * @return the size of the top most element 164 */ 165 #define ucx_stack_topsize(stack) ((stack)->top ? ((struct ucx_stack_metadata*)\ 166 (stack)->top - 1)->size : 0) 167 168 /** 169 * Removes the top most element from the stack and copies the content to <code> 170 * dest</code>, if specified. 171 * 172 * Use #ucx_stack_topsize()# to get the amount of memory that must be available 173 * at the location of <code>dest</code>. 174 * 175 * @param stack a pointer to the stack 176 * @param dest the location where the contents shall be written to, or <code> 177 * NULL</code>, if the element shall only be removed. 178 * @see ucx_stack_free 179 * @see ucx_stack_popn 180 */ 181 #define ucx_stack_pop(stack, dest) ucx_stack_popn(stack, dest, (size_t)-1) 182 183 /** 184 * Removes the top most element from the stack and copies the content to <code> 185 * dest</code>. 186 * 187 * In contrast to #ucx_stack_pop() the <code>dest</code> pointer <code>MUST 188 * NOT</code> be <code>NULL</code>. 189 * 190 * @param stack a pointer to the stack 191 * @param dest the location where the contents shall be written to 192 * @param n copies at most n elements to <code>dest</code> 193 * @see ucx_stack_pop 194 */ 195 void ucx_stack_popn(UcxStack *stack, void *dest, size_t n); 196 197 /** 198 * Returns the remaining available memory on the specified stack. 199 * 200 * @param stack a pointer to the stack 201 * @return the remaining available memory 202 */ 203 size_t ucx_stack_avail(UcxStack *stack); 204 205 /** 206 * Checks, if the stack is empty. 207 * 208 * @param stack a pointer to the stack 209 * @return nonzero, if the stack is empty, zero otherwise 210 */ 211 #define ucx_stack_empty(stack) (!(stack)->top) 212 213 /** 214 * Computes a recommended size for the stack memory area. Note, that 215 * reallocations have not been taken into account, so you might need to reserve 216 * twice as much memory to allow many reallocations. 217 * 218 * @param size the approximate payload 219 * @param elems the approximate count of element allocations 220 * @return a recommended size for the stack space based on the information 221 * provided 222 */ 223 #define ucx_stack_dim(size, elems) (size+sizeof(struct ucx_stack_metadata) * \ 224 (elems + 1)) 225 226 227 #ifdef __cplusplus 228 } 229 #endif 230 231 #endif /* UCX_STACK_H */ 232 233