From 68bc62a7fa5febbf5c8ab2fe8f6171121d18690f Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Tue, 19 Apr 2016 14:57:31 -0700 Subject: Split upb::Arena/upb::Allocator from upb::Environment. (#58) * Split upb::Arena/upb::Allocator from upb::Environment. This will allow arenas and allocators to be used independently of environments, which will be important for an upcoming change (a message representation). Overall this design feels cleaner that the previous Environment/SeededAllocator design. As part of this change, moved all allocations in upb to use a global allocator instead of hard-coding malloc/free. This will allow injecting OOM faults for more robust testing. One place that doesn't use the global allocator is the tracked ref code. Instead of its previous approach of CHECK_OOM() after every malloc() or table insert, it simply uses an allocator that does this automatically. I moved Allocator/Arena/Environment into upb.h. This seems principled since these are the only types in upb whose size is directly exposed to users, since they form the basis of memory allocation strategy. * Cleaned up some header includes and fixed more malloc -> upb_gmalloc(). * Changes from PR review. * Don't use UINTPTR_MAX or UINT64_MAX. * Punt on adding line/file for now. * We actually can't store (uint64_t)-1, update comment and test. --- upb/env.h | 262 -------------------------------------------------------------- 1 file changed, 262 deletions(-) delete mode 100644 upb/env.h (limited to 'upb/env.h') diff --git a/upb/env.h b/upb/env.h deleted file mode 100644 index 3d3585e..0000000 --- a/upb/env.h +++ /dev/null @@ -1,262 +0,0 @@ -/* -** upb::Environment (upb_env) -** -** A upb::Environment provides a means for injecting malloc and an -** error-reporting callback into encoders/decoders. This allows them to be -** independent of nearly all assumptions about their actual environment. -** -** It is also a container for allocating the encoders/decoders themselves that -** insulates clients from knowing their actual size. This provides ABI -** compatibility even if the size of the objects change. And this allows the -** structure definitions to be in the .c files instead of the .h files, making -** the .h files smaller and more readable. -*/ - -#include "upb/upb.h" - -#ifndef UPB_ENV_H_ -#define UPB_ENV_H_ - -#ifdef __cplusplus -namespace upb { -class Environment; -class SeededAllocator; -} -#endif - -UPB_DECLARE_TYPE(upb::Environment, upb_env) -UPB_DECLARE_TYPE(upb::SeededAllocator, upb_seededalloc) - -typedef void *upb_alloc_func(void *ud, void *ptr, size_t oldsize, size_t size); -typedef void upb_cleanup_func(void *ud); -typedef bool upb_error_func(void *ud, const upb_status *status); - -#ifdef __cplusplus - -/* An environment is *not* thread-safe. */ -class upb::Environment { - public: - Environment(); - ~Environment(); - - /* Set a custom memory allocation function for the environment. May ONLY - * be called before any calls to Malloc()/Realloc()/AddCleanup() below. - * If this is not called, the system realloc() function will be used. - * The given user pointer "ud" will be passed to the allocation function. - * - * The allocation function will not receive corresponding "free" calls. it - * must ensure that the memory is valid for the lifetime of the Environment, - * but it may be reclaimed any time thereafter. The likely usage is that - * "ud" points to a stateful allocator, and that the allocator frees all - * memory, arena-style, when it is destroyed. In this case the allocator must - * outlive the Environment. Another possibility is that the allocation - * function returns GC-able memory that is guaranteed to be GC-rooted for the - * life of the Environment. */ - void SetAllocationFunction(upb_alloc_func* alloc, void* ud); - - template - void SetAllocator(T* allocator) { - SetAllocationFunction(allocator->GetAllocationFunction(), allocator); - } - - /* Set a custom error reporting function. */ - void SetErrorFunction(upb_error_func* func, void* ud); - - /* Set the error reporting function to simply copy the status to the given - * status and abort. */ - void ReportErrorsTo(Status* status); - - /* Returns true if all allocations and AddCleanup() calls have succeeded, - * and no errors were reported with ReportError() (except ones that recovered - * successfully). */ - bool ok() const; - - /* Functions for use by encoders/decoders. **********************************/ - - /* Reports an error to this environment's callback, returning true if - * the caller should try to recover. */ - bool ReportError(const Status* status); - - /* Allocate memory. Uses the environment's allocation function. - * - * There is no need to free(). All memory will be freed automatically, but is - * guaranteed to outlive the Environment. */ - void* Malloc(size_t size); - - /* Reallocate memory. Preserves "oldsize" bytes from the existing buffer - * Requires: oldsize <= existing_size. - * - * TODO(haberman): should we also enforce that oldsize <= size? */ - void* Realloc(void* ptr, size_t oldsize, size_t size); - - /* Add a cleanup function to run when the environment is destroyed. - * Returns false on out-of-memory. - * - * The first call to AddCleanup() after SetAllocationFunction() is guaranteed - * to return true -- this makes it possible to robustly set a cleanup handler - * for a custom allocation function. */ - bool AddCleanup(upb_cleanup_func* func, void* ud); - - /* Total number of bytes that have been allocated. It is undefined what - * Realloc() does to this counter. */ - size_t BytesAllocated() const; - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(Environment) - -#else -struct upb_env { -#endif /* __cplusplus */ - - bool ok_; - size_t bytes_allocated; - - /* Alloc function. */ - upb_alloc_func *alloc; - void *alloc_ud; - - /* Error-reporting function. */ - upb_error_func *err; - void *err_ud; - - /* Userdata for default alloc func. */ - void *default_alloc_ud; - - /* Cleanup entries. Pointer to a cleanup_ent, defined in env.c */ - void *cleanup_head; - - /* For future expansion, since the size of this struct is exposed to users. */ - void *future1; - void *future2; -}; - -UPB_BEGIN_EXTERN_C - -void upb_env_init(upb_env *e); -void upb_env_uninit(upb_env *e); -void upb_env_setallocfunc(upb_env *e, upb_alloc_func *func, void *ud); -void upb_env_seterrorfunc(upb_env *e, upb_error_func *func, void *ud); -void upb_env_reporterrorsto(upb_env *e, upb_status *status); -bool upb_env_ok(const upb_env *e); -bool upb_env_reporterror(upb_env *e, const upb_status *status); -void *upb_env_malloc(upb_env *e, size_t size); -void *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size); -bool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud); -size_t upb_env_bytesallocated(const upb_env *e); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -/* An allocator that allocates from an initial memory region (likely the stack) - * before falling back to another allocator. */ -class upb::SeededAllocator { - public: - SeededAllocator(void *mem, size_t len); - ~SeededAllocator(); - - /* Set a custom fallback memory allocation function for the allocator, to use - * once the initial region runs out. - * - * May ONLY be called before GetAllocationFunction(). If this is not - * called, the system realloc() will be the fallback allocator. */ - void SetFallbackAllocator(upb_alloc_func *alloc, void *ud); - - /* Gets the allocation function for this allocator. */ - upb_alloc_func* GetAllocationFunction(); - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(SeededAllocator) - -#else -struct upb_seededalloc { -#endif /* __cplusplus */ - - /* Fallback alloc function. */ - upb_alloc_func *alloc; - upb_cleanup_func *alloc_cleanup; - void *alloc_ud; - bool need_cleanup; - bool returned_allocfunc; - - /* Userdata for default alloc func. */ - void *default_alloc_ud; - - /* Pointers for the initial memory region. */ - char *mem_base; - char *mem_ptr; - char *mem_limit; - - /* For future expansion, since the size of this struct is exposed to users. */ - void *future1; - void *future2; -}; - -UPB_BEGIN_EXTERN_C - -void upb_seededalloc_init(upb_seededalloc *a, void *mem, size_t len); -void upb_seededalloc_uninit(upb_seededalloc *a); -void upb_seededalloc_setfallbackalloc(upb_seededalloc *a, upb_alloc_func *func, - void *ud); -upb_alloc_func *upb_seededalloc_getallocfunc(upb_seededalloc *a); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upb { - -inline Environment::Environment() { - upb_env_init(this); -} -inline Environment::~Environment() { - upb_env_uninit(this); -} -inline void Environment::SetAllocationFunction(upb_alloc_func *alloc, - void *ud) { - upb_env_setallocfunc(this, alloc, ud); -} -inline void Environment::SetErrorFunction(upb_error_func *func, void *ud) { - upb_env_seterrorfunc(this, func, ud); -} -inline void Environment::ReportErrorsTo(Status* status) { - upb_env_reporterrorsto(this, status); -} -inline bool Environment::ok() const { - return upb_env_ok(this); -} -inline bool Environment::ReportError(const Status* status) { - return upb_env_reporterror(this, status); -} -inline void *Environment::Malloc(size_t size) { - return upb_env_malloc(this, size); -} -inline void *Environment::Realloc(void *ptr, size_t oldsize, size_t size) { - return upb_env_realloc(this, ptr, oldsize, size); -} -inline bool Environment::AddCleanup(upb_cleanup_func *func, void *ud) { - return upb_env_addcleanup(this, func, ud); -} -inline size_t Environment::BytesAllocated() const { - return upb_env_bytesallocated(this); -} - -inline SeededAllocator::SeededAllocator(void *mem, size_t len) { - upb_seededalloc_init(this, mem, len); -} -inline SeededAllocator::~SeededAllocator() { - upb_seededalloc_uninit(this); -} -inline void SeededAllocator::SetFallbackAllocator(upb_alloc_func *alloc, - void *ud) { - upb_seededalloc_setfallbackalloc(this, alloc, ud); -} -inline upb_alloc_func *SeededAllocator::GetAllocationFunction() { - return upb_seededalloc_getallocfunc(this); -} - -} /* namespace upb */ - -#endif /* __cplusplus */ - -#endif /* UPB_ENV_H_ */ -- cgit v1.2.3