mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-05-07 18:22:50 -06:00
initial import of the C runtime
This commit is contained in:
276
src/runtime/c/gu/mem.h
Normal file
276
src/runtime/c/gu/mem.h
Normal file
@@ -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_
|
||||
Reference in New Issue
Block a user