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

Program Listing for File arena.hpp

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

#ifndef RIPPLE_ALLOCATION_ARENA_HPP
#define RIPPLE_ALLOCATION_ARENA_HPP

#include <ripple/arch/gpu_utils.hpp>
#include <ripple/utility/memory.hpp>
#include <type_traits>
#include <cstring>

namespace ripple {

template <size_t Size>
class StackArena {
  static constexpr size_t stack_size = Size;

 public:
  // clang-format off
  static constexpr bool contexpr_size   = true;
  static constexpr bool valid_on_device = true;
  static constexpr bool valid_on_host   = true;
  // clang-format on

  using Ptr      = void*;
  using ConstPtr = const void*;

  ripple_all StackArena(size_t size = 0) noexcept {}

  ripple_nodiscard ripple_all auto begin() const noexcept -> ConstPtr {
    return static_cast<ConstPtr>(&buffer_[0]);
  }

  ripple_nodiscard ripple_all auto end() const noexcept -> ConstPtr {
    return static_cast<ConstPtr>(&buffer_[stack_size]);
  }

  ripple_nodiscard ripple_all constexpr auto
  size() const noexcept -> size_t {
    return stack_size;
  }

 private:
  char buffer_[stack_size];
};

struct HeapArena {
 public:
  // clang-format off
  static constexpr bool constexpr_size  = false;
  static constexpr bool valid_on_device = false;
  static constexpr bool valid_on_host   = true;
  // clang-format on

  using Ptr      = void*;
  using ConstPtr = void*;

  explicit HeapArena(size_t size = 0) {
    if (size) {
      cpu::allocate_host_pinned(&start_, size);
      end_ = offset_ptr(start_, size);
    }
  }

  ~HeapArena() noexcept {
    if (start_ != nullptr) {
      cpu::free_host_pinned(start_);
      start_ = nullptr;
      end_   = nullptr;
    }
  }

  // clang-format off
  HeapArena(const HeapArena&)     = delete;
  HeapArena(HeapArena&&) noexcept = default;

  auto operator=(const HeapArena&)                   = delete;
  auto operator=(HeapArena&&) noexcept -> HeapArena& = default;
  // clang-format on

  ripple_nodiscard auto begin() const noexcept -> ConstPtr {
    return start_;
  }

  ripple_nodiscard auto end() const noexcept -> ConstPtr {
    return end_;
  }

  auto resize(size_t new_size) -> void {
    if (new_size < size()) {
      return;
    }
    void* new_ptr = nullptr;
    cpu::allocate_host_pinned(&new_ptr, new_size);
    if (start_) {
      memcpy(new_ptr, start_, size());
      cpu::free_host_pinned(start_);
    }
    start_ = new_ptr;
    end_   = offset_ptr(start_, new_size);
  }

  ripple_nodiscard auto size() const noexcept -> size_t {
    return uintptr_t(end_) - uintptr_t(start_);
  }

 private:
  void* start_ = nullptr;
  void* end_   = nullptr;
};

struct GpuHeapArena {
 public:
  // clang-format off
  static constexpr bool constexpr_size  = false;
  static constexpr bool valid_on_device = true;
  static constexpr bool valid_on_host   = false;
  // clang-format on

  using Ptr      = void*;
  using ConstPtr = void*;

  explicit GpuHeapArena(size_t id, size_t size = 0) : id_{id} {
    if (size) {
      gpu::set_device(id_);
      gpu::allocate_device(&start_, size);
      end_ = offset_ptr(start_, size);
    }
  }

  ~GpuHeapArena() noexcept {
    cleanup();
  }

  // clang-format off
  GpuHeapArena(const GpuHeapArena&)     = delete;
  GpuHeapArena(GpuHeapArena&&) noexcept = default;

  auto operator=(const GpuHeapArena&)                      = delete;
  auto operator=(GpuHeapArena&&) noexcept -> GpuHeapArena& = default;
  // clang-format on

  ripple_nodiscard auto begin() const noexcept -> ConstPtr {
    return start_;
  }

  ripple_nodiscard auto end() const noexcept -> ConstPtr {
    return end_;
  }

  auto resize(size_t new_size) -> void {
    if (new_size < size()) {
      return;
    }
    void* new_ptr = nullptr;
    gpu::set_device(id_);
    gpu::allocate_device(&new_ptr, new_size);
    if (start_) {
      gpu::memcpy_device_to_device_async(new_ptr, start_, size());
      gpu::free_device(start_);
    }
    start_ = new_ptr;
    end_   = offset_ptr(start_, new_size);
  }

  ripple_nodiscard auto size() const noexcept -> size_t {
    return uintptr_t(end_) - uintptr_t(start_);
  }

 private:
  void*  start_ = nullptr;
  void*  end_   = nullptr;
  size_t id_    = 0;

  auto cleanup() noexcept -> void {
    if (start_) {
      gpu::set_device(id_);
      gpu::synchronize_device();
      gpu::free_device(start_);
      start_ = nullptr;
      end_   = nullptr;
    }
  }
};

/*==--- [aliases] ----------------------------------------------------------==*/

static constexpr size_t default_stack_arena_size = 1024;

using DefaultStackArena = StackArena<default_stack_arena_size>;

template <typename Arena>
using arena_constexpr_size_enable_t =
  std::enable_if_t<std::decay_t<Arena>::contexpr_size, int>;

template <typename Arena>
using arena_non_constexpr_size_enable_t =
  std::enable_if_t<!std::decay_t<Arena>::contexpr_size, int>;

} // namespace ripple

#endif // RIPPLE_ALLOCATION_ARENA_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