UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2021 Mike Becker, 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 * @file allocator.h 30 * Interface for custom allocators. 31 */ 32 33 #ifndef UCX_ALLOCATOR_H 34 #define UCX_ALLOCATOR_H 35 36 #include "common.h" 37 38 #ifdef __cplusplus 39 extern "C" { 40 #endif 41 42 /** 43 * The class definition for an allocator. 44 */ 45 typedef struct { 46 /** 47 * The allocator's malloc() implementation. 48 */ 49 void *(*malloc)(void *data, size_t n); 50 51 /** 52 * The allocator's realloc() implementation. 53 */ 54 void *(*realloc)(void *data, void *mem, size_t n); 55 56 /** 57 * The allocator's calloc() implementation. 58 */ 59 void *(*calloc)(void *data, size_t nmemb, size_t size); 60 61 /** 62 * The allocator's free() implementation. 63 */ 64 void (*free)(void *data, void *mem); 65 } cx_allocator_class; 66 67 /** 68 * Structure holding the data for an allocator. 69 */ 70 struct cx_allocator_s { 71 /** 72 * A pointer to the instance of the allocator class. 73 */ 74 cx_allocator_class *cl; 75 /** 76 * A pointer to the data this allocator uses. 77 */ 78 void *data; 79 }; 80 81 /** 82 * High-Level type alias for the allocator type. 83 */ 84 typedef struct cx_allocator_s CxAllocator; 85 86 /** 87 * A pre-defined allocator using standard library malloc() etc. 88 */ 89 CX_EXPORT extern const CxAllocator * const cxStdlibAllocator; 90 91 /** 92 * The default allocator that is used by UCX. 93 * Initialized with cxStdlibAllocator, but you may change it. 94 */ 95 CX_EXPORT extern const CxAllocator * cxDefaultAllocator; 96 97 /** 98 * Function pointer type for destructor functions. 99 * 100 * A destructor function deallocates possible contents and MAY free the memory 101 * pointed to by @p memory. Read the documentation of the respective function 102 * pointer to learn if a destructor SHALL, MAY, or MUST NOT free the memory in 103 * that particular implementation. 104 * 105 * @param memory a pointer to the object to destruct 106 */ 107 typedef void (*cx_destructor_func)(void *memory); 108 109 /** 110 * Function pointer type for destructor functions. 111 * 112 * A destructor function deallocates possible contents and MAY free the memory 113 * pointed to by @p memory. Read the documentation of the respective function 114 * pointer to learn if a destructor SHALL, MAY, or MUST NOT free the memory in 115 * that particular implementation. 116 * 117 * @param data an optional pointer to custom data 118 * @param memory a pointer to the object to destruct 119 */ 120 typedef void (*cx_destructor_func2)(void *data, void *memory); 121 122 123 /** 124 * Function pointer type for clone functions. 125 * 126 * A clone function is supposed to create a deep copy of the memory pointed to 127 * by the @p source pointer. 128 * If the @p target pointer is non-null, the clone function is supposed to store 129 * the copy into that memory region. 130 * Otherwise, the clone function shall use the specified @p allocator to create 131 * a new object. 132 * 133 * The return value of a clone function is always a pointer to the target 134 * memory region, or @c NULL if any allocation failed. 135 * A clone function SHOULD NOT fail for any other reason than an allocation 136 * failure. 137 * 138 * @param target the target memory or @c NULL, if memory shall be allocated 139 * @param source the source memory 140 * @param allocator the allocator that shall be used 141 * @param data optional additional data 142 * @return either the specified @p target, a pointer to the allocated memory, 143 * or @c NULL, if any error occurred 144 */ 145 typedef void*(cx_clone_func)(void *target, const void *source, 146 const CxAllocator *allocator, void *data); 147 148 /** 149 * Returns the system's memory page size. 150 * 151 * If the page size cannot be retrieved from the system, 152 * a default of 4096 bytes is assumed. 153 * 154 * @return the system's memory page size in bytes 155 */ 156 cx_attr_nodiscard 157 CX_EXPORT unsigned long cx_system_page_size(void); 158 159 /** 160 * Reallocate a previously allocated block and changes the pointer in-place, 161 * if necessary. 162 * 163 * @note This will use stdlib reallocate and @em not the cxDefaultAllocator. 164 * 165 * @par Error handling 166 * @c errno will be set by realloc() on failure. 167 * 168 * @param mem pointer to the pointer to allocated block 169 * @param n the new size in bytes 170 * @retval zero success 171 * @retval non-zero failure 172 * @see cx_reallocatearray() 173 */ 174 cx_attr_nonnull cx_attr_nodiscard 175 CX_EXPORT int cx_reallocate_(void **mem, size_t n); 176 177 /** 178 * Reallocate a previously allocated block and changes the pointer in-place, 179 * if necessary. 180 * 181 * The size is calculated by multiplying @p nemb and @p size. 182 * 183 * @note This will use stdlib reallocate and @em not the cxDefaultAllocator. 184 * 185 * @par Error handling 186 * @c errno will be set by realloc() on failure or when the multiplication of 187 * @p nmemb and @p size overflows. 188 * 189 * @param mem pointer to the pointer to allocated block 190 * @param nmemb the number of elements 191 * @param size the size of each element 192 * @retval zero success 193 * @retval non-zero failure 194 * @see cx_reallocate() 195 */ 196 cx_attr_nonnull cx_attr_nodiscard 197 CX_EXPORT int cx_reallocatearray_(void **mem, size_t nmemb, size_t size); 198 199 /** 200 * Reallocate a previously allocated block and changes the pointer in-place, 201 * if necessary. 202 * 203 * @note This will use stdlib reallocate and @em not the cxDefaultAllocator. 204 * 205 * @par Error handling 206 * @c errno will be set by realloc() on failure. 207 * 208 * @param mem (@c void**) pointer to the pointer to allocated block 209 * @param n (@c size_t) the new size in bytes 210 * @retval zero success 211 * @retval non-zero failure 212 * @see cx_reallocatearray() 213 */ 214 #define cx_reallocate(mem, n) cx_reallocate_((void**)(mem), n) 215 216 /** 217 * Reallocate a previously allocated block and changes the pointer in-place, 218 * if necessary. 219 * 220 * The size is calculated by multiplying @p nemb and @p size. 221 * 222 * @note This will use stdlib reallocate and @em not the cxDefaultAllocator. 223 * 224 * @par Error handling 225 * @c errno will be set by realloc() on failure or when the multiplication of 226 * @p nmemb and @p size overflows. 227 * 228 * @param mem (@c void**) pointer to the pointer to allocated block 229 * @param nmemb (@c size_t) the number of elements 230 * @param size (@c size_t) the size of each element 231 * @retval zero success 232 * @retval non-zero failure 233 */ 234 #define cx_reallocatearray(mem, nmemb, size) \ 235 cx_reallocatearray_((void**)(mem), nmemb, size) 236 237 /** 238 * Allocates memory and sets every byte to zero. 239 * 240 * @param n (@c size_t) the number of bytes 241 * @return (@c void*) a pointer to the allocated memory 242 */ 243 #define cx_zalloc(n) calloc(1, n) 244 245 /** 246 * Free a block allocated by this allocator. 247 * 248 * @note Freeing a block of a different allocator is undefined. 249 * 250 * @param allocator the allocator 251 * @param mem a pointer to the block to free 252 */ 253 cx_attr_nonnull_arg(1) 254 CX_EXPORT void cxFree(const CxAllocator *allocator, void *mem); 255 256 /** 257 * Allocate @p n bytes of memory. 258 * 259 * @param allocator the allocator 260 * @param n the number of bytes 261 * @return a pointer to the allocated memory 262 */ 263 cx_attr_nodiscard cx_attr_nonnull 264 cx_attr_malloc cx_attr_dealloc_ucx cx_attr_allocsize(2) 265 CX_EXPORT void *cxMalloc(const CxAllocator *allocator, size_t n); 266 267 /** 268 * Reallocate the previously allocated block in @p mem, making the new block 269 * @p n bytes long. 270 * This function may return the same pointer passed to it if moving 271 * the memory was not necessary. 272 * 273 * @note Re-allocating a block allocated by a different allocator is undefined. 274 * 275 * @param allocator the allocator 276 * @param mem pointer to the previously allocated block 277 * @param n the new size in bytes 278 * @return a pointer to the reallocated memory 279 */ 280 cx_attr_nodiscard cx_attr_nonnull_arg(1) 281 cx_attr_dealloc_ucx cx_attr_allocsize(3) 282 CX_EXPORT void *cxRealloc(const CxAllocator *allocator, void *mem, size_t n); 283 284 /** 285 * Reallocate the previously allocated block in @p mem, making the new block 286 * @p n bytes long. 287 * This function may return the same pointer passed to it if moving 288 * the memory was not necessary. 289 * 290 * The size is calculated by multiplying @p nemb and @p size. 291 * If that multiplication overflows, this function returns @c NULL, and @c errno 292 * will be set. 293 * 294 * @note Re-allocating a block allocated by a different allocator is undefined. 295 * 296 * @param allocator the allocator 297 * @param mem pointer to the previously allocated block 298 * @param nmemb the number of elements 299 * @param size the size of each element 300 * @return a pointer to the reallocated memory 301 */ 302 cx_attr_nodiscard cx_attr_nonnull_arg(1) 303 cx_attr_dealloc_ucx cx_attr_allocsize(3, 4) 304 CX_EXPORT void *cxReallocArray(const CxAllocator *allocator, 305 void *mem, size_t nmemb, size_t size); 306 307 /** 308 * Reallocate a previously allocated block and changes the pointer in-place, 309 * if necessary. 310 * This function acts like cxRealloc() using the pointer pointed to by @p mem. 311 * 312 * @note Re-allocating a block allocated by a different allocator is undefined. 313 * 314 * @par Error handling 315 * @c errno will be set if the underlying realloc function does so. 316 * 317 * @param allocator the allocator 318 * @param mem pointer to the pointer to allocated block 319 * @param n the new size in bytes 320 * @retval zero success 321 * @retval non-zero failure 322 */ 323 cx_attr_nodiscard cx_attr_nonnull 324 CX_EXPORT int cxReallocate_(const CxAllocator *allocator, void **mem, size_t n); 325 326 /** 327 * Reallocate a previously allocated block and changes the pointer in-place, 328 * if necessary. 329 * This function acts like cxRealloc() using the pointer pointed to by @p mem. 330 * 331 * @note Re-allocating a block allocated by a different allocator is undefined. 332 * 333 * @par Error handling 334 * @c errno will be set if the underlying realloc function does so. 335 * 336 * @param allocator (@c CxAllocator*) the allocator 337 * @param mem (@c void**) pointer to the pointer to allocated block 338 * @param n (@c size_t) the new size in bytes 339 * @retval zero success 340 * @retval non-zero failure 341 */ 342 #define cxReallocate(allocator, mem, n) \ 343 cxReallocate_(allocator, (void**)(mem), n) 344 345 /** 346 * Reallocate a previously allocated block and changes the pointer in-place, 347 * if necessary. 348 * This function acts like cxReallocArray() using the pointer pointed to 349 * by @p mem. 350 * 351 * @note Re-allocating a block allocated by a different allocator is undefined. 352 * 353 * @par Error handling 354 * @c errno will be set, if the underlying realloc function does so or the 355 * multiplication of @p nmemb and @p size overflows. 356 * 357 * @param allocator the allocator 358 * @param mem pointer to the pointer to allocated block 359 * @param nmemb the number of elements 360 * @param size the size of each element 361 * @retval zero success 362 * @retval non-zero on failure 363 */ 364 cx_attr_nodiscard cx_attr_nonnull 365 CX_EXPORT int cxReallocateArray_(const CxAllocator *allocator, 366 void **mem, size_t nmemb, size_t size); 367 368 /** 369 * Reallocate a previously allocated block and changes the pointer in-place, 370 * if necessary. 371 * This function acts like cxReallocArray() using the pointer pointed to 372 * by @p mem. 373 * 374 * @note Re-allocating a block allocated by a different allocator is undefined. 375 * 376 * @par Error handling 377 * @c errno will be set, if the underlying realloc function does so or the 378 * multiplication of @p nmemb and @p size overflows. 379 * 380 * @param allocator (@c CxAllocator*) the allocator 381 * @param mem (@c void**) pointer to the pointer to allocated block 382 * @param nmemb (@c size_t) the number of elements 383 * @param size (@c size_t) the size of each element 384 * @retval zero success 385 * @retval non-zero failure 386 */ 387 #define cxReallocateArray(allocator, mem, nmemb, size) \ 388 cxReallocateArray_(allocator, (void**) (mem), nmemb, size) 389 390 /** 391 * Allocate @p nmemb elements of @p n bytes each, all initialized to zero. 392 * 393 * @param allocator the allocator 394 * @param nmemb the number of elements 395 * @param size the size of each element in bytes 396 * @return a pointer to the allocated memory 397 */ 398 cx_attr_nonnull_arg(1) cx_attr_nodiscard 399 cx_attr_malloc cx_attr_dealloc_ucx cx_attr_allocsize(2, 3) 400 CX_EXPORT void *cxCalloc(const CxAllocator *allocator, size_t nmemb, size_t size); 401 402 /** 403 * Allocate @p n bytes of memory and sets every byte to zero. 404 * 405 * @param allocator the allocator 406 * @param n the number of bytes 407 * @return a pointer to the allocated memory 408 */ 409 cx_attr_nodiscard cx_attr_nonnull 410 cx_attr_malloc cx_attr_dealloc_ucx cx_attr_allocsize(2) 411 CX_EXPORT void *cxZalloc(const CxAllocator *allocator, size_t n); 412 413 /** 414 * Convenience macro that invokes cxMalloc() with the cxDefaultAllocator. 415 */ 416 #define cxMallocDefault(...) cxMalloc(cxDefaultAllocator, __VA_ARGS__) 417 /** 418 * Convenience macro that invokes cxZalloc() with the cxDefaultAllocator. 419 */ 420 #define cxZallocDefault(...) cxZalloc(cxDefaultAllocator, __VA_ARGS__) 421 /** 422 * Convenience macro that invokes cxCalloc() with the cxDefaultAllocator. 423 */ 424 #define cxCallocDefault(...) cxCalloc(cxDefaultAllocator, __VA_ARGS__) 425 /** 426 * Convenience macro that invokes cxRealloc() with the cxDefaultAllocator. 427 */ 428 #define cxReallocDefault(...) cxRealloc(cxDefaultAllocator, __VA_ARGS__) 429 /** 430 * Convenience macro that invokes cxReallocate() with the cxDefaultAllocator. 431 */ 432 #define cxReallocateDefault(...) cxReallocate(cxDefaultAllocator, __VA_ARGS__) 433 /** 434 * Convenience macro that invokes cxReallocateArray() with the cxDefaultAllocator. 435 */ 436 #define cxReallocateArrayDefault(...) cxReallocateArray(cxDefaultAllocator, __VA_ARGS__) 437 /** 438 * Convenience macro that invokes cxReallocArray() with the cxDefaultAllocator. 439 */ 440 #define cxReallocArrayDefault(...) cxReallocArray(cxDefaultAllocator, __VA_ARGS__) 441 /** 442 * Convenience function that invokes cxFree() with the cxDefaultAllocator. 443 */ 444 CX_EXPORT void cxFreeDefault(void *mem); 445 446 #ifdef __cplusplus 447 } // extern "C" 448 #endif 449 450 #endif // UCX_ALLOCATOR_H 451