gb.hpp - Hash_Table bug fixes

This commit is contained in:
gingerBill 2015-11-01 00:45:54 +00:00
parent 816e259257
commit d4a4a0770a
2 changed files with 84 additions and 75 deletions

View File

@ -6,7 +6,7 @@ library | latest version | category | languages | description
----------------|----------------|----------|-----------|------------- ----------------|----------------|----------|-----------|-------------
**gb_string.h** | 0.93 | strings | C, C++ | A better string library for C & C++ **gb_string.h** | 0.93 | strings | C, C++ | A better string library for C & C++
**gb_ini.h** | 0.91 | misc | C, C++ | A simple ini file loader library for C & C++ **gb_ini.h** | 0.91 | misc | C, C++ | A simple ini file loader library for C & C++
**gb.hpp** | 0.16 | misc | C++11 | (Experimental) A C++11 helper library without STL geared towards game development **gb.hpp** | 0.18 | misc | C++11 | (Experimental) A C++11 helper library without STL geared towards game development
## FAQ ## FAQ

135
gb.hpp
View File

@ -1,8 +1,9 @@
// gb.hpp - v0.16 - public domain C++11 helper library - no warranty implied; use at your own risk // gb.hpp - v0.18 - public domain C++11 helper library - no warranty implied; use at your own risk
// (Experimental) A C++11 helper library without STL geared towards game development // (Experimental) A C++11 helper library without STL geared towards game development
/* /*
Version History: Version History:
0.18 - Hash_Table bug fixes
0.17 - Death to OOP 0.17 - Death to OOP
0.16 - All References are const convention 0.16 - All References are const convention
0.15 - Namespaced Types 0.15 - Namespaced Types
@ -703,10 +704,10 @@ struct Thread
namespace thread namespace thread
{ {
Thread make(); Thread make();
void destroy(Thread* thread); void destroy(Thread* t);
void start(Thread* thread, Thread_Function* func, void* data = nullptr, usize stack_size = 0); void start(Thread* t, Thread_Function* func, void* data = nullptr, usize stack_size = 0);
void stop(Thread* thread); void stop(Thread* t);
bool is_running(const Thread& thread); bool is_running(const Thread& t);
} // namespace thread } // namespace thread
@ -898,8 +899,8 @@ template <usize BUFFER_SIZE>
void* void*
Temp_Allocator<BUFFER_SIZE>::alloc(usize size, usize align) Temp_Allocator<BUFFER_SIZE>::alloc(usize size, usize align)
{ {
current_pointer = (u8*)memory::align_forward(current_pointer, align); current_pointer = static_cast<u8*>(memory::align_forward(current_pointer, align));
if (size > (usize)physical_end - current_pointer) if (size > static_cast<usize>(physical_end) - current_pointer)
{ {
usize to_allocate = sizeof(void*) + size + align; usize to_allocate = sizeof(void*) + size + align;
if (to_allocate < chunk_size) if (to_allocate < chunk_size)
@ -907,10 +908,10 @@ Temp_Allocator<BUFFER_SIZE>::alloc(usize size, usize align)
chunk_size *= 2; chunk_size *= 2;
void* ptr = backing_->alloc(to_allocate); void* ptr = backing_->alloc(to_allocate);
*static_cast<void**>(physical_start) = ptr; *static_cast<void**>(physical_start) = ptr;
current_pointer = physical_start = (u8*)ptr; current_pointer = physical_start = static_cast<u8*>(ptr);
*static_cast<void**>(physical_start) = 0; *static_cast<void**>(physical_start) = 0;
current_pointer = memory::pointer_add(current_pointer, sizeof(void*)); current_pointer = memory::pointer_add(current_pointer, sizeof(void*));
current_pointer = (u8*)memory::align_forward(current_pointer, align); current_pointer = static_cast<u8*>(memory::align_forward(current_pointer, align));
} }
void* result = current_pointer; void* result = current_pointer;
@ -918,7 +919,6 @@ Temp_Allocator<BUFFER_SIZE>::alloc(usize size, usize align)
return (result); return (result);
} }
namespace memory namespace memory
{ {
inline void* inline void*
@ -1161,7 +1161,7 @@ struct Hash_Table
Array<s64> hashes; Array<s64> hashes;
Array<Entry> entries; Array<Entry> entries;
Hash_Table() = default; Hash_Table();
explicit Hash_Table(Allocator* a); explicit Hash_Table(Allocator* a);
Hash_Table(const Hash_Table<T>& other); Hash_Table(const Hash_Table<T>& other);
Hash_Table<T>& operator=(const Hash_Table<T>& other); Hash_Table<T>& operator=(const Hash_Table<T>& other);
@ -1226,7 +1226,6 @@ Array<T>::Array(Allocator* a, usize count_)
, capacity(0) , capacity(0)
, data(nullptr) , data(nullptr)
{ {
if (count_ > 0) if (count_ > 0)
{ {
data = alloc_array<T>(a, count_); data = alloc_array<T>(a, count_);
@ -1254,7 +1253,7 @@ template <typename T>
inline inline
Array<T>::~Array() Array<T>::~Array()
{ {
if (allocator) if (allocator && capacity > 0)
dealloc(allocator, data); dealloc(allocator, data);
} }
@ -1263,6 +1262,8 @@ template <typename T>
Array<T>& Array<T>&
Array<T>::operator=(const Array<T>& other) Array<T>::operator=(const Array<T>& other)
{ {
if (allocator == nullptr)
allocator = other.allocator;
const auto n = other.count; const auto n = other.count;
array::resize(this, n); array::resize(this, n);
memory::copy(data, other.data, n * sizeof(T)); memory::copy(data, other.data, n * sizeof(T));
@ -1276,11 +1277,8 @@ template <typename T>
inline Array<T> inline Array<T>
make(Allocator* allocator, usize count) make(Allocator* allocator, usize count)
{ {
Array<T> array = {}; Array<T> array{allocator};
array.allocator = allocator;
array.count = 0;
array.capacity = 0;
array.data = nullptr;
if (count > 0) if (count > 0)
{ {
array.data = alloc_array<T>(allocator, count); array.data = alloc_array<T>(allocator, count);
@ -1293,10 +1291,10 @@ make(Allocator* allocator, usize count)
template <typename T> template <typename T>
inline void inline void
dealloc(Array<T>* array) dealloc(Array<T>* a)
{ {
if (array.allocator) if (a->allocator)
dealloc(array.allocator, array.data); dealloc(a->allocator, a->data);
} }
template <typename T> template <typename T>
@ -1312,7 +1310,7 @@ template <typename T>
inline void inline void
append(Array<T>* a, const T* items, usize count) append(Array<T>* a, const T* items, usize count)
{ {
if (a->capacity <= a->count + count) if (a->capacity <= a->count + static_cast<s64>(count))
array::grow(a, a->count + count); array::grow(a, a->count + count);
memory::copy(&a->data[a->count], items, count * sizeof(T)); memory::copy(&a->data[a->count], items, count * sizeof(T));
@ -1389,6 +1387,13 @@ grow(Array<T>* a, usize min_capacity)
/// Hash Table /// /// Hash Table ///
/// /// /// ///
//////////////////////////////// ////////////////////////////////
template <typename T>
inline
Hash_Table<T>::Hash_Table()
: hashes()
, entries()
{
}
template <typename T> template <typename T>
inline inline
@ -1422,7 +1427,8 @@ template <typename T>
inline Hash_Table<T> inline Hash_Table<T>
make(Allocator* a) make(Allocator* a)
{ {
return Hash_Table<T>(a); Hash_Table<T> h{a};
return h;
} }
namespace impl namespace impl
@ -1602,11 +1608,11 @@ rehash(Hash_Table<T>* h, usize new_capacity)
multi_hash_table::insert(&nh, e.key, e.value); multi_hash_table::insert(&nh, e.key, e.value);
} }
auto empty = hash_table::make<T>(h->hashes.allocator); Hash_Table<T> empty_ht{h->hashes.allocator};
h->~Hash_Table<T>(); h->~Hash_Table<T>();
memory::copy(&h, &nh, sizeof(Hash_Table<T>)); memory::copy(h, &nh, sizeof(Hash_Table<T>));
memory::copy(&nh, &empty, sizeof(Hash_Table<T>)); memory::copy(&nh, &empty_ht, sizeof(Hash_Table<T>));
} }
template <typename T> template <typename T>
@ -2275,6 +2281,7 @@ extern const f32 PI;
extern const f32 TAU; extern const f32 TAU;
extern const f32 SQRT_2; extern const f32 SQRT_2;
extern const f32 SQRT_3; extern const f32 SQRT_3;
extern const f32 SQRT_5;
extern const f32 F32_PRECISION; extern const f32 F32_PRECISION;
@ -3130,43 +3137,43 @@ namespace thread
Thread Thread
make() make()
{ {
Thread thread = {}; Thread t = {};
#if defined(GB_SYSTEM_WINDOWS) #if defined(GB_SYSTEM_WINDOWS)
thread.win32_handle = INVALID_HANDLE_VALUE; t.win32_handle = INVALID_HANDLE_VALUE;
#else #else
thread.posix_handle = 0; t.posix_handle = 0;
#endif #endif
thread.function = nullptr; t.function = nullptr;
thread.data = nullptr; t.data = nullptr;
thread.stack_size = 0; t.stack_size = 0;
thread.is_running = false; t.is_running = false;
thread.semaphore = semaphore::make(); t.semaphore = semaphore::make();
return thread; return t;
} }
void void
destroy(Thread* thread) destroy(Thread* t)
{ {
if (thread->is_running) if (t->is_running)
thread::stop(thread); thread::stop(t);
semaphore::destroy(&thread->semaphore); semaphore::destroy(&t->semaphore);
} }
internal s32 internal s32
run(Thread* thread) run(Thread* t)
{ {
semaphore::post(&thread->semaphore); semaphore::post(&t->semaphore);
return thread->function(thread->data); return t->function(t->data);
} }
#if defined(GB_SYSTEM_WINDOWS) #if defined(GB_SYSTEM_WINDOWS)
internal DWORD WINAPI internal DWORD WINAPI
thread_proc(void* arg) thread_proc(void* arg)
{ {
Thread* thread = static_cast<Thread*>(arg); Thread* t = static_cast<Thread*>(arg);
s32 result = thread::run(thread); s32 result = thread::run(t);
return result; return result;
} }
@ -3182,17 +3189,17 @@ thread_proc(void* arg)
#endif #endif
void void
start(Thread* thread, Thread_Function* func, void* data, usize stack_size) start(Thread* t, Thread_Function* func, void* data, usize stack_size)
{ {
GB_ASSERT(!thread->is_running); GB_ASSERT(!t->is_running);
GB_ASSERT(func != nullptr); GB_ASSERT(func != nullptr);
thread->function = func; t->function = func;
thread->data = data; t->data = data;
thread->stack_size = stack_size; t->stack_size = stack_size;
#if defined(GB_SYSTEM_WINDOWS) #if defined(GB_SYSTEM_WINDOWS)
thread->win32_handle = CreateThread(nullptr, stack_size, thread_proc, thread, 0, nullptr); t->win32_handle = CreateThread(nullptr, stack_size, thread_proc, t, 0, nullptr);
GB_ASSERT(thread->win32_handle != nullptr, GB_ASSERT(t->win32_handle != nullptr,
"CreateThread: GetLastError = %d", GetLastError()); "CreateThread: GetLastError = %d", GetLastError());
#else #else
@ -3201,13 +3208,13 @@ start(Thread* thread, Thread_Function* func, void* data, usize stack_size)
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
GB_ASSERT(result == 0, "pthread_attr_init: errno = %d", result); GB_ASSERT(result == 0, "pthread_attr_init: errno = %d", result);
if (thread->stack_size != 0) if (t->stack_size != 0)
{ {
result = pthread_attr_setstacksize(&attr, thread->stack_size); result = pthread_attr_setstacksize(&attr, t->stack_size);
GB_ASSERT(result == 0, "pthread_attr_setstacksize: errno = %d", result); GB_ASSERT(result == 0, "pthread_attr_setstacksize: errno = %d", result);
} }
result = pthread_create(&thread->posix_handle, &attr, thread_proc, thread); result = pthread_create(&t->posix_handle, &attr, thread_proc, thread);
GB_ASSERT(result == 0, "pthread_create: errno = %d", result); GB_ASSERT(result == 0, "pthread_create: errno = %d", result);
// NOTE(bill): Free attr memory // NOTE(bill): Free attr memory
@ -3217,25 +3224,26 @@ start(Thread* thread, Thread_Function* func, void* data, usize stack_size)
// NOTE(bill): So much boiler patch compared to windows.h (for once) // NOTE(bill): So much boiler patch compared to windows.h (for once)
#endif #endif
thread->is_running = true; t->is_running = true;
semaphore::wait(&thread->semaphore); semaphore::wait(&t->semaphore);
} }
void void
stop(Thread* thread) stop(Thread* t)
{ {
if (!thread->is_running) if (!t->is_running)
return; return;
#if defined(GB_SYSTEM_WINDOWS) #if defined(GB_SYSTEM_WINDOWS)
WaitForSingleObject(thread->win32_handle, INFINITE); WaitForSingleObject(t->win32_handle, INFINITE);
CloseHandle(thread->win32_handle); CloseHandle(t->win32_handle);
thread->win32_handle = INVALID_HANDLE_VALUE; t->win32_handle = INVALID_HANDLE_VALUE;
#else #else
int result = pthread_join(t->posix_handle, nullptr);
t->posix_handle = 0;
#endif #endif
thread->is_running = false; t->is_running = false;
} }
bool bool
@ -5187,6 +5195,7 @@ const f32 PI = 3.141592654f;
const f32 TAU = 6.283185307f; const f32 TAU = 6.283185307f;
const f32 SQRT_2 = 1.414213562f; const f32 SQRT_2 = 1.414213562f;
const f32 SQRT_3 = 1.732050808f; const f32 SQRT_3 = 1.732050808f;
const f32 SQRT_5 = 2.236067978f;
const f32 F32_PRECISION = 1.0e-7f; const f32 F32_PRECISION = 1.0e-7f;