.. _program_listing_file_include_ripple_allocation_freelist.hpp: Program Listing for File freelist.hpp ===================================== |exhale_lsh| :ref:`Return to documentation for file <file_include_ripple_allocation_freelist.hpp>` (``include/ripple/allocation/freelist.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #ifndef RIPPLE_ALLOCATION_FREELIST_HPP #define RIPPLE_ALLOCATION_FREELIST_HPP #include <ripple/utility/memory.hpp> namespace ripple { class Freelist { struct Node { Node* next = nullptr; }; public: ripple_all Freelist() noexcept : head_{nullptr} {} ripple_all ~Freelist() noexcept { if (head_ != nullptr) { head_ = nullptr; } } ripple_all Freelist( const void* start, const void* end, size_t element_size, size_t alignment) noexcept : head_{initialize(start, end, element_size, alignment)} {} Freelist(Freelist&& other) noexcept = default; auto operator=(Freelist&& other) noexcept -> Freelist& = default; // clang-format off Freelist(const Freelist&) = delete; auto operator=(const Freelist&) = delete; // clang-format on /*==--- [interface] ------------------------------------------------------==*/ ripple_all auto pop_front() noexcept -> void* { Node* const popped_head = head_; head_ = popped_head ? popped_head->next : nullptr; return static_cast<void*>(popped_head); } ripple_all auto push_front(void* ptr) noexcept -> void { if (ptr == nullptr) { return; } Node* const pushed_head = static_cast<Node*>(ptr); pushed_head->next = head_; head_ = pushed_head; } private: Node* head_ = nullptr; ripple_all static auto initialize( const void* start, const void* end, size_t element_size, size_t alignment) -> Node* { // Create the first and second elements: void* const first = align_ptr(start, alignment); void* const second = align_ptr(offset_ptr(first, element_size), alignment); const size_t size = uintptr_t(second) - uintptr_t(first); const size_t elements = (uintptr_t(end) - uintptr_t(first)) / size; // Set the head of the list: Node* head = static_cast<Node*>(first); // Initialize the rest of the list: Node* current = head; for (size_t i = 1; i < elements; ++i) { Node* next = static_cast<Node*>(offset_ptr(current, size)); current->next = next; current = next; } assert( offset_ptr(current, size) <= end && "Freelist initialization overflows provided arena!"); current->next = nullptr; return head; } }; } // namespace ripple #endif // RIPPLE_ALLOCATION_FREELIST_HPP