• Docs >
  • Program Listing for File freelist.hpp
Shortcuts

Program Listing for File freelist.hpp

Return to documentation for file (include/ripple/allocation/freelist.hpp)

#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

Docs

Access comprehensive developer documentation for Ripple

View Docs

Tutorials

Get tutorials to help with understand all features

View Tutorials

Examples

Find examples to help get started

View Examples