gb.hpp - Hash_Table bug fixes
This commit is contained in:
parent
816e259257
commit
d4a4a0770a
|
@ -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
135
gb.hpp
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue