diff --git a/source/lib/allocators.h b/source/lib/allocators.h index f789d4dc1c..8dd37f35e3 100644 --- a/source/lib/allocators.h +++ b/source/lib/allocators.h @@ -124,4 +124,70 @@ extern void** matrix_alloc(uint cols, uint rows, size_t el_size); // (e.g. int**); they must be cast to void**. extern void matrix_free(void** matrix); + + + +template class OverrunProtector +{ + DynArray da; + T* cached_ptr; + uintptr_t initialized; + +public: + OverrunProtector() + { + memset(&da, 0, sizeof(da)); + cached_ptr = 0; + initialized = 0; + } + + ~OverrunProtector() + { + initialized = 2; + cached_ptr->~T(); // call dtor (since we used placement new) + cached_ptr = 0; + (void)da_free(&da); + } + + void lock() + { + da_set_prot(&da, PROT_NONE); + } + +private: + void unlock() + { + da_set_prot(&da, PROT_READ|PROT_WRITE); + } + + void init() + { + const size_t size = 4096; + cassert(sizeof(T) <= size); + if(da_alloc(&da, size) < 0) + goto fail; + if(da_set_size(&da, size) < 0) + goto fail; + +#include "nommgr.h" + cached_ptr = new(da.base) T(); +#include "mmgr.h" + lock(); + return; // success + +fail: + debug_warn("OverrunProtector mem alloc failed"); + } + +public: + T* get() + { + if(CAS(&initialized, 0, 1)) + init(); + debug_assert(initialized != 2 && "OverrunProtector: used after dtor called:"); + unlock(); + return cached_ptr; + } +}; + #endif // #ifndef ALLOCATORS_H__ diff --git a/source/lib/res/h_mgr.cpp b/source/lib/res/h_mgr.cpp index 011e6003fb..7f54bb2e61 100755 --- a/source/lib/res/h_mgr.cpp +++ b/source/lib/res/h_mgr.cpp @@ -339,60 +339,13 @@ static int free_idx(i32 idx) typedef STL_HASH_MULTIMAP Key2Idx; typedef Key2Idx::iterator It; - -static DynArray key2idx_da; -static Key2Idx* key2idx_; - -static void key2idx_lock() -{ - da_set_prot(&key2idx_da, PROT_NONE); -} - -static void key2idx_unlock() -{ - da_set_prot(&key2idx_da, PROT_READ|PROT_WRITE); -} - -static void key2idx_init(void) -{ - const size_t size = 4096; - cassert(sizeof(Key2Idx) <= size); - if(da_alloc(&key2idx_da, size) < 0) - goto fail; - if(da_set_size(&key2idx_da, size) < 0) - goto fail; - -#include "nommgr.h" - key2idx_ = new(key2idx_da.base) Key2Idx; -#include "mmgr.h" - key2idx_lock(); - return; // success - -fail: - debug_warn("key2idx mem alloc failed"); -} - -static void key2idx_shutdown() -{ - key2idx_ = 0; - (void)da_free(&key2idx_da); -} - - -static Key2Idx* key2idx_get() -{ - static pthread_once_t key2idx_once = PTHREAD_ONCE_INIT; - pthread_once(&key2idx_once, key2idx_init); - key2idx_unlock(); - return key2idx_; -} - +static OverrunProtector key2idx_wrapper; enum KeyRemoveFlag { KEY_NOREMOVE, KEY_REMOVE }; static Handle key_find(uintptr_t key, H_Type type, KeyRemoveFlag remove_option = KEY_NOREMOVE) { - Key2Idx* key2idx = key2idx_get(); + Key2Idx* key2idx = key2idx_wrapper.get(); if(!key2idx) return ERR_NO_MEM; @@ -417,14 +370,14 @@ static Handle key_find(uintptr_t key, H_Type type, KeyRemoveFlag remove_option = } } - key2idx_lock(); + key2idx_wrapper.lock(); return ret; } static void key_add(uintptr_t key, Handle h) { - Key2Idx* key2idx = key2idx_get(); + Key2Idx* key2idx = key2idx_wrapper.get(); if(!key2idx) return; @@ -433,7 +386,7 @@ static void key_add(uintptr_t key, Handle h) // there is no overload of insert() that returns pair. (void)key2idx->insert(std::make_pair(key, idx)); - key2idx_lock(); + key2idx_wrapper.lock(); } @@ -1020,6 +973,4 @@ void h_mgr_shutdown() } fn_shutdown(); - - key2idx_shutdown(); }