blob: 26d49d27c4f98e5b23bde67275eace68f03ad576 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
#pragma once
#include <cstdint>
#include <optional>
#include <utility>
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "span.hpp"
#include "sys/_stdint.h"
namespace memory {
class Arena;
/*
* A pointer to data that has been given out by an Arena, plus extra accounting
* information so that it can be returned properly.
*/
struct ArenaPtr {
Arena* owner;
std::byte* start;
std::size_t size;
// A convenience for keeping track of the subset of the block that has had
// data placed within it.
std::size_t used_size;
};
/*
* A basic memory arena. This class mediates access to fixed-size blocks of
* memory within a larger contiguous block. This is faster than re-allocating
* smaller blocks every time they're needed, and lets us easily limit the
* maximum size of the memory used.
*
* A single arena instance is safe to be used concurrently by multiple tasks,
* however there is no built in synchronisation of the underlying memory.
*/
class Arena {
public:
Arena(std::size_t block_size, std::size_t num_blocks, uint32_t alloc_flags);
~Arena();
/*
* Attempts to receive an allocation from this arena. Returns absent if
* there are no blocks left.
*/
auto Acquire() -> std::optional<ArenaPtr>;
/* Returns a previously allocated block to this arena. */
auto Return(ArenaPtr) -> void;
/* Returns the number of blocks that are currently free. */
auto BlocksFree() -> std::size_t;
Arena(const Arena&) = delete;
Arena& operator=(const Arena&) = delete;
private:
std::size_t block_size_;
// The large memory allocation that is divided into blocks.
std::byte* pool_;
// A FreeRTOS queue containing the blocks that are currently unused.
QueueHandle_t free_blocks_;
};
/*
* Wrapper around an ArenaPtr that handles acquiring and returning the block
* through RAII.
*/
class ArenaRef {
public:
static auto Acquire(Arena* a) -> std::optional<ArenaRef>;
explicit ArenaRef(ArenaPtr ptr);
~ArenaRef();
auto Release() -> ArenaPtr;
ArenaRef(ArenaRef&&);
ArenaRef(const ArenaRef&) = delete;
Arena& operator=(const Arena&) = delete;
ArenaPtr ptr;
};
} // namespace memory
|