diff options
| author | kr.angelov <kr.angelov@gmail.com> | 2012-01-20 13:41:10 +0000 |
|---|---|---|
| committer | kr.angelov <kr.angelov@gmail.com> | 2012-01-20 13:41:10 +0000 |
| commit | 2eee382a62a909d5a3f2f5eda94f30fe68fd5335 (patch) | |
| tree | b0b0d513535895f244214aebf6358e172b8dce6d /src/runtime/c/gu/mem.h | |
| parent | b9728357126f8b9a6311cca17d9f0dcc2a7bfb9b (diff) | |
initial import of the C runtime
Diffstat (limited to 'src/runtime/c/gu/mem.h')
| -rw-r--r-- | src/runtime/c/gu/mem.h | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/src/runtime/c/gu/mem.h b/src/runtime/c/gu/mem.h new file mode 100644 index 000000000..4369f4036 --- /dev/null +++ b/src/runtime/c/gu/mem.h @@ -0,0 +1,276 @@ +/* + * Copyright 2010 University of Helsinki. + * + * This file is part of libgu. + * + * Libgu is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Libgu is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libgu. If not, see <http://www.gnu.org/licenses/>. + */ + +/** @file + * + * Memory allocation tools. + */ + +#ifndef GU_MEM_H_ +#define GU_MEM_H_ + +#include <gu/defs.h> +#include <gu/fun.h> + +/** @defgroup GuPool Memory pools */ +//@{ + + +/// A memory pool. +typedef struct GuPool GuPool; + +/// @name Creating a pool +//@{ + + +/// Create a new memory pool. +GU_ONLY GuPool* +gu_new_pool(void); + +/**< + * @return A new memory pool. + */ + + +//@private +GuPool* +gu_local_pool_(uint8_t* init_buf, size_t sz); + +//@private +#define GU_LOCAL_POOL_INIT_SIZE (16 * sizeof(GuWord)) + + +/// Create a stack-allocated memory pool. +#define gu_local_pool() \ + gu_local_pool_(gu_alloca(GU_LOCAL_POOL_INIT_SIZE), \ + GU_LOCAL_POOL_INIT_SIZE) +/**< + * @return A memory pool whose first chunk is allocated directly from + * the stack. This makes its creation faster, and more suitable for + * functions that usually allocate only a little memory from the pool + * until it is freed. + * + * @note The pool created with #gu_local_pool \e must be freed with + * #gu_pool_free before the end of the block where #gu_local_pool was + * called. + * + * @note Because #gu_local_pool uses relatively much stack space, it + * should not be used in the bodies of recursive functions. + */ + + +//@} +/// @name Destroying a pool +//@{ + + +/// Free a memory pool and all objects allocated from it. +void +gu_pool_free(GU_ONLY GuPool* pool); +/**< + * When the pool is freed, all finalizers registered by + * #gu_pool_finally on \p pool are invoked in reverse order of + * registration. + * + * @note After the pool is freed, all objects allocated from it become + * invalid and may no longer be used. */ + +//@} +/// @name Allocating from a pool +//@{ + + +/// Allocate memory with a specified alignment. +void* +gu_malloc_aligned(GuPool* pool, size_t size, size_t alignment); + +void* +gu_malloc_prefixed(GuPool* pool, size_t pre_align, size_t pre_size, + size_t align, size_t size); + +/// Allocate memory from a pool. +inline void* +gu_malloc(GuPool* pool, size_t size) { + return gu_malloc_aligned(pool, size, 0); +} + +#include <string.h> + +//@private +static inline void* +gu_malloc_init_aligned(GuPool* pool, size_t size, size_t alignment, + const void* init) +{ + void* p = gu_malloc_aligned(pool, size, alignment); + memcpy(p, init, size); + return p; +} + +//@private +static inline void* +gu_malloc_init(GuPool* pool, size_t size, const void* init) +{ + return gu_malloc_init_aligned(pool, size, 0, init); +} + + +/** Allocate memory to store an array of objects of a given type. */ + +#define gu_new_n(type, n, pool) \ + ((type*)gu_malloc_aligned((pool), \ + sizeof(type) * (n), \ + gu_alignof(type))) +/**< + * @param type The C type of the objects to allocate. + * + * @param n The number of objects to allocate. + * + * @param pool The memory pool to allocate from. + * + * @return A pointer to a heap-allocated array of \p n uninitialized + * objects of type \p type. + */ + + +/** Allocate memory to store an object of a given type. */ + +#define gu_new(type, pool) \ + gu_new_n(type, 1, pool) +/**< + * @param type The C type of the object to allocate. + * + * @param pool The memory pool to allocate from. + * + * @return A pointer to a heap-allocated uninitialized object of type + * \p type. + */ + + +#define gu_new_prefixed(pre_type, type, pool) \ + ((type*)(gu_malloc_prefixed((pool), \ + gu_alignof(pre_type), sizeof(pre_type), \ + gu_alignof(type), sizeof(type)))) + + + + + +#ifdef GU_HAVE_STATEMENT_EXPRESSIONS +#define gu_new_i(pool, type, ...) \ + ({ \ + type *gu_new_p_ = gu_new(type, pool); \ + memcpy((void*) gu_new_p_, &(type){ __VA_ARGS__ }, \ + sizeof(type)); \ + gu_new_p_; \ + }) +#else // GU_HAVE_STATEMENT_EXPRESSIONS +#define gu_new_i(pool, type, ...) \ + ((type*)gu_malloc_init_aligned((pool), sizeof(type), \ + gu_alignof(type), \ + &(type){ __VA_ARGS__ })) +#endif // GU_HAVE_STATEMENT_EXPRESSIONS + +/** @def gu_new_i(pool, type, ...) + * + * Allocate and initialize an object. + * + * @param pool The pool to allocate from. + * + * @param type The C type of the object to allocate. + * + * @param ... An initializer list for the object to allocate. + */ + +#define gu_new_s gu_new_i + +// Alas, there's no portable way to get the alignment of flex structs. +#define gu_new_flex(pool_, type_, flex_member_, n_elems_) \ + ((type_ *)gu_malloc_aligned( \ + (pool_), \ + GU_FLEX_SIZE(type_, flex_member_, n_elems_), \ + gu_flex_alignof(type_))) + + +//@} +/// @name Finalizers +//@{ + + +typedef struct GuFinalizer GuFinalizer; + +struct GuFinalizer { + void (*fn)(GuFinalizer* self); + ///< @param self A pointer to this finalizer. +}; + +/// Register a finalizer. +void gu_pool_finally(GuPool* pool, GuFinalizer* fini); + +/**< Register \p fini to be called when \p pool is destroyed. The + * finalizers are called in reverse order of registration. + */ + + +//@} +//@} + +/** @defgroup GuMemBuf Memory buffers + * + * Resizable blocks of heap-allocated memory. These operations differ + * from standard \c malloc, \c realloc and \c free -functions in that + * memory buffers are not allocated by exact size. Instead, a minimum + * size is requested, and the returned buffer may be larger. This + * gives the memory allocator more flexibility when the client code + * can make use of larger buffers than requested. + * */ + +//@{ + + +/// Allocate a new memory buffer. +GU_ONLY void* +gu_mem_buf_alloc(size_t min_size, size_t* real_size); +/**< + * @param min_size The minimum acceptable size for a returned memory block. + * + * @param[out] real_size The actual size of the returned memory + * block. This is never less than \p min_size. + * + * @return A pointer to the memory buffer. + */ + + +/// Allocate a new memory buffer to replace an old one. +GU_ONLY void* +gu_mem_buf_realloc( + GU_NULL GU_ONLY GU_RETURNED + void* buf, + size_t min_size, + size_t* real_size_out); + + +/// Free a memory buffer. +void +gu_mem_buf_free(GU_ONLY void* buf); + + +//@} + + +#endif // GU_MEM_H_ |
