diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a99b02..d59eb3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.0.67) +project(blt-gp VERSION 0.0.68) include(CTest) diff --git a/include/blt/gp/program.h b/include/blt/gp/program.h index 1c20d19..b34b8d2 100644 --- a/include/blt/gp/program.h +++ b/include/blt/gp/program.h @@ -299,9 +299,9 @@ namespace blt::gp thread_helper.threads_left.fetch_add(1, std::memory_order::memory_order_relaxed); while (thread_helper.evaluation_left > 0) { + blt::size_t size = 0; blt::size_t begin = 0; blt::size_t end = thread_helper.evaluation_left.load(std::memory_order_acquire); - blt::size_t size = 0; do { size = std::min(end, config.evaluation_size); diff --git a/include/blt/gp/stack.h b/include/blt/gp/stack.h index 96bb304..297f859 100644 --- a/include/blt/gp/stack.h +++ b/include/blt/gp/stack.h @@ -20,6 +20,7 @@ #define BLT_GP_STACK_H #include +#include #include #include #include @@ -79,11 +80,7 @@ namespace blt::gp head->metadata.offset -= TYPE_SIZE; if (head->used_bytes_in_block() == 0) { - auto old = head; - head = head->metadata.prev; - if (head != nullptr) - head->metadata.next = nullptr; - std::free(old); + move_back(); } return t; } @@ -143,12 +140,7 @@ namespace blt::gp if (diff <= 0) { bytes -= head->used_bytes_in_block(); - auto old = head; - head = head->metadata.prev; - // required to prevent silly memory :3 - if (head != nullptr) - head->metadata.next = nullptr; - std::free(old); + move_back(); if (diff == 0) break; } else @@ -160,6 +152,27 @@ namespace blt::gp } } + /** + * Warning this function should be used to transfer types, not arrays of types! It will produce an error if you attempt to pass more + * than one type # of bytes at a time~! + * @param to stack to push to + * @param bytes number of bytes to transfer out. + */ + void transfer_bytes(stack_allocator& to, blt::size_t bytes) + { + if (empty()) + throw std::runtime_error("This stack is empty!"); + if (head->used_bytes_in_block() < static_cast(bytes)) + BLT_ABORT("This stack doesn't contain enough data for this type! This is an invalid runtime state!"); + auto type_size = aligned_size(bytes); + auto ptr = to.allocate_bytes(bytes); + to.head->metadata.offset = static_cast(ptr) + type_size; + std::memcpy(ptr, head->metadata.offset - type_size, type_size); + head->metadata.offset -= type_size; + if (head->used_bytes_in_block() == 0) + move_back(); + } + template void call_destructors() { @@ -252,19 +265,18 @@ namespace blt::gp ~stack_allocator() { - block* current = head; - while (current != nullptr) - { - block* ptr = current; - current = current->metadata.prev; - std::free(ptr); - } + free_chain(head); } template static inline constexpr blt::size_t aligned_size() noexcept { - return (sizeof(T) + (MAX_ALIGNMENT - 1)) & ~(MAX_ALIGNMENT - 1); + return aligned_size(sizeof(T)); + } + + static inline constexpr blt::size_t aligned_size(blt::size_t size) noexcept + { + return (size + (MAX_ALIGNMENT - 1)) & ~(MAX_ALIGNMENT - 1); } private: @@ -292,6 +304,11 @@ namespace blt::gp metadata.offset = buffer; } + void reset() + { + metadata.offset = buffer; + } + [[nodiscard]] blt::ptrdiff_t storage_size() const { return static_cast(metadata.size - sizeof(typename block::block_metadata_t)); @@ -311,10 +328,23 @@ namespace blt::gp template void* allocate_bytes() { - auto ptr = get_aligned_pointer(sizeof(T)); + return allocate_bytes(sizeof(T)); + } + + void* allocate_bytes(blt::size_t size) + { + auto ptr = get_aligned_pointer(size); if (ptr == nullptr) - push_block_for(); - ptr = get_aligned_pointer(sizeof(T)); + { + if (head != nullptr && head->metadata.next != nullptr) + { + head = head->metadata.next; + if (head != nullptr) + head->reset(); + } else + push_block(aligned_size(size)); + } + ptr = get_aligned_pointer(size); if (ptr == nullptr) throw std::bad_alloc(); return ptr; @@ -329,12 +359,6 @@ namespace blt::gp return std::align(MAX_ALIGNMENT, bytes, pointer, remaining_bytes); } - template - void push_block_for() - { - push_block(aligned_size()); - } - void push_block(blt::size_t size) { auto blk = allocate_block(size); @@ -361,6 +385,28 @@ namespace blt::gp new(data) block{size}; return reinterpret_cast(data); } + + static void free_chain(block* current) + { + while (current != nullptr) + { + block* ptr = current; + current = current->metadata.prev; + std::free(ptr); + } + } + + inline void move_back() + { + auto old = head; + head = head->metadata.prev; + if (head == nullptr) + free_chain(old); + // required to prevent silly memory :3 + //if (head != nullptr) + // head->metadata.next = nullptr; + //std::free(old); + } private: block* head = nullptr; diff --git a/lib/blt b/lib/blt index c5f3d9b..9a437ec 160000 --- a/lib/blt +++ b/lib/blt @@ -1 +1 @@ -Subproject commit c5f3d9ba3b805d16c44cca020eeeec8abcee443f +Subproject commit 9a437ec75a41cc32e716da7d88cf36007f30f268