aboutsummaryrefslogtreecommitdiffstats
path: root/gb.hpp
diff options
context:
space:
mode:
authorGravatar gingerBill 2015-11-27 00:20:44 +0000
committerGravatar gingerBill 2015-11-27 00:20:44 +0000
commit2159ae399a1fe0f9ff813f005b649a010b944bd0 (patch)
tree89a2c2021723a24b6cc72d6e076fca8693e389cc /gb.hpp
parentMany bug fixes (diff)
gb.hpp v0.25 - gb_math.hpp v0.03
0.25 - Faster Heap_Allocator for Windows using HeapAlloc 0.03 - Remove templated min/max/clamp
Diffstat (limited to 'gb.hpp')
-rw-r--r--gb.hpp149
1 files changed, 98 insertions, 51 deletions
diff --git a/gb.hpp b/gb.hpp
index 6c52e17..56237cf 100644
--- a/gb.hpp
+++ b/gb.hpp
@@ -1,4 +1,4 @@
-// gb.hpp - v0.24b - public domain C++11 helper library - no warranty implied; use at your own risk
+// gb.hpp - v0.25 - 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
/*
@@ -218,11 +218,6 @@ CONTENTS:
#include <sys/time.h>
#endif
-#ifndef GB_ARRAY_BOUND_CHECKING
-#define GB_ARRAY_BOUND_CHECKING 1
-#endif
-
-
#ifndef GB_DISABLE_COPY
#define GB_DISABLE_COPY(Type) \
Type(const Type&) = delete; \
@@ -838,7 +833,7 @@ namespace thread
Thread make();
void destroy(Thread* t);
void start(Thread* t, Thread_Function* func, void* data = nullptr, usize stack_size = 0);
-void stop(Thread* t);
+void join(Thread* t);
bool is_running(const Thread& t);
u32 current_id();
} // namespace thread
@@ -948,10 +943,18 @@ struct Allocator
/// Allocations are padded with to align them to the desired alignment
struct Heap_Allocator : Allocator
{
- Mutex mutex = mutex::make();
+ struct Header
+ {
+ usize size;
+ };
+
s64 total_allocated_count = 0;
s64 allocation_count = 0;
+#if defined(GB_SYSTEM_WINDOWS)
+ HANDLE heap_handle = HeapCreate(0, 0, 0);
+#endif
+
Heap_Allocator() = default;
virtual ~Heap_Allocator();
@@ -1042,6 +1045,7 @@ void* copy(const void* src, usize bytes, void* dest);
void* move(const void* src, usize bytes, void* dest);
bool equals(const void* a, const void* b, usize bytes);
+// TODO(bill): Should this be just zero(T*) ???
template <typename T>
T* zero_struct(T* ptr);
@@ -1049,6 +1053,12 @@ template <typename T>
T* copy_array(const T* src_array, usize count, T* dest_array);
// TODO(bill): Should I implement something like std::copy, std::fill, std::fill_n ???
+
+template <typename T>
+void swap(T* a, T* b);
+
+template <typename T, usize N>
+void swap(T (& a)[N], T (& b)[N]);
} // namespace memory
void* alloc(Allocator* a, usize size, usize align = GB_DEFAULT_ALIGNMENT);
@@ -1148,6 +1158,10 @@ void format_uint(u64 value, char* buffer, usize len);
/// ///
////////////////////////////////
+#ifndef GB_ARRAY_BOUND_CHECKING
+#define GB_ARRAY_BOUND_CHECKING 1
+#endif
+
/// Dynamic resizable array for POD types only
template <typename T>
struct Array
@@ -1281,7 +1295,6 @@ template <typename T> void remove_entry(Hash_Table<T>* h, typename const Hash_Ta
template <typename T> void remove_all(Hash_Table<T>* h, u64 key);
} // namespace multi_hash_table
-
////////////////////////////////
/// ///
/// Hash ///
@@ -1519,9 +1532,9 @@ Array<T>::Array(const Array<T>& other)
, capacity(0)
, data(nullptr)
{
- const auto n = other.count;
- array::set_capacity(this, n);
- memory::copy(other.data, n * sizeof(T), data);
+ const auto count = other.count;
+ array::set_capacity(this, count);
+ memory::copy_array(other.data, count, data);
count = n;
}
@@ -1552,9 +1565,9 @@ Array<T>::operator=(const Array<T>& other)
{
if (allocator == nullptr)
allocator = other.allocator;
- const auto n = other.count;
- array::resize(this, n);
- memory::copy(other.data, n * sizeof(T), data);
+ const auto count = other.count;
+ array::resize(this, count);
+ memory::copy_count(other.data, count, data);
return *this;
}
@@ -1660,7 +1673,7 @@ append(Array<T>* a, const T* items, usize count)
if (a->capacity <= a->count + static_cast<s64>(count))
array::grow(a, a->count + count);
- memory::copy(items, count * sizeof(T), &a->data[a->count]);
+ memory::copy_array(items, count, &a->data[a->count]);
a->count += count;
}
@@ -1711,7 +1724,7 @@ set_capacity(Array<T>* a, usize capacity)
if (capacity > 0)
{
data = alloc_array<T>(a->allocator, capacity);
- memory::copy(a->data, a->count * sizeof(T), data);
+ memory::copy_array(a->data, a->count, data);
}
dealloc(a->allocator, a->data);
a->data = data;
@@ -2200,6 +2213,23 @@ copy_array(const T* src_array, usize count, T* dest_array)
{
return static_cast<T*>(memory::copy(src_array, count * sizeof(T), dest_array));
}
+
+template <typename T>
+inline void
+swap(T* a, T* b)
+{
+ T c = __GB_NAMESPACE_START::move(*a);
+ *a = __GB_NAMESPACE_START::move(*b);
+ *b = __GB_NAMESPACE_START::move(c);
+}
+
+template <typename T, usize N>
+inline void
+swap(T (& a)[N], T (& b)[N])
+{
+ for (usize i = 0; i < N; i++)
+ math::swap(&a[i], &b[i]);
+}
} // namespace memory
@@ -2594,11 +2624,11 @@ make()
#else
t.posix_handle = 0;
#endif
- t.function = nullptr;
- t.data = nullptr;
+ t.function = nullptr;
+ t.data = nullptr;
t.stack_size = 0;
t.is_running = false;
- t.semaphore = semaphore::make();
+ t.semaphore = semaphore::make();
return t;
}
@@ -2607,7 +2637,7 @@ void
destroy(Thread* t)
{
if (t->is_running)
- thread::stop(t);
+ thread::join(t);
semaphore::destroy(&t->semaphore);
}
@@ -2677,7 +2707,7 @@ start(Thread* t, Thread_Function* func, void* data, usize stack_size)
}
void
-stop(Thread* t)
+join(Thread* t)
{
if (!t->is_running)
return;
@@ -2705,13 +2735,11 @@ current_id()
{
u32 thread_id;
-
#if defined(GB_SYSTEM_WINDOWS)
u8* thread_local_storage = reinterpret_cast<u8*>(__readgsqword(0x30));
thread_id = *reinterpret_cast<u32*>(thread_local_storage + 0x48);
#elif defined(GB_SYSTEM_OSX) && defined(GB_ARCH_64_BIT)
- u32 thread_id;
asm("mov %%gs:0x00,%0" : "=r"(thread_id));
#elif defined(GB_ARCH_32_BIT)
asm("mov %%gs:0x08,%0" : "=r"(thread_id));
@@ -2721,7 +2749,6 @@ current_id()
#error Unsupported architecture for thread::current_id()
#endif
-
return thread_id;
}
@@ -2886,24 +2913,32 @@ free(Data* tmp)
#else
-//#define GB_HEAP_ALLOCATOR_HEADER_PAD_VALUE (usize)(-1)
Heap_Allocator::~Heap_Allocator()
{
-#if 0
- GB_ASSERT(allocation_count == 0 && total_allocated() == 0,
- "Heap Allocator: allocation count = %lld; total allocated = %lld",
- allocation_count, total_allocated());
+#if defined (GB_SYSTEM_WINDOWS)
+ HeapDestroy(heap_handle);
+#else
+
#endif
}
void*
Heap_Allocator::alloc(usize size, usize align)
{
- mutex::lock(&mutex);
- defer (mutex::unlock(&mutex));
-
usize total = size + align - (size % align);
+
+#if defined (GB_SYSTEM_WINDOWS)
+ total += sizeof(Header);
+
+ void* data = HeapAlloc(heap_handle, 0, total);
+ Header* h = static_cast<Header*>(data);
+ h->size = total;
+ data = (h + 1);
+
+#else
+ // TODO(bill): Find a better malloc alternative for this platform
void* data = malloc(total);
+#endif
total_allocated_count += total;
allocation_count++;
@@ -2917,27 +2952,34 @@ Heap_Allocator::dealloc(const void* ptr)
if (!ptr)
return;
- mutex::lock(&mutex);
- defer (mutex::unlock(&mutex));
-
total_allocated_count -= this->allocated_size(ptr);
allocation_count--;
+#if defined (GB_SYSTEM_WINDOWS)
+ ptr = static_cast<const Header*>(ptr) + 1;
+ HeapFree(heap_handle, 0, const_cast<void*>(ptr));
+
+#else
::free(const_cast<void*>(ptr));
+
+#endif
}
inline s64
Heap_Allocator::allocated_size(const void* ptr)
{
- mutex::lock(&mutex);
- defer (mutex::unlock(&mutex));
-
#if defined(GB_SYSTEM_WINDOWS)
- return static_cast<usize>(_msize(const_cast<void*>(ptr)));
+ const Header* h = static_cast<const Header*>(ptr) - 1;
+ return static_cast<usize>(h->size);
+
#elif defined(GB_SYSTEM_OSX)
return static_cast<usize>(malloc_size(ptr));
-#else
+
+#elif defined(GB_SYSTEM_LINUX)
return static_cast<usize>(malloc_usable_size(const_cast<void*>(ptr)));
+
+#else
+ #error Implement Heap_Allocator::allocated_size
#endif
}
@@ -2971,8 +3013,10 @@ Arena_Allocator::~Arena_Allocator()
if (backing)
backing->dealloc(physical_start);
- GB_ASSERT(total_allocated_count == 0,
- "Memory leak of %ld bytes, maybe you forgot to call arena_allocator::clear()?", total_allocated_count);
+ GB_ASSERT(temp_count == 0,
+ "%ld Temporary_Arena_Memory have not be cleared", temp_count);
+
+ total_allocated_count = 0;
}
void*
@@ -3035,7 +3079,6 @@ free(Temporary_Arena_Memory* tmp)
#endif
-
////////////////////////////////
/// ///
/// Memory ///
@@ -3197,17 +3240,19 @@ make(Allocator* a, const void* init_str, Size len)
{
usize header_size = sizeof(string::Header);
void* ptr = alloc(a, header_size + len + 1);
+ if (!ptr)
+ return nullptr;
+
if (!init_str)
memory::zero(ptr, header_size + len + 1);
- if (ptr == nullptr)
- return nullptr;
-
String str = static_cast<char*>(ptr) + header_size;
+
string::Header* header = string::header(str);
header->allocator = a;
header->len = len;
header->cap = len;
+
if (len && init_str)
memory::copy(init_str, len, str);
str[len] = '\0';
@@ -3220,10 +3265,11 @@ free(String str)
{
if (str == nullptr)
return;
+
string::Header* h = string::header(str);
- Allocator* a = h->allocator;
- if (a)
- dealloc(a, h);
+
+ if (h->allocator)
+ dealloc(h->allocator, h);
}
inline String
@@ -3337,7 +3383,7 @@ make_space_for(String* str, Size add_len)
if (available >= add_len) // Return if there is enough space left
return;
- void* ptr = reinterpret_cast<string::Header*>(*str) - 1;
+ void* ptr = reinterpret_cast<string::Header*>(str) - 1;
usize old_size = sizeof(string::Header) + string::length(*str) + 1;
usize new_size = sizeof(string::Header) + new_len + 1;
@@ -4302,6 +4348,7 @@ __GB_NAMESPACE_END
/*
Version History:
+ 0.25 - Faster Heap_Allocator for Windows using HeapAlloc
0.24b - Even More Hash_Table Bug Fixes
0.24a - Hash_Table Bug Fixes
0.24 - More documentation and bug fixes