From 2943d418e2a553648110fe3e3025b2b708fa2151 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Tue, 26 Nov 2024 01:11:10 +0100 Subject: [PATCH] cleanup --- asset/Asset.h | 2 - audio/Audio.h | 10 - compression/Huffman.h | 3 +- input/ControllerInput.h | 2 + log/Debug.cpp | 4 +- log/Debug.h | 5 +- log/Log.h | 8 - log/TimingStat.h | 1 - memory/BufferMemory.h | 12 +- memory/ChunkMemory.h | 8 +- memory/Heap.h | 154 ++++++++++ memory/Queue.h | 85 ++---- memory/RingMemory.h | 56 +++- memory/ThreadedQueue.h | 204 +++++++++++++ models/mob/PrimaryStatsPoints.h | 2 +- models/mob/SecondaryStatsPoints.h | 16 +- object/Mesh.h | 6 +- pathfinding/Metric2d.h | 1 - pathfinding/Metric3d.h | 2 +- pathfinding/Path.h | 23 ++ pathfinding/jps/Jps.h | 43 +++ pathfinding/jps/JpsGrid.h | 30 ++ pathfinding/jps/JpsNode.h | 23 ++ platform/SystemInfo.h | 5 +- platform/linux/Allocation.h | 61 ---- platform/linux/Allocator.h | 132 +++++++++ platform/linux/Library.h | 4 +- .../linux/{SystemInfo.h => SystemInfo.cpp} | 1 - platform/linux/Thread.h | 14 - .../{ThreadDefines.h => threading/Atomic.h} | 12 +- platform/linux/threading/Semaphore.h | 15 + platform/linux/threading/Spinlock.h | 27 ++ platform/linux/threading/Thread.h | 21 ++ platform/linux/threading/ThreadDefines.h | 19 ++ platform/win32/Allocation.h | 56 ---- platform/win32/Allocator.h | 92 ++++++ platform/win32/FastPipes.h | 49 ++++ platform/win32/Server.h | 1 - platform/win32/SystemInfo.cpp | 8 +- platform/win32/Thread.h | 271 ------------------ platform/win32/UtilsWin32.h | 46 +-- platform/win32/audio/XAudio2.h | 1 - platform/win32/input/HidInput.h | 2 +- platform/win32/input/RawInput.h | 7 +- platform/win32/input/XInput.h | 1 - .../{ThreadDefines.h => threading/Atomic.h} | 23 +- platform/win32/threading/Semaphore.h | 37 +++ platform/win32/threading/Spinlock.h | 26 ++ platform/win32/threading/Thread.h | 253 ++++++++++++++++ platform/win32/threading/ThreadDefines.h | 30 ++ stdlib/HashMap.h | 4 +- thread/Thread.h | 8 +- thread/ThreadJob.h | 4 +- thread/ThreadPool.h | 4 +- ui/UITheme.h | 24 +- utils/FastPipes.h | 51 ---- utils/MathUtils.h | 8 +- utils/StringUtils.h | 90 +++--- utils/SystemUtils.h | 15 - utils/Utils.h | 1 - 60 files changed, 1413 insertions(+), 710 deletions(-) create mode 100644 memory/Heap.h create mode 100644 memory/ThreadedQueue.h create mode 100644 pathfinding/Path.h create mode 100644 pathfinding/jps/Jps.h create mode 100644 pathfinding/jps/JpsGrid.h create mode 100644 pathfinding/jps/JpsNode.h delete mode 100644 platform/linux/Allocation.h create mode 100644 platform/linux/Allocator.h rename platform/linux/{SystemInfo.h => SystemInfo.cpp} (99%) delete mode 100644 platform/linux/Thread.h rename platform/linux/{ThreadDefines.h => threading/Atomic.h} (80%) create mode 100644 platform/linux/threading/Semaphore.h create mode 100644 platform/linux/threading/Spinlock.h create mode 100644 platform/linux/threading/Thread.h create mode 100644 platform/linux/threading/ThreadDefines.h delete mode 100644 platform/win32/Allocation.h create mode 100644 platform/win32/Allocator.h create mode 100644 platform/win32/FastPipes.h delete mode 100644 platform/win32/Thread.h rename platform/win32/{ThreadDefines.h => threading/Atomic.h} (62%) create mode 100644 platform/win32/threading/Semaphore.h create mode 100644 platform/win32/threading/Spinlock.h create mode 100644 platform/win32/threading/Thread.h create mode 100644 platform/win32/threading/ThreadDefines.h delete mode 100644 utils/FastPipes.h delete mode 100644 utils/SystemUtils.h diff --git a/asset/Asset.h b/asset/Asset.h index 0147ccc..5118f7c 100644 --- a/asset/Asset.h +++ b/asset/Asset.h @@ -10,8 +10,6 @@ #define TOS_ASSET_H #include "../stdlib/Types.h" -#include "../object/Vertex.h" -#include "../stdlib/HashMap.h" #include "AssetType.h" #define MAX_ASSET_NAME_LENGTH 32 diff --git a/audio/Audio.h b/audio/Audio.h index 38a4f6c..8c30f9e 100644 --- a/audio/Audio.h +++ b/audio/Audio.h @@ -10,16 +10,6 @@ #define TOS_AUDIO_H #include "../stdlib/Types.h" -#include "../utils/StringUtils.h" -#include "../memory/RingMemory.h" - -#if _WIN32 - #include "../platform/win32/UtilsWin32.h" -#else - #include "../platform/linux/UtilsLinux.h" -#endif - -#include "Audio.h" struct Audio { // bits per sample diff --git a/compression/Huffman.h b/compression/Huffman.h index a686597..6cfd080 100644 --- a/compression/Huffman.h +++ b/compression/Huffman.h @@ -15,7 +15,6 @@ #include "../stdlib/Types.h" #include "../utils/BitUtils.h" #include "../utils/EndianUtils.h" -#include "../utils/Utils.h" struct HuffmanNode { HuffmanNode* left; @@ -152,7 +151,7 @@ void huffman_dump(const Huffman* hf, byte* out) void huffman_load(Huffman* hf, const byte* in) { - // load the char -> code relations and convert relative indeces to pointers + // load the char -> code relations and convert relative indices to pointers for (int32 i = 0; i < ARRAY_COUNT(hf->code); ++i) { int64 value = SWAP_ENDIAN_LITTLE(*((int64 *) in)); in += sizeof(value); diff --git a/input/ControllerInput.h b/input/ControllerInput.h index ecc4fb4..8963120 100644 --- a/input/ControllerInput.h +++ b/input/ControllerInput.h @@ -51,6 +51,8 @@ enum ControllerButton { }; struct ControllerInput { + // @todo should probably include controller_id for xinput and LPDIRECTINPUTDEVICE8 for directinput + int8 button[MAX_CONTROLLER_KEYS]; bool is_analog[MAX_CONTROLLER_KEYS]; // = uses deadzone diff --git a/log/Debug.cpp b/log/Debug.cpp index af4f191..8670e0d 100644 --- a/log/Debug.cpp +++ b/log/Debug.cpp @@ -7,6 +7,8 @@ #include "Log.h" #include "TimingStat.h" #include "../utils/StringUtils.h" +#include "../utils/TestUtils.h" +#include "../utils/MathUtils.h" global_persist DebugContainer* debug_container = NULL; @@ -21,7 +23,7 @@ global_persist DebugContainer* debug_container = NULL; QueryPerformanceFrequency(&perf_counter); debug_container->performance_count_frequency = perf_counter.QuadPart; } -#else +#elif __linux__ void setup_performance_count() { if (!debug_container) { return; diff --git a/log/Debug.h b/log/Debug.h index 99cf579..dc42402 100644 --- a/log/Debug.h +++ b/log/Debug.h @@ -11,9 +11,12 @@ #include "../stdlib/Types.h" #include "DebugMemory.h" -#include "Log.h" #include "TimingStat.h" +#if _WIN32 + #include +#endif + struct LogMemory { byte* memory; diff --git a/log/Log.h b/log/Log.h index cf55316..d0a997f 100644 --- a/log/Log.h +++ b/log/Log.h @@ -10,17 +10,9 @@ #define TOS_LOG_H #include -#include - #include "../stdlib/Types.h" -#include "../utils/TestUtils.h" -#include "../utils/MathUtils.h" #include "Debug.h" -#ifdef _WIN32 - #include -#endif - #ifndef LOG_LEVEL #define LOG_LEVEL 0 #endif diff --git a/log/TimingStat.h b/log/TimingStat.h index 5b086b5..10d1686 100644 --- a/log/TimingStat.h +++ b/log/TimingStat.h @@ -10,7 +10,6 @@ #define TOS_LOG_TIMING_STAT_H #include -#include #include "../stdlib/Types.h" #include "Debug.h" diff --git a/memory/BufferMemory.h b/memory/BufferMemory.h index 9e94712..23d763f 100644 --- a/memory/BufferMemory.h +++ b/memory/BufferMemory.h @@ -17,12 +17,12 @@ #include "../log/DebugMemory.h" #if _WIN32 - #include "../platform/win32/Allocation.h" + #include "../platform/win32/Allocator.h" #elif __linux__ - #include "../platform/linux/Allocation.h" + #include "../platform/linux/Allocator.h" #endif -// @question Consider to use element_alignment to automatically align/pad elmeents +// @question Consider to use element_alignment to automatically align/pad elements struct BufferMemory { byte* memory; @@ -59,9 +59,9 @@ void buffer_free(BufferMemory* buf) { DEBUG_MEMORY_DELETE((uint64) buf->memory, buf->size); if (buf->alignment < 2) { - platform_free((void **) &buf->memory, buf->size); + platform_free((void **) &buf->memory); } else { - platform_aligned_free((void **) &buf->memory, buf->size); + platform_aligned_free((void **) &buf->memory); } } @@ -86,7 +86,7 @@ void buffer_init(BufferMemory* buf, byte* data, uint64 size, int32 alignment = 6 inline void buffer_reset(BufferMemory* buf) { - // @bug arent we wasting element 0 (see get_memory, we are not using 0 only next element) + // @bug aren't we wasting element 0 (see get_memory, we are not using 0 only next element) DEBUG_MEMORY_DELETE((uint64) buf->memory, buf->head - buf->memory); buf->head = buf->memory; } diff --git a/memory/ChunkMemory.h b/memory/ChunkMemory.h index 1ad3a26..a8a85d1 100644 --- a/memory/ChunkMemory.h +++ b/memory/ChunkMemory.h @@ -18,9 +18,9 @@ #include "BufferMemory.h" #if _WIN32 - #include "../platform/win32/Allocation.h" + #include "../platform/win32/Allocator.h" #elif __linux__ - #include "../platform/linux/Allocation.h" + #include "../platform/linux/Allocator.h" #endif struct ChunkMemory { @@ -66,9 +66,9 @@ void chunk_free(ChunkMemory* buf) { DEBUG_MEMORY_DELETE((uint64) buf->memory, buf->size); if (buf->alignment < 2) { - platform_free((void **) &buf->memory, buf->size); + platform_free((void **) &buf->memory); } else { - platform_aligned_free((void **) &buf->memory, buf->size); + platform_aligned_free((void **) &buf->memory); } } diff --git a/memory/Heap.h b/memory/Heap.h new file mode 100644 index 0000000..0d27541 --- /dev/null +++ b/memory/Heap.h @@ -0,0 +1,154 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_MEMORY_HEAP_H +#define TOS_MEMORY_HEAP_H + +#include +#include +#include "../stdlib/Types.h" +#include "../log/DebugMemory.h" +#include "BufferMemory.h" + +#if _WIN32 + #include "../platform/win32/Allocator.h" +#elif __linux__ + #include "../platform/linux/Allocator.h" +#endif + +struct Heap { + byte* elements; + byte* helper_mem; + uint32 element_size; + uint64 capacity; + uint64 size; + int32 (*compare) (const void*, const void*); +}; + +void heap_alloc(Heap* heap, uint32 element_size, uint64 capacity, int32 (*compare)(const void*, const void*)) { + ASSERT_SIMPLE(element_size * capacity); + + heap->elements = (byte *) platform_alloc(element_size * capacity + element_size); + if (!heap->elements) { + return; + } + + heap->element_size = element_size; + heap->capacity = capacity; + heap->size = 0; + heap->compare = compare; + heap->helper_mem = heap->elements + element_size; + + DEBUG_MEMORY_INIT((uint64) heap->elements, element_size * capacity); +} + +void heap_free(Heap* heap) +{ + DEBUG_MEMORY_DELETE((uint64) heap->elements, heap->element_size * heap->capacity); + platform_free((void **) &heap->elements); +} + +void heap_init(Heap* heap, BufferMemory* buf, uint32 element_size, uint64 capacity, int32 (*compare)(const void*, const void*)) { + ASSERT_SIMPLE(element_size * capacity); + + heap->elements = buffer_get_memory(buf, element_size * capacity, 8, true); + if (!heap->elements) { + return; + } + + heap->element_size = element_size; + heap->capacity = capacity; + heap->size = 0; + heap->compare = compare; + + DEBUG_MEMORY_INIT((uint64) heap->elements, element_size * capacity); +} + +void heapify_down(Heap* heap, uint64 index) { + uint64 left_child = 2 * index + 1; + uint64 right_child = left_child + 1; + uint64 largest = index; + + void* largest_element = heap->elements + (largest * heap->element_size); + if (left_child < heap->size) { + void* left = heap->elements + (left_child * heap->element_size); + if (heap->compare(left, largest_element) > 0) { + largest = left_child; + } + } + + if (right_child < heap->size) { + void* right = heap->elements + (right_child * heap->element_size); + void* current_largest = heap->elements + (largest * heap->element_size); + if (heap->compare(right, current_largest) > 0) { + largest = right_child; + } + } + + if (largest != index) { + heap_swap( + heap->elements + (index * heap->element_size), + heap->elements + (largest * heap->element_size), + heap->element_size, heap->helper_mem + ); + + heapify_down(heap, largest); + } +} + +void heapify_up(Heap* heap, uint64 index) { + if (index == 0) { + return; // Root node + } + + uint64 parent_index = (index - 1) / 2; + void* current = heap->elements + (index * heap->element_size); + void* parent = heap->elements + (parent_index * heap->element_size); + + if (heap->compare(current, parent) > 0) { + heap_swap(current, parent, heap->element_size, heap->helper_mem); + heapify_up(heap, parent_index); + } +} + +void heap_push(Heap* heap, const void* element) { + if (heap->size >= heap->capacity) { + return; + } + + void* target = heap->elements + (heap->size * heap->element_size); + memcpy(target, element, heap->element_size); + heapify_up(heap, heap->size); + ++heap->size; +} + +void heap_pop(Heap* heap, void* out) { + if (heap->size == 0) { + return; + } + + memcpy(out, heap->elements, heap->element_size); + void* last_element = heap->elements + ((heap->size - 1) * heap->element_size); + memcpy(heap->elements, last_element, heap->element_size); + --heap->size; + heapify_down(heap, 0); +} + +inline +void* heap_peek(Heap* heap) { + return heap->elements; +} + +inline +void heap_swap(void* a, void* b, uint32 size, void* helper_mem) { + memcpy(helper_mem, a, size); + memcpy(a, b, size); + memcpy(b, helper_mem, size); +} + +#endif \ No newline at end of file diff --git a/memory/Queue.h b/memory/Queue.h index b09926d..6329f59 100644 --- a/memory/Queue.h +++ b/memory/Queue.h @@ -9,110 +9,73 @@ #ifndef TOS_MEMORY_QUEUE_H #define TOS_MEMORY_QUEUE_H +#include "../stdlib/Types.h" #include "RingMemory.h" typedef RingMemory Queue; inline -void queue_alloc(Queue* ring, uint64 size, int32 alignment = 64) +void queue_alloc(Queue* queue, uint64 size, uint32 element_size, int32 alignment = 64) { - ring_alloc(ring, size, alignment); - - pthread_mutex_init(&ring->mutex, NULL); - pthread_cond_init(&ring->cond, NULL); + ring_alloc(queue, size, alignment); } inline -void queue_init(Queue* ring, BufferMemory* buf, uint64 size, int32 alignment = 64) +void queue_init(Queue* queue, BufferMemory* buf, uint64 size, uint32 element_size, int32 alignment = 64) { - ring_init(ring, buf, size, alignment); - - pthread_mutex_init(&ring->mutex, NULL); - pthread_cond_init(&ring->cond, NULL); + ring_init(queue, buf, size, alignment); } inline -void queue_free(Queue* buf) +void queue_init(Queue* queue, byte* buf, uint64 size, uint32 element_size, int32 alignment = 64) { - ring_free(buf); + ring_init(queue, buf, size, alignment); } inline -void queue_init(Queue* ring, byte* buf, uint64 size, int32 alignment = 64) +void queue_free(Queue* queue) { - ring_init(ring, buf, size, alignment); + ring_free(queue); } +// Conditional Lock inline -void ring_enqueue(Queue* ring, byte* data, uint64 size) +void queue_enqueue(Queue* queue, byte* data, uint64 size, byte aligned = 0) { - pthread_mutex_lock(&ring->mutex); - - while (!ring_commit_safe(ring, size)) { - pthread_cond_wait(&ring->cond, &ring->mutex); - } - - byte* mem = ring_get_memory(ring, size); + byte* mem = ring_get_memory_nomove(queue, size, aligned); memcpy(mem, data, size); - - pthread_cond_signal(&ring->cond); - pthread_mutex_unlock(&ring->mutex); + ring_move_pointer(queue, &queue->head, size, aligned); } inline -byte* ring_enqueue_start(Queue* ring, uint64 size, byte aligned = 0) +byte* queue_enqueue_start(Queue* queue, uint64 size, byte aligned = 0) { - pthread_mutex_lock(&ring->mutex); - - while (!ring_commit_safe(ring, size, aligned)) { - pthread_cond_wait(&ring->cond, &ring->mutex); - } - - return ring_get_memory(ring, size, aligned); + return ring_get_memory_nomove(queue, size, aligned); } inline -void ring_enqueue_end(Queue* ring) +void queue_enqueue_end(Queue* queue, uint64 size, byte aligned = 0) { - pthread_cond_signal(&ring->cond); - pthread_mutex_unlock(&ring->mutex); + ring_move_pointer(queue, &queue->head, size, aligned); } inline -byte* ring_dequeue(Queue* ring, byte* data, uint64 size, byte aligned = 0) +byte* queue_dequeue(Queue* queue, byte* data, uint64 size, byte aligned = 0) { - pthread_mutex_lock(&ring->mutex); - - while (ring->head == ring->tail) { - pthread_cond_wait(&ring->cond, &ring->mutex); - } - - memcpy(data, ring->tail, size); - ring_move_pointer(ring, &ring->tail, size, aligned); - - pthread_cond_signal(&ring->cond); - pthread_mutex_unlock(&ring->mutex); + memcpy(data, queue->tail, size); + ring_move_pointer(queue, &queue->tail, size, aligned); } inline -byte* ring_dequeue_start(Queue* ring) +byte* queue_dequeue_start(Queue* queue) { - pthread_mutex_lock(&ring->mutex); - - while (ring->head == ring->tail) { - pthread_cond_wait(&ring->cond, &ring->mutex); - } - - return ring->tail; + return queue->tail; } inline -void ring_dequeue_end(Queue* ring, uint64 size, byte aligned = 0) +void queue_dequeue_end(Queue* queue, uint64 size, byte aligned = 0) { - ring_move_pointer(ring, &ring->tail, size, aligned); - - pthread_cond_signal(&ring->cond); - pthread_mutex_unlock(&ring->mutex); + ring_move_pointer(queue, &queue->tail, size, aligned); } #endif \ No newline at end of file diff --git a/memory/RingMemory.h b/memory/RingMemory.h index 2d95d31..95d049d 100644 --- a/memory/RingMemory.h +++ b/memory/RingMemory.h @@ -21,11 +21,13 @@ #include "../log/DebugMemory.h" #if _WIN32 - #include "../platform/win32/Allocation.h" - #include "../platform/win32/Thread.h" + #include "../platform/win32/Allocator.h" + #include "../platform/win32/threading/ThreadDefines.h" + #include "../platform/win32/threading/Semaphore.h" #elif __linux__ - #include "../platform/linux/Allocation.h" - #include "../platform/linux/Thread.h" + #include "../platform/linux/Allocator.h" + #include "../platform/linux/threading/ThreadDefines.h" + #include "../platform/linux/threading/Semaphore.h" #endif struct RingMemory { @@ -34,7 +36,7 @@ struct RingMemory { byte* head; - // This variable is usually only used by single read/write code mostly found in threads. + // This variable is usually only used by single producer/consumer code mostly found in threads. // One thread inserts elements -> updates head // The other thread reads elements -> updates tail // This code itself doesn't change this variable @@ -44,8 +46,13 @@ struct RingMemory { int32 alignment; int32 element_alignment; + // We support both conditional locking and semaphore locking + // These values are not initialized and not used unless you use the queue pthread_mutex_t mutex; pthread_cond_t cond; + + sem_t empty; + sem_t full; }; // @bug alignment should also include the end point, not just the start @@ -114,9 +121,9 @@ inline void ring_free(RingMemory* buf) { if (buf->alignment < 2) { - platform_free((void **) &buf->memory, buf->size); + platform_free((void **) &buf->memory); } else { - platform_aligned_free((void **) &buf->memory, buf->size); + platform_aligned_free((void **) &buf->memory); } } @@ -218,6 +225,41 @@ byte* ring_get_memory(RingMemory* ring, uint64 size, byte aligned = 0, bool zero return offset; } +// Same as ring_get_memory but DOESN'T move the head +byte* ring_get_memory_nomove(RingMemory* ring, uint64 size, byte aligned = 0, bool zeroed = false) +{ + ASSERT_SIMPLE(size <= ring->size); + + if (aligned == 0) { + aligned = (byte) OMS_MAX(ring->element_alignment, 1); + } + + byte* pos = ring->head; + + if (aligned > 1) { + uintptr_t address = (uintptr_t) pos; + pos += (aligned - (address& (aligned - 1))) % aligned; + } + + size = ROUND_TO_NEAREST(size, aligned); + if (pos + size > ring->end) { + ring_reset(ring); + + if (aligned > 1) { + uintptr_t address = (uintptr_t) pos; + pos += (aligned - (address & (aligned - 1))) % aligned; + } + } + + if (zeroed) { + memset((void *) pos, 0, size); + } + + DEBUG_MEMORY_WRITE((uint64) pos, size); + + return pos; +} + // Used if the ring only contains elements of a certain size // This way you can get a certain element inline diff --git a/memory/ThreadedQueue.h b/memory/ThreadedQueue.h new file mode 100644 index 0000000..3fedb6c --- /dev/null +++ b/memory/ThreadedQueue.h @@ -0,0 +1,204 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_MEMORY_QUEUE_H +#define TOS_MEMORY_QUEUE_H + +#include "RingMemory.h" + +#if _WIN32 + #include "../platform/win32/threading/Thread.h" + #include "../platform/win32/threading/Semaphore.h" +#elif __linux__ + #include "../platform/linux/threading/Thread.h" + #include "../platform/linux/threading/Semaphore.h" +#endif + +typedef RingMemory ThreadedQueue; + +inline +void threaded_queue_alloc(ThreadedQueue* queue, uint64 size, uint32 element_count, int32 alignment = 64) +{ + ring_alloc(queue, size, alignment); + + pthread_mutex_init(&queue->mutex, NULL); + pthread_cond_init(&queue->cond, NULL); + + sem_init(&queue->empty, element_count); + sem_init(&queue->full, 0); +} + +inline +void threaded_queue_init(ThreadedQueue* queue, BufferMemory* buf, uint64 size, uint32 element_count, int32 alignment = 64) +{ + ring_init(queue, buf, size, alignment); + + pthread_mutex_init(&queue->mutex, NULL); + pthread_cond_init(&queue->cond, NULL); + + sem_init(&queue->empty, element_count); + sem_init(&queue->full, 0); +} + +inline +void threaded_queue_init(ThreadedQueue* queue, byte* buf, uint64 size, uint32 element_count, int32 alignment = 64) +{ + ring_init(queue, buf, size, alignment); + + pthread_mutex_init(&queue->mutex, NULL); + pthread_cond_init(&queue->cond, NULL); + + sem_init(&queue->empty, element_count); + sem_init(&queue->full, 0); +} + +inline +void threaded_queue_free(ThreadedQueue* queue) +{ + ring_free(queue); + sem_destroy(&queue->empty); + sem_destroy(&queue->full); + pthread_mutex_destroy(&queue->mutex); + pthread_cond_destroy(&queue->cond); +} + +// Conditional Lock +inline +void threaded_queue_enqueue(ThreadedQueue* queue, byte* data, uint64 size, byte aligned = 0) +{ + pthread_mutex_lock(&queue->mutex); + + while (!ring_commit_safe(queue, size)) { + pthread_cond_wait(&queue->cond, &queue->mutex); + } + + byte* mem = ring_get_memory(queue, size, aligned); + memcpy(mem, data, size); + + pthread_cond_signal(&queue->cond); + pthread_mutex_unlock(&queue->mutex); +} + +inline +byte* threaded_queue_enqueue_start(ThreadedQueue* queue, uint64 size, byte aligned = 0) +{ + pthread_mutex_lock(&queue->mutex); + + while (!ring_commit_safe(queue, size, aligned)) { + pthread_cond_wait(&queue->cond, &queue->mutex); + } + + return ring_get_memory(queue, size, aligned); +} + +inline +void threaded_queue_enqueue_end(ThreadedQueue* queue) +{ + pthread_cond_signal(&queue->cond); + pthread_mutex_unlock(&queue->mutex); +} + +inline +byte* threaded_queue_dequeue(ThreadedQueue* queue, byte* data, uint64 size, byte aligned = 0) +{ + pthread_mutex_lock(&queue->mutex); + + while (queue->head == queue->tail) { + pthread_cond_wait(&queue->cond, &queue->mutex); + } + + memcpy(data, queue->tail, size); + ring_move_pointer(queue, &queue->tail, size, aligned); + + pthread_cond_signal(&queue->cond); + pthread_mutex_unlock(&queue->mutex); +} + +inline +byte* threaded_queue_dequeue_start(ThreadedQueue* queue) +{ + pthread_mutex_lock(&queue->mutex); + + while (queue->head == queue->tail) { + pthread_cond_wait(&queue->cond, &queue->mutex); + } + + return queue->tail; +} + +inline +void threaded_queue_dequeue_end(ThreadedQueue* queue, uint64 size, byte aligned = 0) +{ + ring_move_pointer(queue, &queue->tail, size, aligned); + + pthread_cond_signal(&queue->cond); + pthread_mutex_unlock(&queue->mutex); +} + +// Semaphore Lock +inline +void threaded_queue_enqueue_sem(ThreadedQueue* queue, byte* data, uint64 size, byte aligned = 0) +{ + sem_wait(&queue->empty); + pthread_mutex_lock(&queue->mutex); + + byte* mem = ring_get_memory(queue, size, aligned); + memcpy(mem, data, size); + + pthread_mutex_unlock(&queue->mutex); + sem_post(&queue->full); +} + +inline +byte* threaded_queue_enqueue_start_sem(ThreadedQueue* queue, uint64 size, byte aligned = 0) +{ + sem_wait(&queue->empty); + pthread_mutex_lock(&queue->mutex); + + return ring_get_memory(queue, size, aligned); +} + +inline +void threaded_queue_enqueue_end_sem(ThreadedQueue* queue) +{ + pthread_mutex_unlock(&queue->mutex); + sem_post(&queue->full); +} + +inline +byte* threaded_queue_dequeue_sem(ThreadedQueue* queue, byte* data, uint64 size, byte aligned = 0) +{ + sem_wait(&queue->full); + pthread_mutex_lock(&queue->mutex); + + memcpy(data, queue->tail, size); + ring_move_pointer(queue, &queue->tail, size, aligned); + + pthread_mutex_unlock(&queue->mutex); + sem_post(&queue->empty); +} + +inline +byte* threaded_queue_dequeue_start_sem(ThreadedQueue* queue) +{ + sem_wait(&queue->full); + pthread_mutex_lock(&queue->mutex); + + return queue->tail; +} + +inline +void threaded_queue_dequeue_end_sem(ThreadedQueue* queue, uint64 size, byte aligned = 0) +{ + ring_move_pointer(queue, &queue->tail, size, aligned); + + pthread_mutex_unlock(&queue->mutex); + sem_post(&queue->empty); +} + +#endif \ No newline at end of file diff --git a/models/mob/PrimaryStatsPoints.h b/models/mob/PrimaryStatsPoints.h index f4371f1..bf2187d 100644 --- a/models/mob/PrimaryStatsPoints.h +++ b/models/mob/PrimaryStatsPoints.h @@ -17,7 +17,7 @@ static const int PRIMARY_STAT_INDICES[] = {0, 1, 2, 3, 4, 5, 6, 7}; // Character stats modifiable through leveling (simple +/- buttons) struct PrimaryStatsPoints { uint16 stat_str; // strength : effects health + base damage - uint16 stat_int; // inteligence : effects resource + base demage + uint16 stat_int; // intelligence : effects resource + base damage uint16 stat_acc; // accuracy : effects critical chance + base damage + miss chance uint16 stat_agi; // agility : effects resource + base damage + dodge chance // @todo not implemented in database diff --git a/models/mob/SecondaryStatsPoints.h b/models/mob/SecondaryStatsPoints.h index 29c22cf..46e2e68 100644 --- a/models/mob/SecondaryStatsPoints.h +++ b/models/mob/SecondaryStatsPoints.h @@ -29,7 +29,7 @@ static const int SECONDARY_STAT_INDICES[] = { * @todo optimize order of struct members to ensure optimal struct size */ -// Character stats modifiable thorugh skill tree? +// Character stats modifiable through skill tree? struct SecondaryStatsPoints { /* @todo @@ -45,15 +45,12 @@ struct SecondaryStatsPoints { // This allows us to create skills with multiple additive damage types AND composite damage that has multiple types at the same time uint16 dmg[MOB_STATS_TYPE_SIZE]; - uint16 dmg_reflection; - uint16 dmg_reflection_chance; - // @question is this a damage number or is this a % number of the total damage? uint16 dmg_crit; uint16 dmg_crit_chance; // @question is this similar to the different damage categories, is this a % of the total damage or should this just be a flag - uint16 dmg_pircing; + uint16 dmg_piercing; // Health & Resource uint16 health; @@ -85,6 +82,9 @@ struct SecondaryStatsPoints { uint16 block_chance; uint16 block_amount; + uint16 dmg_reflection; + uint16 dmg_reflection_chance; + uint16 dodge_chance; uint16 cc_protection; uint16 miss_chance; @@ -162,7 +162,7 @@ struct SecondaryStatsPoints2 { byte dmg_crit_chance; // @question is this similar to the different damage categories, is this a % of the total damage or should this just be a flag - byte dmg_pircing; + byte dmg_piercing; // Health & Resource byte health; @@ -257,7 +257,7 @@ struct SecondaryStatsRelPoints2 { byte dmg_crit; byte dmg_crit_chance; - byte dmg_pircing; + byte dmg_piercing; // Health & Resource byte health; @@ -281,7 +281,7 @@ struct SecondaryStatsRelPoints2 { byte resource_loss_on_dmg_taken; // Defense types - // think about it as armor and/or resistence if it helps + // think about it as armor and/or resistance if it helps byte defense[MOB_STATS_TYPE_SIZE]; // Accuracy diff --git a/object/Mesh.h b/object/Mesh.h index 44d48ae..fcafffd 100644 --- a/object/Mesh.h +++ b/object/Mesh.h @@ -109,7 +109,7 @@ void mesh_from_file_txt( uint32 temp_color_count = 0; while (*pos != '\0') { - char_skip_empty(&pos); + str_skip_empty(&pos); if (*pos == '\0') { break; @@ -152,11 +152,11 @@ void mesh_from_file_txt( state = 15; } else { // not supported or comment - char_move_to(&pos, '\n'); + str_move_to(&pos, '\n'); } // move past keyword - char_skip_non_empty(&pos); + str_skip_non_empty(&pos); // move past whitespaces and newline bool is_next_line = false; diff --git a/pathfinding/Metric2d.h b/pathfinding/Metric2d.h index 6aeed72..255cd9d 100644 --- a/pathfinding/Metric2d.h +++ b/pathfinding/Metric2d.h @@ -15,7 +15,6 @@ #include "../stdlib/Types.h" #include "../utils/MathUtils.h" -#include "../memory/RingMemory.h" f32 manhattan_2d(v2_f32 a, v2_f32 b) { return fabs(a.x - b.x) + fabs(a.y - b.y); diff --git a/pathfinding/Metric3d.h b/pathfinding/Metric3d.h index 854cd3f..2c384f6 100644 --- a/pathfinding/Metric3d.h +++ b/pathfinding/Metric3d.h @@ -12,9 +12,9 @@ #include #include +#include #include "../stdlib/Types.h" -#include "../memory/RingMemory.h" // Manhattan distance for 3D f32 manhattan_3d(v3_f32 a, v3_f32 b) { diff --git a/pathfinding/Path.h b/pathfinding/Path.h new file mode 100644 index 0000000..86d6fe3 --- /dev/null +++ b/pathfinding/Path.h @@ -0,0 +1,23 @@ +/** + * Jingga + * + * @package Utils + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_PATHFINDING_PATH_H +#define TOS_PATHFINDING_PATH_H + +#include +#include + +#include "../stdlib/Types.h" +#include "../utils/MathUtils.h" + +struct Path { + +}; + +#endif \ No newline at end of file diff --git a/pathfinding/jps/Jps.h b/pathfinding/jps/Jps.h new file mode 100644 index 0000000..8d13db2 --- /dev/null +++ b/pathfinding/jps/Jps.h @@ -0,0 +1,43 @@ +/** + * Jingga + * + * @package Utils + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_PATHFINDING_JPS_H +#define TOS_PATHFINDING_JPS_H + +#include +#include + +#include "../../stdlib/Types.h" +#include "../../utils/MathUtils.h" + +#include "JpsGrid.h" +#include "../Path.h" + +void jps_find_path( + v3_int32 start, v3_int32 end, + const JpsGrid* grid, Path* path, + int32 heuristic, int32 movement +) { + JpsNode* start_node = &grid->nodes[ + grid->dimension.x * grid->dimension.y * start.z + + grid->dimension.x * start.y + + start.x + ]; + + JpsNode* end_node = &grid->nodes[ + grid->dimension.x * grid->dimension.y * end.z + + grid->dimension.x * end.y + + end.x + ]; + + if (!start_node->is_walkable || !end_node->is_walkable) { + return; + } +} +#endif \ No newline at end of file diff --git a/pathfinding/jps/JpsGrid.h b/pathfinding/jps/JpsGrid.h new file mode 100644 index 0000000..47480e5 --- /dev/null +++ b/pathfinding/jps/JpsGrid.h @@ -0,0 +1,30 @@ +/** + * Jingga + * + * @package Utils + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_PATHFINDING_JPS_GRID_H +#define TOS_PATHFINDING_JPS_GRID_H + +#include +#include + +#include "../../stdlib/Types.h" +#include "../../utils/MathUtils.h" + +#include "JpsNode.h" + +struct JpsGrid { + // 1. left to right + // 2. then front to back + // 3. then height + JpsNode* nodes; + + v3_int32 dimension; +}; + +#endif \ No newline at end of file diff --git a/pathfinding/jps/JpsNode.h b/pathfinding/jps/JpsNode.h new file mode 100644 index 0000000..c9a9964 --- /dev/null +++ b/pathfinding/jps/JpsNode.h @@ -0,0 +1,23 @@ +/** + * Jingga + * + * @package Utils + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_PATHFINDING_JPS_NODE_H +#define TOS_PATHFINDING_JPS_NODE_H + +#include +#include + +#include "../../stdlib/Types.h" +#include "../../utils/MathUtils.h" + +struct JpsNode { + bool is_walkable; +}; + +#endif \ No newline at end of file diff --git a/platform/SystemInfo.h b/platform/SystemInfo.h index 939726d..9b84fc1 100644 --- a/platform/SystemInfo.h +++ b/platform/SystemInfo.h @@ -33,7 +33,7 @@ struct NetworkInfo { }; struct SIMDInfo { - f32 sse; + int32 sse; int32 avx256; int32 avx512; int32 sve; @@ -89,8 +89,11 @@ struct SystemInfo { GpuInfo gpu[2]; int32 gpu_count; + DisplayInfo display_primary; DisplayInfo display[6]; int32 display_count; + + int32 language; }; #endif \ No newline at end of file diff --git a/platform/linux/Allocation.h b/platform/linux/Allocation.h deleted file mode 100644 index 4ce2f50..0000000 --- a/platform/linux/Allocation.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Jingga - * - * @copyright Jingga - * @license OMS License 2.0 - * @version 1.0.0 - * @link https://jingga.app - */ -#ifndef TOS_PLATFORM_LINUX_ALLOCATION_H -#define TOS_PLATFORM_LINUX_ALLOCATION_H - -#include -#include - -inline -void aligned_free(void** ptr) { - free(*ptr); - *ptr = NULL; -} - -inline -void* platform_alloc(size_t size) -{ - ssize_t page_size = sysconf(_SC_PAGESIZE); - - size = (size + page_size - 1) & ~(page_size - 1); - - return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -} - -inline -void* platform_alloc_aligned(size_t size, int32 alignment) -{ - ssize_t page_size = sysconf(_SC_PAGESIZE); - if (alignment < page_size) { - alignment = page_size; - } - - size = (size + alignment - 1) & ~(alignment - 1); - - void* ptr = mmap(NULL, size + alignment + sizeof(void*), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - - void* aligned_ptr = (void*)(((uintptr_t)ptr + alignment + sizeof(void*) - 1) & ~(alignment - 1)); - ((void**) aligned_ptr)[-1] = ptr; - - return aligned_ptr; -} - -inline -void platform_free(void** ptr, size_t size) { - munmap(*ptr, size); - *ptr = NULL; -} - -inline -void platform_aligned_free(void** aligned_ptr, size_t size) { - void* ptr = ((void**) *aligned_ptr)[-1]; - munmap(ptr, size + ((uintptr_t) *aligned_ptr - (uintptr_t)ptr)); - *aligned_ptr = NULL; -} -#endif \ No newline at end of file diff --git a/platform/linux/Allocator.h b/platform/linux/Allocator.h new file mode 100644 index 0000000..48968f2 --- /dev/null +++ b/platform/linux/Allocator.h @@ -0,0 +1,132 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_PLATFORM_LINUX_ALLOCATOR_H +#define TOS_PLATFORM_LINUX_ALLOCATOR_H + +#include +#include +#include +#include +#include "../../stdlib/Types.h" +#include "../../utils/TestUtils.h" + +// @todo Currently alignment only effects the starting position, but it should also effect the ending/size +// @todo Consider to rename file to Allocator.h + +// @question Since we store at least the size of the memory in the beginning, +// does this have a negative impact on caching? +// Our Memory doesn't start at the cache line beginning but at least offset by sizeof(size_t) + +inline +void* platform_alloc(size_t size) +{ + ssize_t page_size = sysconf(_SC_PAGESIZE); + size = (size + sizeof(size_t) + page_size - 1) & ~(page_size - 1); + + void* ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + ASSERT_SIMPLE(ptr != MAP_FAILED); + + *((size_t *) ptr) = size; + + return (void *) ((uintptr_t) ptr + sizeof(size_t)); +} + +inline +void* platform_alloc_aligned(size_t size, int32 alignment) +{ + ssize_t page_size = sysconf(_SC_PAGESIZE); + if (alignment < page_size) { + alignment = page_size; + } + + size += alignment - 1 + sizeof(void *) + sizeof(size_t); + + void* ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + ASSERT_SIMPLE(ptr != MAP_FAILED); + + // We want an aligned memory area but mmap doesn't really support that. + // That's why we have to manually offset our memory area. + // However, when freeing the pointer later on we need the actual start of the memory area, not the manually offset one. + // We do the same with the size, which is required when freeing + uintptr_t raw_address = (uintptr_t) ptr + sizeof(void *) + sizeof(size_t); + void* aligned_ptr = (void *) ((raw_address + alignment - 1) & ~(alignment - 1)); + + *((void **) ((uintptr_t) aligned_ptr - sizeof(void *) - sizeof(size_t))) = ptr; + *((size_t *) ((uintptr_t) aligned_ptr - sizeof(size_t))) = size; + + return aligned_ptr; +} + +inline +void platform_free(void** ptr) { + void* actual_ptr = (void *) ((uintptr_t) *ptr - sizeof(size_t)); + munmap(actual_ptr, *((size_t *) actual_ptr)); + *ptr = NULL; +} + +inline +void platform_aligned_free(void** aligned_ptr) { + void* ptr = (void *) ((uintptr_t) *aligned_ptr - sizeof(void *) - sizeof(size_t)); + munmap(ptr, *((size_t *) ((uintptr_t) ptr + sizeof(void *)))); + *aligned_ptr = NULL; +} + +inline +void* platform_shared_alloc(int32* fd, const char* name, size_t size) +{ + *fd = shm_open(name, O_CREAT | O_RDWR, 0666); + ASSERT_SIMPLE(*fd != -1); + + ssize_t page_size = sysconf(_SC_PAGESIZE); + size = (size + sizeof(size_t) + page_size - 1) & ~(page_size - 1); + + ftruncate(*fd, size); + + void* shm_ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0); + ASSERT_SIMPLE(shm_ptr); + + *((size_t *) shm_ptr) = size; + + return (void *) ((uintptr_t) shm_ptr + sizeof(size_t)); +} + +inline +void* platform_shared_open(int32* fd, const char* name, size_t size) +{ + *fd = shm_open(name, O_RDWR, 0666); + ASSERT_SIMPLE(*fd != -1); + + ssize_t page_size = sysconf(_SC_PAGESIZE); + size = (size + sizeof(size_t) + page_size - 1) & ~(page_size - 1); + + void* shm_ptr = mmap(NULL, size, PROT_READ, MAP_SHARED, *fd, 0); + ASSERT_SIMPLE(shm_ptr); + + *((size_t *) shm_ptr) = size; + + return (void *) ((uintptr_t) shm_ptr + sizeof(size_t)); +} + +inline +void platform_shared_free(int32 fd, const char* name, void** ptr) +{ + munmap((void *) ((uintptr_t) *ptr - sizeof(size_t)), *((size_t *) ((uintptr_t) *ptr - sizeof(size_t)))); + *ptr = NULL; + + shm_unlink(name); + close(fd); +} + +inline +void platform_shared_close(int32 fd) +{ + close(fd); +} + +#endif \ No newline at end of file diff --git a/platform/linux/Library.h b/platform/linux/Library.h index a1f3c4c..a77fc68 100644 --- a/platform/linux/Library.h +++ b/platform/linux/Library.h @@ -62,7 +62,7 @@ bool library_load(Library* lib) } lib->is_valid = true; - for (int32_t c = 0; c < lib->function_count; ++c) { + for (int32 c = 0; c < lib->function_count; ++c) { void* function = dlsym(lib->handle, lib->function_names[c]); if (function) { lib->functions[c] = function; @@ -82,7 +82,7 @@ void library_unload(Library* lib) lib->handle = NULL; } - for (int32_t c = 0; c < lib->function_count; ++c) { + for (int32 c = 0; c < lib->function_count; ++c) { lib->functions[c] = NULL; } } diff --git a/platform/linux/SystemInfo.h b/platform/linux/SystemInfo.cpp similarity index 99% rename from platform/linux/SystemInfo.h rename to platform/linux/SystemInfo.cpp index 85197da..d4c78e2 100644 --- a/platform/linux/SystemInfo.h +++ b/platform/linux/SystemInfo.cpp @@ -13,7 +13,6 @@ #include #include "../../stdlib/Types.h" #include "../../stdlib/simd/SIMD_Helper.h" -#include "../../utils/StringUtils.h" #include "../SystemInfo.h" #include diff --git a/platform/linux/Thread.h b/platform/linux/Thread.h deleted file mode 100644 index 571e4a7..0000000 --- a/platform/linux/Thread.h +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Jingga - * - * @copyright Jingga - * @license OMS License 2.0 - * @version 1.0.0 - * @link https://jingga.app - */ -#ifndef TOS_PLATFORM_LINUX_THREAD_H -#define TOS_PLATFORM_LINUX_THREAD_H - -#include "ThreadDefines.h" - -#endif \ No newline at end of file diff --git a/platform/linux/ThreadDefines.h b/platform/linux/threading/Atomic.h similarity index 80% rename from platform/linux/ThreadDefines.h rename to platform/linux/threading/Atomic.h index 023d168..3eb79a5 100644 --- a/platform/linux/ThreadDefines.h +++ b/platform/linux/threading/Atomic.h @@ -6,17 +6,11 @@ * @version 1.0.0 * @link https://jingga.app */ -#ifndef TOS_PLATFORM_LINUX_THREAD_DEFINES_H -#define TOS_PLATFORM_LINUX_THREAD_DEFINES_H +#ifndef TOS_PLATFORM_LINUX_THREADING_ATOMIC_H +#define TOS_PLATFORM_LINUX_THREADING_ATOMIC_H #include -#include - -#include "../../stdlib/Types.h" - -typedef void* (*ThreadJobFunc)(void*); - -#define THREAD_RETURN void* +#include "../../../stdlib/Types.h" inline void atomic_set(volatile int32* value, int32 new_value) diff --git a/platform/linux/threading/Semaphore.h b/platform/linux/threading/Semaphore.h new file mode 100644 index 0000000..b0bf453 --- /dev/null +++ b/platform/linux/threading/Semaphore.h @@ -0,0 +1,15 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_PLATFORM_LINUX_THREADING_SEMAPHORE_H +#define TOS_PLATFORM_LINUX_THREADING_SEMAPHORE_H + +#include +#include + +#endif \ No newline at end of file diff --git a/platform/linux/threading/Spinlock.h b/platform/linux/threading/Spinlock.h new file mode 100644 index 0000000..09e91fc --- /dev/null +++ b/platform/linux/threading/Spinlock.h @@ -0,0 +1,27 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_PLATFORM_LINUX_THREADING_SPINLOCK_H +#define TOS_PLATFORM_LINUX_THREADING_SPINLOCK_H + +#include +#include "../../../stdlib/Types.h" + +typedef volatile int32 spinlock32; + +inline +void spinlock_start(spinlock32* lock) { + while (__atomic_exchange_n(lock, 1, __ATOMIC_ACQUIRE)) {} +} + +inline +void spinlock_end(spinlock32* lock) { + __atomic_store_n(lock, 0, __ATOMIC_RELEASE); +} + +#endif \ No newline at end of file diff --git a/platform/linux/threading/Thread.h b/platform/linux/threading/Thread.h new file mode 100644 index 0000000..a1201f2 --- /dev/null +++ b/platform/linux/threading/Thread.h @@ -0,0 +1,21 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_PLATFORM_LINUX_THREADING_THREAD_H +#define TOS_PLATFORM_LINUX_THREADING_THREAD_H + +#include +#include "../../../stdlib/Types.h" +#include "ThreadDefines.h" + +uint32 pcthread_get_num_procs() +{ + return (uint32) sysconf(_SC_NPROCESSORS_ONLN); +} + +#endif \ No newline at end of file diff --git a/platform/linux/threading/ThreadDefines.h b/platform/linux/threading/ThreadDefines.h new file mode 100644 index 0000000..9a92fa2 --- /dev/null +++ b/platform/linux/threading/ThreadDefines.h @@ -0,0 +1,19 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_PLATFORM_LINUX_THREADING_THREAD_DEFINES_H +#define TOS_PLATFORM_LINUX_THREADING_THREAD_DEFINES_H + +#include +#include + +typedef void* (*ThreadJobFunc)(void*); + +#define THREAD_RETURN void* + +#endif \ No newline at end of file diff --git a/platform/win32/Allocation.h b/platform/win32/Allocation.h deleted file mode 100644 index 5bbe70f..0000000 --- a/platform/win32/Allocation.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Jingga - * - * @copyright Jingga - * @license OMS License 2.0 - * @version 1.0.0 - * @link https://jingga.app - */ -#ifndef TOS_PLATFORM_WIN32_ALLOCATION_H -#define TOS_PLATFORM_WIN32_ALLOCATION_H - -#include -#include -#include "../../stdlib/Types.h" - -inline -void* aligned_alloc(size_t alignment, size_t size) { - return _aligned_malloc(size, alignment); -} - -inline -void aligned_free(void** ptr) { - _aligned_free(*ptr); - *ptr = NULL; -} - -inline -void* platform_alloc(size_t size) -{ - return VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); -} - -inline -void* platform_alloc_aligned(size_t size, int32 alignment) -{ - void* ptr = VirtualAlloc(NULL, size + alignment + sizeof(void*), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - - void* aligned_ptr = (void*)(((uintptr_t)ptr + alignment + sizeof(void*) - 1) & ~(alignment - 1)); - ((void**) aligned_ptr)[-1] = ptr; - - return aligned_ptr; -} - -inline -void platform_free(void** ptr, size_t) { - VirtualFree(*ptr, 0, MEM_RELEASE); - *ptr = NULL; -} - -inline -void platform_aligned_free(void** aligned_ptr, size_t) { - void* ptr = ((void**) *aligned_ptr)[-1]; - VirtualFree(ptr, 0, MEM_RELEASE); - *aligned_ptr = NULL; -} -#endif \ No newline at end of file diff --git a/platform/win32/Allocator.h b/platform/win32/Allocator.h new file mode 100644 index 0000000..7309f90 --- /dev/null +++ b/platform/win32/Allocator.h @@ -0,0 +1,92 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_PLATFORM_WIN32_ALLOCATOR_H +#define TOS_PLATFORM_WIN32_ALLOCATOR_H + +#include +#include +#include "../../stdlib/Types.h" +#include "../../utils/TestUtils.h" + +// @todo Currently alignment only effects the starting position, but it should also effect the ending/size +// @todo Consider to rename file to Allocator.h + +inline +void* platform_alloc(size_t size) +{ + return VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); +} + +inline +void* platform_alloc_aligned(size_t size, int32 alignment) +{ + void* ptr = VirtualAlloc(NULL, size + alignment + sizeof(void*), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + ASSERT_SIMPLE(ptr); + + // We want an aligned memory area but mmap doesn't really support that. + // That's why we have to manually offset our memory area. + // However, when freeing the pointer later on we need the actual start of the memory area, not the manually offset one. + void* aligned_ptr = (void *) (((uintptr_t) ptr + alignment + sizeof(void*) - 1) & ~(alignment - 1)); + ((void**) aligned_ptr)[-1] = ptr; + + return aligned_ptr; +} + +inline +void platform_free(void** ptr) { + VirtualFree(*ptr, 0, MEM_RELEASE); + *ptr = NULL; +} + +inline +void platform_aligned_free(void** aligned_ptr) { + void* ptr = ((void**) *aligned_ptr)[-1]; + VirtualFree(ptr, 0, MEM_RELEASE); + *aligned_ptr = NULL; +} + +inline +void* platform_shared_alloc(HANDLE* fd, const char* name, size_t size) +{ + *fd = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD) size, name); + ASSERT_SIMPLE(*fd); + + void* shm_ptr = MapViewOfFile(*fd, FILE_MAP_ALL_ACCESS, 0, 0, size); + ASSERT_SIMPLE(shm_ptr); + + return shm_ptr; +} + +inline +void* platform_shared_open(HANDLE* fd, const char* name, size_t size) +{ + *fd = OpenFileMappingA(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, name); + ASSERT_SIMPLE(*fd); + + void* shm_ptr = MapViewOfFile(*fd, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, (DWORD) size); + ASSERT_SIMPLE(shm_ptr); + + return shm_ptr; +} + +inline +void platform_shared_free(HANDLE fd, const char*, void** ptr) +{ + UnmapViewOfFile(*ptr); + CloseHandle(fd); + *ptr = NULL; +} + +inline +void platform_shared_close(HANDLE fd) +{ + CloseHandle(fd); +} + +#endif \ No newline at end of file diff --git a/platform/win32/FastPipes.h b/platform/win32/FastPipes.h new file mode 100644 index 0000000..8ff1f43 --- /dev/null +++ b/platform/win32/FastPipes.h @@ -0,0 +1,49 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_UTILS_FAST_PIPES_H +#define TOS_UTILS_FAST_PIPES_H + +#include "../stdlib/Types.h" + +#pragma comment(lib, "kernel32.lib") +#pragma comment(lib, "user32.lib") + +#include +#include +#include +#include + +static int ENABLE_FAST_PIPES() +{ + int32 result = 0; + + wchar_t pipe_name[32]; + wsprintfW(pipe_name, L"\\\\.\\pipe\\fastpipe%x", GetCurrentProcessId()); + HANDLE fast_pip = CreateFileW(pipe_name, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); + + if(fast_pip != INVALID_HANDLE_VALUE) { + SetStdHandle(STD_OUTPUT_HANDLE, fast_pip); + SetStdHandle(STD_INPUT_HANDLE, fast_pip); + + int32 std_out = _open_osfhandle((intptr_t) fast_pip, O_WRONLY | O_TEXT); + int32 std_in = _open_osfhandle((intptr_t) fast_pip, O_RDONLY | O_TEXT); + + _dup2(std_out, _fileno(stdout)); + _dup2(std_in, _fileno(stdin)); + + _close(std_out); + _close(std_in); + + result = 1; + } + + return result; +} + +#endif \ No newline at end of file diff --git a/platform/win32/Server.h b/platform/win32/Server.h index 9ad4e1a..7ca5c76 100644 --- a/platform/win32/Server.h +++ b/platform/win32/Server.h @@ -16,7 +16,6 @@ #include #include -#include "../../stdlib/Types.h" #include "../../network/SocketConnection.h" #include "../../utils/EndianUtils.h" diff --git a/platform/win32/SystemInfo.cpp b/platform/win32/SystemInfo.cpp index 438f393..5f46011 100644 --- a/platform/win32/SystemInfo.cpp +++ b/platform/win32/SystemInfo.cpp @@ -13,7 +13,6 @@ #include #include "../../stdlib/Types.h" #include "../../stdlib/simd/SIMD_Helper.h" -#include "../../utils/StringUtils.h" #include "../SystemInfo.h" #include @@ -312,8 +311,7 @@ int network_info_get(NetworkInfo* info) { } void cpu_info_get(CpuInfo* info) { - int32 temp; - info->simd.sse = (temp = max_sse_supported()) > 9 ? temp / 10.0f : temp; + info->simd.sse = max_sse_supported(); info->simd.avx256 = max_avx256_supported(); info->simd.avx512 = max_avx512_supported(); info->simd.sve = max_sve_supported(); @@ -553,7 +551,7 @@ void system_info_render(char* buf, const SystemInfo* info) { info->cpu.cache[1].size, info->cpu.cache[1].line_size, info->cpu.cache[2].size, info->cpu.cache[2].line_size, info->cpu.cache[3].size, info->cpu.cache[3].line_size, - info->cpu.simd.sse, info->cpu.simd.avx256, info->cpu.simd.avx512 > 0 ? avx512[info->cpu.simd.avx512 - 1] : "0", info->cpu.simd.sve, info->cpu.simd.neon, (int32) info->cpu.simd.abm, + info->cpu.simd.sse > 9 ? (f32) info->cpu.simd.sse / 10.0f : (f32) info->cpu.simd.sse, info->cpu.simd.avx256, info->cpu.simd.avx512 > 0 ? avx512[info->cpu.simd.avx512 - 1] : "0", info->cpu.simd.sve, info->cpu.simd.neon, (int32) info->cpu.simd.abm, info->gpu[0].name, info->gpu[0].vram, info->gpu_count < 2 ? "" : info->gpu[1].name, info->gpu_count < 2 ? 0 : info->gpu[1].vram, info->display[0].name, info->display[0].width, info->display[0].height, info->display[0].hz, @@ -575,6 +573,8 @@ void system_info_get(SystemInfo* info) ram_info_get(&info->ram); info->gpu_count = gpu_info_get(info->gpu); info->display_count = display_info_get(info->display); + display_info_get_primary(&info->display_primary); + info->language = system_language_code(); } #endif \ No newline at end of file diff --git a/platform/win32/Thread.h b/platform/win32/Thread.h deleted file mode 100644 index cfaa262..0000000 --- a/platform/win32/Thread.h +++ /dev/null @@ -1,271 +0,0 @@ -/** - * Jingga - * - * @copyright Jingga - * @license OMS License 2.0 - * @version 1.0.0 - * @link https://jingga.app - */ -#ifndef TOS_PLATFORM_WIN32_THREAD_H -#define TOS_PLATFORM_WIN32_THREAD_H - -#include - -#include "../stdlib/Types.h" -#include "ThreadDefines.h" - -#include - -void ms_to_timespec(timespec *ts, uint32 ms) -{ - if (ts == 0) { - return; - } - - // @todo replace time() with os specifc solution - ts->tv_sec = (ms / 1000) + time(0); - ts->tv_nsec = (ms % 1000) * 1000000; -} - -#ifdef _WIN32 - int32 pthread_create(pthread_t* thread, void*, ThreadJobFunc start_routine, void* arg) - { - if (thread == NULL || start_routine == NULL) { - return 1; - } - - *thread = CreateThread(NULL, 0, start_routine, arg, 0, NULL); - if (*thread == NULL) { - return 1; - } - - return 0; - } - - int32 pthread_join(pthread_t thread, void**) - { - WaitForSingleObject(thread, INFINITE); - CloseHandle(thread); - - return 0; - } - - int32 pthread_detach(pthread_t thread) - { - CloseHandle(thread); - - return 0; - } - - int32 pthread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t*) - { - if (mutex == NULL) { - return 1; - } - - InitializeCriticalSection(mutex); - - return 0; - } - - int32 pthread_mutex_destroy(pthread_mutex_t* mutex) - { - if (mutex == NULL) { - return 1; - } - - DeleteCriticalSection(mutex); - - return 0; - } - - int32 pthread_mutex_lock(pthread_mutex_t* mutex) - { - if (mutex == NULL) { - return 1; - } - - EnterCriticalSection(mutex); - - return 0; - } - - int32 pthread_mutex_unlock(pthread_mutex_t* mutex) - { - if (mutex == NULL) { - return 1; - } - - LeaveCriticalSection(mutex); - - return 0; - } - - int32 pthread_cond_init(pthread_cond_t* cond, pthread_condattr_t*) - { - if (cond == NULL) { - return 1; - } - - InitializeConditionVariable(cond); - - return 0; - } - - int32 pthread_cond_destroy(pthread_cond_t*) - { - /* Windows does not have a destroy for conditionals */ - return 0; - } - - static DWORD timespec_to_ms(const timespec* abstime) - { - if (abstime == NULL) { - return INFINITE; - } - - DWORD t = (DWORD) (((abstime->tv_sec - time(0)) * 1000) + (abstime->tv_nsec / 1000000)); - - return t < 0 ? 1 : t; - } - - int32 pthread_cond_timedwait(pthread_cond_t* cond, pthread_mutex_t* mutex, const timespec* abstime) - { - if (cond == NULL || mutex == NULL) { - return 1; - } - - if (!SleepConditionVariableCS(cond, mutex, timespec_to_ms(abstime))) { - return 1; - } - - return 0; - } - - int32 pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex) - { - if (cond == NULL || mutex == NULL) { - return 1; - } - - return pthread_cond_timedwait(cond, mutex, NULL); - } - - int32 pthread_cond_signal(pthread_cond_t* cond) - { - if (cond == NULL) { - return 1; - } - - WakeConditionVariable(cond); - - return 0; - } - - int32 pthread_cond_broadcast(pthread_cond_t* cond) - { - if (cond == NULL) { - return 1; - } - - WakeAllConditionVariable(cond); - - return 0; - } - - int32 pthread_rwlock_init(pthread_rwlock_t* rwlock, const pthread_rwlockattr_t*) - { - if (rwlock == NULL) { - return 1; - } - - InitializeSRWLock(&rwlock->lock); - rwlock->exclusive = false; - - return 0; - } - - int32 pthread_rwlock_destroy(pthread_rwlock_t*) - { - return 0; - } - - int32 pthread_rwlock_rdlock(pthread_rwlock_t* rwlock) - { - if (rwlock == NULL) { - return 1; - } - - AcquireSRWLockShared(&rwlock->lock); - - return 0; - } - - int32 pthread_rwlock_tryrdlock(pthread_rwlock_t* rwlock) - { - if (rwlock == NULL) { - return 1; - } - - return !TryAcquireSRWLockShared(&rwlock->lock); - } - - int32 pthread_rwlock_wrlock(pthread_rwlock_t* rwlock) - { - if (rwlock == NULL) { - return 1; - } - - AcquireSRWLockExclusive(&rwlock->lock); - rwlock->exclusive = true; - - return 0; - } - - int32 pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock) - { - if (rwlock == NULL) { - return 1; - } - - BOOLEAN ret = TryAcquireSRWLockExclusive(&rwlock->lock); - if (ret) { - rwlock->exclusive = true; - } - - return ret; - } - - int32 pthread_rwlock_unlock(pthread_rwlock_t* rwlock) - { - if (rwlock == NULL) { - return 1; - } - - if (rwlock->exclusive) { - rwlock->exclusive = false; - ReleaseSRWLockExclusive(&rwlock->lock); - } else { - ReleaseSRWLockShared(&rwlock->lock); - } - - return 0; - } - - uint32 pcthread_get_num_procs() - { - SYSTEM_INFO sysinfo; - GetSystemInfo(&sysinfo); - - return sysinfo.dwNumberOfProcessors; - } - - #define pthread_exit(a) {return (a);} -#else - uint32 pcthread_get_num_procs() - { - return (uint32) sysconf(_SC_NPROCESSORS_ONLN); - } -#endif - -#endif \ No newline at end of file diff --git a/platform/win32/UtilsWin32.h b/platform/win32/UtilsWin32.h index 5ebf283..47c39db 100644 --- a/platform/win32/UtilsWin32.h +++ b/platform/win32/UtilsWin32.h @@ -12,6 +12,7 @@ #include #include #include +#include #ifdef _MSC_VER #include @@ -21,6 +22,7 @@ #include "../../utils/Utils.h" #include "../../utils/TestUtils.h" #include "../../memory/RingMemory.h" +#include "../../log/Debug.cpp" #define strtok_r strtok_s @@ -60,9 +62,36 @@ time_t system_time() return ((time_t) (largeInt.QuadPart / 10000000ULL)) - ((time_t) 11644473600ULL); } +// doesn't return clock time, only to return time since program start +// -> can be used for profiling +inline +uint64 time_mu() +{ + LARGE_INTEGER counter; + QueryPerformanceCounter(&counter); + + return (counter.QuadPart * 1000000) / debug_container->performance_count_frequency; +} + +inline +time_t unix_epoch_s() +{ + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + + ULARGE_INTEGER li; + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + + time_t seconds_since_epoch = (li.QuadPart - 116444736000000000ULL) / 10000000ULL; + + return seconds_since_epoch; +} + // @todo Consider to implement directly mapped files (CreateFileMapping) for certain files (e.g. map data or texture data, ...) -inline void relative_to_absolute(const char* rel, char* path) +inline +void relative_to_absolute(const char* rel, char* path) { char self_path[MAX_PATH]; int32 self_path_length = GetModuleFileNameA(NULL, self_path, MAX_PATH); @@ -130,21 +159,6 @@ file_size(const char* path) return size.QuadPart; } -inline -uint64 time_mu() -{ - LARGE_INTEGER frequency; - LARGE_INTEGER counter; - - if (!QueryPerformanceFrequency(&frequency)) { - return 0; - } - - QueryPerformanceCounter(&counter); - - return (counter.QuadPart * 1000000) / frequency.QuadPart; -} - inline bool file_exists(const char* path) { diff --git a/platform/win32/audio/XAudio2.h b/platform/win32/audio/XAudio2.h index 0efb0c4..92cf2f5 100644 --- a/platform/win32/audio/XAudio2.h +++ b/platform/win32/audio/XAudio2.h @@ -15,7 +15,6 @@ #include "../../../stdlib/Types.h" #include "../../../audio/AudioSetting.h" -#include "../../../utils/MathUtils.h" #include "../../../log/Log.h" #include "../../../audio/Audio.cpp" diff --git a/platform/win32/input/HidInput.h b/platform/win32/input/HidInput.h index b29a1dd..5729d9a 100644 --- a/platform/win32/input/HidInput.h +++ b/platform/win32/input/HidInput.h @@ -23,7 +23,7 @@ #pragma comment(lib, "hid.lib") #pragma comment(lib, "setupapi.lib") -void hid_init_contorllers(Input* __restrict states, int32 state_count, RingMemory* ring) { +void hid_init_controllers(Input* __restrict states, int32 state_count, RingMemory* ring) { HANDLE* controller_handles = NULL; diff --git a/platform/win32/input/RawInput.h b/platform/win32/input/RawInput.h index 8ad575f..e0b35c9 100644 --- a/platform/win32/input/RawInput.h +++ b/platform/win32/input/RawInput.h @@ -17,10 +17,7 @@ #include "../../../input/ControllerInput.h" #include "controller/DualShock4.h" #include "../../../utils/TestUtils.h" -#include "../../../utils/MathUtils.h" #include "../../../memory/RingMemory.h" -#include "../../../memory/BufferMemory.h" -#include "../../../stdlib/simd/SIMD_I8.h" #include #define INPUT_MOUSE_BUTTON_1 1 @@ -32,7 +29,7 @@ #define INPUT_MOUSE_BUTTON_HWHEEL 7 // IMPORTANT: -// Even if it is nowhere documented (at least not to our knowledge) the GetRawInputDeviceInfoA, GetRawInputBuffer functions requried +// Even if it is nowhere documented (at least not to our knowledge) the GetRawInputDeviceInfoA, GetRawInputBuffer functions required // aligned memory. So far we only figured out that 4 bytes works, maybe this needs to be 8 in the future?! int rawinput_init_mousekeyboard(HWND hwnd, Input* __restrict states, RingMemory* ring) @@ -110,7 +107,7 @@ int rawinput_init_mousekeyboard(HWND hwnd, Input* __restrict states, RingMemory* return i; } -// WARNING: While this works we highly recommend to use hid_init_contorllers +// WARNING: While this works we highly recommend to use hid_init_controllers int rawinput_init_controllers(HWND hwnd, Input* __restrict states, RingMemory* ring) { uint32 device_count; diff --git a/platform/win32/input/XInput.h b/platform/win32/input/XInput.h index cf36247..0fb449a 100644 --- a/platform/win32/input/XInput.h +++ b/platform/win32/input/XInput.h @@ -12,7 +12,6 @@ #include #include -#include "../../../input/Input.h" #include "../../../input/ControllerInput.h" #include "../../../stdlib/Types.h" #include "../../../utils/MathUtils.h" diff --git a/platform/win32/ThreadDefines.h b/platform/win32/threading/Atomic.h similarity index 62% rename from platform/win32/ThreadDefines.h rename to platform/win32/threading/Atomic.h index 0ab7270..6b2b2b7 100644 --- a/platform/win32/ThreadDefines.h +++ b/platform/win32/threading/Atomic.h @@ -6,28 +6,11 @@ * @version 1.0.0 * @link https://jingga.app */ -#ifndef TOS_PLATFORM_WIN32_THREAD_DEFINES_H -#define TOS_PLATFORM_WIN32_THREAD_DEFINES_H +#ifndef TOS_PLATFORM_WIN32_THREADING_ATOMIC_H +#define TOS_PLATFORM_WIN32_THREADING_ATOMIC_H -#include #include - -#include "../../stdlib/Types.h" - -typedef DWORD (WINAPI *ThreadJobFunc)(void*); -typedef CRITICAL_SECTION pthread_mutex_t; -typedef void pthread_mutexattr_t; -typedef void pthread_condattr_t; -typedef void pthread_rwlockattr_t; -typedef HANDLE pthread_t; -typedef CONDITION_VARIABLE pthread_cond_t; - -struct pthread_rwlock_t { - SRWLOCK lock; - bool exclusive; -}; - -#define THREAD_RETURN DWORD WINAPI +#include "../../../stdlib/Types.h" inline void atomic_set(volatile int32* value, int32 new_value) diff --git a/platform/win32/threading/Semaphore.h b/platform/win32/threading/Semaphore.h new file mode 100644 index 0000000..5544be9 --- /dev/null +++ b/platform/win32/threading/Semaphore.h @@ -0,0 +1,37 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_PLATFORM_WIN32_THREADING_SEMAPHORE_H +#define TOS_PLATFORM_WIN32_THREADING_SEMAPHORE_H + +#include +#include "../../../stdlib/Types.h" + +typedef HANDLE sem_t; + +void sem_init(sem_t* semaphore, int32 value) +{ + *semaphore = CreateSemaphore(NULL, value, MAX_INT32, NULL); +} + +void sem_destroy(sem_t* semaphore) +{ + CloseHandle(*semaphore); +} + +// decrement if != 0, if = 0 wait +void sem_wait(sem_t* semaphore) { + WaitForSingleObject(*semaphore, INFINITE); +} + +// increment +void sem_post(sem_t* semaphore) { + ReleaseSemaphore(*semaphore, 1, NULL); +} + +#endif \ No newline at end of file diff --git a/platform/win32/threading/Spinlock.h b/platform/win32/threading/Spinlock.h new file mode 100644 index 0000000..24f79a7 --- /dev/null +++ b/platform/win32/threading/Spinlock.h @@ -0,0 +1,26 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_PLATFORM_WIN32_THREADING_SPINLOCK_H +#define TOS_PLATFORM_WIN32_THREADING_SPINLOCK_H + +#include + +typedef volatile long spinlock32; + +inline +void spinlock_start(spinlock32* lock) { + while (InterlockedExchange(lock, 1) == 1) {} +} + +inline +void spinlock_end(spinlock32* lock) { + InterlockedExchange(lock, 0); +} + +#endif \ No newline at end of file diff --git a/platform/win32/threading/Thread.h b/platform/win32/threading/Thread.h new file mode 100644 index 0000000..f1f35ad --- /dev/null +++ b/platform/win32/threading/Thread.h @@ -0,0 +1,253 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_PLATFORM_WIN32_THREADING_THREAD_H +#define TOS_PLATFORM_WIN32_THREADING_THREAD_H + +#include "../../../stdlib/Types.h" +#include "../UtilsWin32.h" +#include "ThreadDefines.h" + +#include + +int32 pthread_create(pthread_t* thread, void*, ThreadJobFunc start_routine, void* arg) +{ + if (thread == NULL || start_routine == NULL) { + return 1; + } + + *thread = CreateThread(NULL, 0, start_routine, arg, 0, NULL); + if (*thread == NULL) { + return 1; + } + + return 0; +} + +int32 pthread_join(pthread_t thread, void**) +{ + WaitForSingleObject(thread, INFINITE); + CloseHandle(thread); + + return 0; +} + +int32 pthread_detach(pthread_t thread) +{ + CloseHandle(thread); + + return 0; +} + +int32 pthread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t*) +{ + if (mutex == NULL) { + return 1; + } + + InitializeCriticalSection(mutex); + + return 0; +} + +int32 pthread_mutex_destroy(pthread_mutex_t* mutex) +{ + if (mutex == NULL) { + return 1; + } + + DeleteCriticalSection(mutex); + + return 0; +} + +int32 pthread_mutex_lock(pthread_mutex_t* mutex) +{ + if (mutex == NULL) { + return 1; + } + + EnterCriticalSection(mutex); + + return 0; +} + +int32 pthread_mutex_unlock(pthread_mutex_t* mutex) +{ + if (mutex == NULL) { + return 1; + } + + LeaveCriticalSection(mutex); + + return 0; +} + +int32 pthread_cond_init(pthread_cond_t* cond, pthread_condattr_t*) +{ + if (cond == NULL) { + return 1; + } + + InitializeConditionVariable(cond); + + return 0; +} + +int32 pthread_cond_destroy(pthread_cond_t*) +{ + /* Windows does not have a destroy for conditionals */ + return 0; +} + +static DWORD timespec_to_ms(const timespec* abstime) +{ + if (abstime == NULL) { + return INFINITE; + } + + time_t seconds_since_epoch = unix_epoch_s(); + DWORD t = (DWORD) (((abstime->tv_sec - seconds_since_epoch) * 1000) + (abstime->tv_nsec / 1000000)); + + return t < 0 ? 1 : t; +} + +int32 pthread_cond_timedwait(pthread_cond_t* cond, pthread_mutex_t* mutex, const timespec* abstime) +{ + if (cond == NULL || mutex == NULL) { + return 1; + } + + if (!SleepConditionVariableCS(cond, mutex, timespec_to_ms(abstime))) { + return 1; + } + + return 0; +} + +int32 pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex) +{ + if (cond == NULL || mutex == NULL) { + return 1; + } + + return pthread_cond_timedwait(cond, mutex, NULL); +} + +int32 pthread_cond_signal(pthread_cond_t* cond) +{ + if (cond == NULL) { + return 1; + } + + WakeConditionVariable(cond); + + return 0; +} + +int32 pthread_cond_broadcast(pthread_cond_t* cond) +{ + if (cond == NULL) { + return 1; + } + + WakeAllConditionVariable(cond); + + return 0; +} + +int32 pthread_rwlock_init(pthread_rwlock_t* rwlock, const pthread_rwlockattr_t*) +{ + if (rwlock == NULL) { + return 1; + } + + InitializeSRWLock(&rwlock->lock); + rwlock->exclusive = false; + + return 0; +} + +int32 pthread_rwlock_destroy(pthread_rwlock_t*) +{ + return 0; +} + +int32 pthread_rwlock_rdlock(pthread_rwlock_t* rwlock) +{ + if (rwlock == NULL) { + return 1; + } + + AcquireSRWLockShared(&rwlock->lock); + + return 0; +} + +int32 pthread_rwlock_tryrdlock(pthread_rwlock_t* rwlock) +{ + if (rwlock == NULL) { + return 1; + } + + return !TryAcquireSRWLockShared(&rwlock->lock); +} + +int32 pthread_rwlock_wrlock(pthread_rwlock_t* rwlock) +{ + if (rwlock == NULL) { + return 1; + } + + AcquireSRWLockExclusive(&rwlock->lock); + rwlock->exclusive = true; + + return 0; +} + +int32 pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock) +{ + if (rwlock == NULL) { + return 1; + } + + BOOLEAN ret = TryAcquireSRWLockExclusive(&rwlock->lock); + if (ret) { + rwlock->exclusive = true; + } + + return ret; +} + +int32 pthread_rwlock_unlock(pthread_rwlock_t* rwlock) +{ + if (rwlock == NULL) { + return 1; + } + + if (rwlock->exclusive) { + rwlock->exclusive = false; + ReleaseSRWLockExclusive(&rwlock->lock); + } else { + ReleaseSRWLockShared(&rwlock->lock); + } + + return 0; +} + +uint32 pcthread_get_num_procs() +{ + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + + return sysinfo.dwNumberOfProcessors; +} + +#define pthread_exit(a) {return (a);} + +#endif \ No newline at end of file diff --git a/platform/win32/threading/ThreadDefines.h b/platform/win32/threading/ThreadDefines.h new file mode 100644 index 0000000..ddc0b70 --- /dev/null +++ b/platform/win32/threading/ThreadDefines.h @@ -0,0 +1,30 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_PLATFORM_WIN32_THREADING_THREAD_DEFINES_H +#define TOS_PLATFORM_WIN32_THREADING_THREAD_DEFINES_H + +#include +#include + +typedef DWORD (WINAPI *ThreadJobFunc)(void*); +typedef CRITICAL_SECTION pthread_mutex_t; +typedef void pthread_mutexattr_t; +typedef void pthread_condattr_t; +typedef void pthread_rwlockattr_t; +typedef HANDLE pthread_t; +typedef CONDITION_VARIABLE pthread_cond_t; + +struct pthread_rwlock_t { + SRWLOCK lock; + bool exclusive; +}; + +#define THREAD_RETURN DWORD WINAPI + +#endif \ No newline at end of file diff --git a/stdlib/HashMap.h b/stdlib/HashMap.h index 15a2e3c..e6c1de3 100644 --- a/stdlib/HashMap.h +++ b/stdlib/HashMap.h @@ -9,11 +9,11 @@ #ifndef TOS_STDLIB_HASHMAP_H #define TOS_STDLIB_HASHMAP_H +#include "Types.h" #include "../hash/GeneralHash.h" #include "../memory/RingMemory.h" #include "../memory/BufferMemory.h" #include "../memory/ChunkMemory.h" -#include "Types.h" #include "../utils/StringUtils.h" #define MAX_KEY_LENGTH 32 @@ -406,7 +406,7 @@ int64 hashmap_dump(const HashMap* hm, byte* data) *((uint64 *) data) = SWAP_ENDIAN_LITTLE(hm->buf.count); data += sizeof(uint64); - // Dump the table content where the elements are relative indeces/pointers + // Dump the table content where the elements are relative indices/pointers for (int32 i = 0; i < hm->buf.count; ++i) { *((uint64 *) data) = hm->table[i] ? SWAP_ENDIAN_LITTLE((uintptr_t) hm->table[i] - (uintptr_t) hm->buf.memory) diff --git a/thread/Thread.h b/thread/Thread.h index 7e4ea69..79253c5 100644 --- a/thread/Thread.h +++ b/thread/Thread.h @@ -15,11 +15,11 @@ #include "../stdlib/Types.h" #if _WIN32 - #include "../platform/win32/ThreadDefines.h" - #include "../platform/win32/Thread.h" + #include "../platform/win32/threading/Thread.h" + #include "../platform/win32/threading/Atomic.h" #elif __linux__ - #include "../platform/linux/ThreadDefines.h" - #include "../platform/linux/Thread.h" + #include "../platform/linux/threading/Thread.h" + #include "../platform/linux/threading/Atomic.h" #endif #include "ThreadJob.h" diff --git a/thread/ThreadJob.h b/thread/ThreadJob.h index bce5949..7b8c7f2 100644 --- a/thread/ThreadJob.h +++ b/thread/ThreadJob.h @@ -15,9 +15,9 @@ #include "../stdlib/Types.h" #if _WIN32 - #include "../platform/win32/ThreadDefines.h" + #include "../platform/win32/threading/ThreadDefines.h" #elif __linux__ - #include "../platform/linux/ThreadDefines.h" + #include "../platform/linux/threading/ThreadDefines.h" #endif struct PoolWorker { diff --git a/thread/ThreadPool.h b/thread/ThreadPool.h index 90c15dd..5468284 100644 --- a/thread/ThreadPool.h +++ b/thread/ThreadPool.h @@ -15,9 +15,9 @@ #include "../stdlib/Types.h" #ifdef _WIN32 - #include "../platform/win32/Thread.h" + #include "../platform/win32/threading/Thread.h" #elif __linux__ - #include "../platform/linux/Thread.h" + #include "../platform/linux/threading/Thread.h" #endif #include "ThreadJob.h" diff --git a/ui/UITheme.h b/ui/UITheme.h index f80fc72..2e5b949 100644 --- a/ui/UITheme.h +++ b/ui/UITheme.h @@ -105,7 +105,7 @@ int compare_by_attribute_id(const void* a, const void* b) { // attributes ... // attributes ... -// WARNING: theme needs to have memory already reserved and asigned to data +// WARNING: theme needs to have memory already reserved and assigned to data void theme_from_file_txt( UIThemeStyle* theme, byte* data @@ -127,7 +127,7 @@ void theme_from_file_txt( int32 temp_group_count = 0; while (*pos != '\0') { // Skip all white spaces - char_skip_empty(&pos); + str_skip_empty(&pos); // Is group name if (*pos == '#' || *pos == '.') { @@ -135,7 +135,7 @@ void theme_from_file_txt( } // Go to the end of the line - char_move_to(&pos, '\n'); + str_move_to(&pos, '\n'); // Go to next line if (*pos != '\0') { @@ -154,7 +154,7 @@ void theme_from_file_txt( pos += 8; // move past version while (*pos != '\0') { - char_skip_empty(&pos); + str_skip_empty(&pos); if (*pos == '\n') { ++pos; @@ -173,7 +173,7 @@ void theme_from_file_txt( last_token_newline = false; if (!block_open) { - char_copy_move_until(&pos, block_name, " \n", sizeof(" \n") - 1); + str_copy_move_until(&pos, block_name, " \n", sizeof(" \n") - 1); // All blocks need to start with #. In the past this wasn't the case and may not be in the future. This is why we keep this if here. if (*block_name == '#' || *block_name == '.') { @@ -198,10 +198,10 @@ void theme_from_file_txt( continue; } - char_copy_move_until(&pos, attribute_name, " :\n", sizeof(" :\n") - 1); + str_copy_move_until(&pos, attribute_name, " :\n", sizeof(" :\n") - 1); // Skip any white spaces or other delimeters - char_skip_list(&pos, " \t:", sizeof(" \t:") - 1); + str_skip_list(&pos, " \t:", sizeof(" \t:") - 1); ASSERT_SIMPLE((*pos != '\0' && *pos != '\n')); @@ -211,7 +211,7 @@ void theme_from_file_txt( attribute.attribute_id = UI_ATTRIBUTE_TYPE_TYPE; char str[32]; - char_copy_move_until(&pos, str, '\n'); + str_copy_move_until(&pos, str, '\n'); for (int32 j = 0; j < UI_ELEMENT_TYPE_SIZE; ++j) { if (strcmp(str, ui_element_type_to_string_const((UIElementType) j)) == 0) { @@ -225,7 +225,7 @@ void theme_from_file_txt( } else if (strcmp(ui_attribute_type_to_string_const(UI_ATTRIBUTE_TYPE_STYLE), attribute_name) == 0) { attribute.attribute_id = UI_ATTRIBUTE_TYPE_STYLE; - char_copy_move_until(&pos, attribute.value_str, '\n'); + str_copy_move_until(&pos, attribute.value_str, '\n'); } else if (strcmp(ui_attribute_type_to_string_const(UI_ATTRIBUTE_TYPE_FONT_COLOR), attribute_name) == 0) { ++pos; // Skip '#' @@ -257,7 +257,7 @@ void theme_from_file_txt( } else if (strcmp(ui_attribute_type_to_string_const(UI_ATTRIBUTE_TYPE_BACKGROUND_IMG), attribute_name) == 0) { attribute.attribute_id = UI_ATTRIBUTE_TYPE_BACKGROUND_IMG; - char_copy_move_until(&pos, attribute.value_str, '\n'); + str_copy_move_until(&pos, attribute.value_str, '\n'); } else if (strcmp(ui_attribute_type_to_string_const(UI_ATTRIBUTE_TYPE_BACKGROUND_IMG_OPACITY), attribute_name) == 0) { attribute.attribute_id = UI_ATTRIBUTE_TYPE_BACKGROUND_IMG_OPACITY; attribute.value_float = SWAP_ENDIAN_LITTLE(strtof(pos, &pos)); @@ -354,7 +354,7 @@ void theme_from_file_txt( attribute.attribute_id = UI_ATTRIBUTE_TYPE_TRANSITION_DURATION; attribute.value_float = strtof(pos, &pos); } else { - char_move_to(&pos, '\n'); + str_move_to(&pos, '\n'); continue; } @@ -372,7 +372,7 @@ void theme_from_file_txt( ++temp_group->attribute_size; } - char_move_to(&pos, '\n'); + str_move_to(&pos, '\n'); } // We still need to sort the last group diff --git a/utils/FastPipes.h b/utils/FastPipes.h deleted file mode 100644 index 9d571d3..0000000 --- a/utils/FastPipes.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Jingga - * - * @copyright Jingga - * @license OMS License 2.0 - * @version 1.0.0 - * @link https://jingga.app - */ -#ifndef TOS_UTILS_FAST_PIPES_H -#define TOS_UTILS_FAST_PIPES_H - -// requires kernel32.lib and user32.lib -#include "../stdlib/Types.h" - -#if _WIN32 - #include - #include - #include - #include - - static int ENABLE_FAST_PIPES() - { - int32 result = 0; - - wchar_t pipe_name[32]; - wsprintfW(pipe_name, L"\\\\.\\pipe\\fastpipe%x", GetCurrentProcessId()); - HANDLE fast_pip = CreateFileW(pipe_name, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); - - if(fast_pip != INVALID_HANDLE_VALUE) { - SetStdHandle(STD_OUTPUT_HANDLE, fast_pip); - SetStdHandle(STD_INPUT_HANDLE, fast_pip); - - int32 std_out = _open_osfhandle((intptr_t) fast_pip, O_WRONLY | O_TEXT); - int32 std_in = _open_osfhandle((intptr_t) fast_pip, O_RDONLY | O_TEXT); - - _dup2(std_out, _fileno(stdout)); - _dup2(std_in, _fileno(stdin)); - - _close(std_out); - _close(std_in); - - result = 1; - } - - return result; - } -#else - #define ENABLE_FAST_PIPES(...) 0 -#endif - -#endif \ No newline at end of file diff --git a/utils/MathUtils.h b/utils/MathUtils.h index 3aa9b34..ab4bfa3 100644 --- a/utils/MathUtils.h +++ b/utils/MathUtils.h @@ -12,12 +12,6 @@ #include -#if ARM - #include "../stdlib/IntrinsicsArm.h" -#else - #include "../stdlib/Intrinsics.h" -#endif - #define OMS_PI 3.14159265358979323846f #define OMS_PI_OVER_TWO (OMS_PI / 2.0f) #define OMS_PI_OVER_FOUR (OMS_PI / 4.0f) @@ -25,7 +19,7 @@ #define OMS_MAX(a, b) ((a) > (b) ? (a) : (b)) #define OMS_MIN(a, b) ((a) > (b) ? (b) : (a)) -#define OMS_CLAMP(a, b, c) (OMS_MAX(OMS_MIN((a), (b))), (c)) +#define OMS_CLAMP(a, b, c) (OMS_MAX(OMS_MIN((a), (b)), (c))) #define OMS_ABS(a) ((a) > 0 ? (a) : -(a)) #define OMS_DEG2RAD(angle) ((angle) * OMS_PI / 180.0f) #define OMS_RAD2DEG(angle) ((angle) * 180.0f / OMS_PI) diff --git a/utils/StringUtils.h b/utils/StringUtils.h index 40c13ec..29d5564 100644 --- a/utils/StringUtils.h +++ b/utils/StringUtils.h @@ -136,12 +136,12 @@ int32 utf8_get_char_at(const char* in, int32 index) { inline void wchar_to_char(wchar_t* str) { - char *src = (char*) str; - char *dest = (char *) src; + char* src = (char*) str; + char* dest = src; while (*src != '\0' && src[1] != '\0') { if (*src != '\0') { - *dest++ = (char) *src; + *dest++ = *src; } ++src; @@ -151,16 +151,14 @@ void wchar_to_char(wchar_t* str) } inline -void wchar_to_char(const char* str, char* __restrict dest) +void wchar_to_char(const char* __restrict str, char* __restrict dest) { - char *src = (char*) str; - - while (*src != '\0' && src[1] != '\0') { - if (*src != '\0') { - *dest++ = (char) *src; + while (*str != '\0' && str[1] != '\0') { + if (*str != '\0') { + *dest++ = (char) *str; } - ++src; + ++str; } *dest = '\0'; @@ -189,8 +187,8 @@ int32 str_to_int(const char *str) inline constexpr int32 int_to_str(int64 number, char *str, const char thousands = ',') { int32 i = 0; - int64 sign = number; int32 digit_count = 0; + int64 sign = number; if (number == 0) { str[i++] = '0'; @@ -243,7 +241,8 @@ size_t str_count(const char* __restrict str, const char* __restrict substr) return count; } -inline char* strsep(const char* *sp, const char* sep) +inline +char* strsep(const char** sp, const char* sep) { char* p, *s; @@ -251,7 +250,7 @@ inline char* strsep(const char* *sp, const char* sep) return (NULL); } - s = (char* ) *sp; + s = (char *) *sp; p = s + strcspn(s, sep); if (*p != '\0') { @@ -431,8 +430,7 @@ void str_replace(const char* str, const char* __restrict search, const char* __r memcpy(result_ptr, replace, replace_len); result_ptr += replace_len; - current += search_len; - str = current; + str = current + search_len; } strcpy(result_ptr, str); @@ -476,7 +474,7 @@ bool is_whitespace(char str) } inline -int32 chars_to_eol(const char* str) +int32 str_to_eol(const char* str) { int32 offset = 0; while (!is_eol(str) && *str++ != '\0') { @@ -487,7 +485,7 @@ int32 chars_to_eol(const char* str) } inline -int32 chars_to(const char* str, char delim) +int32 str_to(const char* str, char delim) { int32 offset = 0; while (*str != delim && *str++ != '\0') { @@ -498,7 +496,7 @@ int32 chars_to(const char* str, char delim) } inline -void char_move_to(char** str, const char delim) +void str_move_to(char** str, char delim) { while (**str != delim && **str != '\0') { ++(*str); @@ -506,7 +504,7 @@ void char_move_to(char** str, const char delim) } inline -void char_move_past(char** str, const char delim) +void str_move_past(char** str, char delim) { while (**str != delim && **str != '\0') { ++(*str); @@ -518,7 +516,7 @@ void char_move_past(char** str, const char delim) } inline -void char_move_past_alpha_num(char** str) +void str_move_past_alpha_num(char** str) { while ((**str >= 48 && **str <= 57) || (**str >= 65 && **str <= 90) @@ -536,7 +534,7 @@ bool str_is_comment(char* str) } inline -void char_skip(char** str, const char delim) +void str_skip(char** str, char delim) { while (**str == delim) { ++(*str); @@ -544,7 +542,7 @@ void char_skip(char** str, const char delim) } inline -void char_skip_whitespace(char** str) +void str_skip_whitespace(char** str) { while (**str == ' ' || **str == '\t') { ++(*str); @@ -552,7 +550,7 @@ void char_skip_whitespace(char** str) } inline -void char_skip_empty(char** str) +void str_skip_empty(char** str) { while (**str == ' ' || **str == '\t' || **str == '\n' || **str == '\r') { ++(*str); @@ -560,7 +558,7 @@ void char_skip_empty(char** str) } inline -void char_skip_non_empty(char** str) +void str_skip_non_empty(char** str) { while (**str != ' ' && **str != '\t' && **str != '\n' && **str != '\0') { ++(*str); @@ -568,7 +566,7 @@ void char_skip_non_empty(char** str) } inline -void char_skip_list(char** __restrict str, const char* __restrict delim, int32 len) +void str_skip_list(char** __restrict str, const char* __restrict delim, int32 len) { bool run = true; while (run && **str != '\0') { @@ -586,7 +584,7 @@ void char_skip_list(char** __restrict str, const char* __restrict delim, int32 l } inline -void char_skip_until_list(char** __restrict str, const char* __restrict delim, int32 len) +void str_skip_until_list(char** __restrict str, const char* __restrict delim, int32 len) { while (**str != '\0') { for (int32 i = 0; i < len; ++i) { @@ -600,7 +598,7 @@ void char_skip_until_list(char** __restrict str, const char* __restrict delim, i } inline -void char_copy_until(const char* __restrict src, char* __restrict dest, char delim) +void str_copy_until(const char* __restrict src, char* __restrict dest, char delim) { while (*src != delim && *src != '\0') { *dest++ = *src++; @@ -610,7 +608,7 @@ void char_copy_until(const char* __restrict src, char* __restrict dest, char del } inline -void char_copy_until(const char* __restrict src, char* __restrict dest, const char* __restrict delim, int32 len) +void str_copy_until(const char* __restrict src, char* __restrict dest, const char* __restrict delim, int32 len) { while (*src != '\0') { for (int32 i = 0; i < len; ++i) { @@ -627,9 +625,37 @@ void char_copy_until(const char* __restrict src, char* __restrict dest, const ch } inline -void char_copy_move_until(char** __restrict src, char* __restrict dest, char delim) +int32 str_copy_until(char* __restrict dest, const char* __restrict src, char delim) { - while (**src != delim) { + int32 len = 0; + while (*src != delim && *src != '\0') { + *dest++ = *src++; + ++len; + } + + *dest = '\0'; + + return len; +} + +inline +int32 str_copy(char* __restrict dest, const char* __restrict src, char delim) +{ + int32 len = 0; + while (*src != delim) { + *dest++ = *src++; + ++len; + } + + *dest = '\0'; + + return len; +} + +inline +void str_copy_move_until(char** __restrict src, char* __restrict dest, char delim) +{ + while (**src != delim && **src != '\0') { *dest++ = **src; ++(*src); } @@ -638,7 +664,7 @@ void char_copy_move_until(char** __restrict src, char* __restrict dest, char del } inline -void char_copy_move_until(char** __restrict src, char* __restrict dest, const char* __restrict delim, int32 len) +void str_copy_move_until(char** __restrict src, char* __restrict dest, const char* __restrict delim, int32 len) { while (**src != '\0') { for (int32 i = 0; i < len; ++i) { @@ -655,8 +681,6 @@ void char_copy_move_until(char** __restrict src, char* __restrict dest, const ch *dest = '\0'; } -// @question Do we really need this, isn't char_copy_move_until better? -// Maybe create a copy_move_until_eol inline int32 strcpy_to_eol(const char* src, char* dst) { diff --git a/utils/SystemUtils.h b/utils/SystemUtils.h deleted file mode 100644 index 5fb22d8..0000000 --- a/utils/SystemUtils.h +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Jingga - * - * @copyright Jingga - * @license OMS License 2.0 - * @version 1.0.0 - * @link https://jingga.app - */ -#ifndef TOS_UTILS_SYSTEM_UTILS_H -#define TOS_UTILS_SYSTEM_UTILS_H - -#include -#include - -#endif \ No newline at end of file diff --git a/utils/Utils.h b/utils/Utils.h index 8536f15..0444fc8 100644 --- a/utils/Utils.h +++ b/utils/Utils.h @@ -10,7 +10,6 @@ #define TOS_UTILS_H #include -#include #include "../stdlib/Types.h"