Pixie
Loading...
Searching...
No Matches
payload_chunks.h
1#pragma once
2
3#include <concepts>
4#include <type_traits>
5#include <utility>
6#include <vector>
7
8namespace pixie::permutations::detail {
9
10// Own frozen payload vectors independently of the order tree. Publishing a
11// chunk transfers ownership; its reserved capacity must not grow afterwards.
12// Chain splicing preserves addresses, and destruction uses constant stack.
13template <class T>
14struct PayloadChunks {
15 // Avoid vector<bool>'s proxy storage: indirect reads need actual bool
16 // objects.
17 struct BoolSlot {
18 bool value;
19 };
20 using Slot = std::conditional_t<std::same_as<T, bool>, BoolSlot, T>;
21 static_assert(sizeof(Slot) == sizeof(T));
22 struct Chunk {
23 std::vector<Slot> values;
24 Chunk* next = nullptr;
25 };
26
27 Chunk* head = nullptr;
28 Chunk* tail = nullptr;
29
30 PayloadChunks() noexcept = default;
31 PayloadChunks(const PayloadChunks&) = delete;
32 PayloadChunks& operator=(const PayloadChunks&) = delete;
33 PayloadChunks(PayloadChunks&& other) noexcept
34 : head(std::exchange(other.head, nullptr)),
35 tail(std::exchange(other.tail, nullptr)) {}
36 PayloadChunks& operator=(PayloadChunks&& other) noexcept {
37 if (this != &other) {
38 clear();
39 head = std::exchange(other.head, nullptr);
40 tail = std::exchange(other.tail, nullptr);
41 }
42 return *this;
43 }
44 ~PayloadChunks() { clear(); }
45
46 void clear() noexcept {
47 while (head) {
48 auto* next = head->next;
49 delete head;
50 head = next;
51 }
52 tail = nullptr;
53 }
54 void append(Chunk* chunk) noexcept {
55 if (tail) {
56 tail->next = chunk;
57 } else {
58 head = chunk;
59 }
60 tail = chunk;
61 }
62 void splice(PayloadChunks& donor) noexcept {
63 if (!donor.head) {
64 return;
65 }
66 if (tail) {
67 tail->next = donor.head;
68 } else {
69 head = donor.head;
70 }
71 tail = donor.tail;
72 donor.head = donor.tail = nullptr;
73 }
74};
75
76} // namespace pixie::permutations::detail
Definition payload_chunks.h:14