Fork of Tangara with customizations
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
tangara-fw/src/memory/arena.cpp

86 lines
1.8 KiB

/*
* Copyright 2023 jacqueline <me@jacqueline.id.au>
*
* SPDX-License-Identifier: GPL-3.0-only
*/
#include "arena.hpp"
#include <cstdint>
#include <optional>
#include "esp_heap_caps.h"
#include "freertos/queue.h"
#include "span.hpp"
namespace memory {
Arena::Arena(std::size_t block_size,
std::size_t num_blocks,
uint32_t alloc_flags)
: block_size_(block_size) {
pool_ = static_cast<std::byte*>(
heap_caps_malloc(block_size * num_blocks, alloc_flags));
free_blocks_ = xQueueCreate(num_blocks, sizeof(void*));
for (int i = 0; i < num_blocks; i++) {
std::byte* block = pool_ + (i * block_size);
xQueueSend(free_blocks_, &block, 0);
}
}
Arena::~Arena() {
// We shouldn't have any blocks in use when destroying an arena.
assert(uxQueueSpacesAvailable(free_blocks_) == 0);
vQueueDelete(free_blocks_);
free(pool_);
}
auto Arena::Acquire() -> std::optional<ArenaPtr> {
std::byte* block;
bool result = xQueueReceive(free_blocks_, &block, 0);
if (result) {
ArenaPtr ptr{this, block, block_size_, 0};
return ptr;
} else {
return {};
}
}
auto Arena::Return(ArenaPtr ptr) -> void {
assert(ptr.owner == this);
xQueueSend(free_blocks_, &ptr.start, 0);
}
auto Arena::BlocksFree() -> std::size_t {
return uxQueueMessagesWaiting(free_blocks_);
}
auto ArenaRef::Acquire(Arena* a) -> std::optional<ArenaRef> {
auto ptr = a->Acquire();
if (ptr) {
ArenaRef ref{*ptr};
return ref;
}
return {};
}
ArenaRef::ArenaRef(ArenaPtr p) : ptr(p) {}
ArenaRef::ArenaRef(ArenaRef&& other) : ptr(other.Release()) {}
auto ArenaRef::Release() -> ArenaPtr {
auto ret = ptr;
ptr.owner = nullptr;
ptr.start = nullptr;
ptr.size = 0;
ptr.used_size = 0;
return ret;
}
ArenaRef::~ArenaRef() {
if (ptr.owner != nullptr) {
ptr.owner->Return(ptr);
}
}
} // namespace memory