Pixie
Loading...
Searching...
No Matches
aligned.h
1#pragma once
2
3#include <pixie/storage.h>
4#include <pixie/storage/read_only_view.h>
5
6#include <algorithm>
7#include <array>
8#include <cstddef>
9#include <cstdint>
10#include <limits>
11#include <span>
12#include <stdexcept>
13#include <vector>
14
15namespace pixie {
16
17inline constexpr std::size_t kAlignedStorageLineBytes = 64;
18inline constexpr std::size_t kAlignedStorageLineBits =
19 kAlignedStorageLineBytes * 8;
20inline constexpr std::size_t kAlignedStorageLineWords64 =
21 kAlignedStorageLineBytes / sizeof(std::uint64_t);
22inline constexpr std::size_t kAlignedStorageLineWords16 =
23 kAlignedStorageLineBytes / sizeof(std::uint16_t);
24
26struct alignas(kAlignedStorageLineBytes) CacheLine {
27 std::array<std::byte, kAlignedStorageLineBytes> data{};
28};
29
30static_assert(alignof(CacheLine) == kAlignedStorageLineBytes);
31static_assert(sizeof(CacheLine) == kAlignedStorageLineBytes);
32
41class AlignedStorage : public StorageBase<AlignedStorage> {
42 public:
43 AlignedStorage() = default;
44
46 explicit AlignedStorage(std::size_t size_bits)
47 : logical_size_bytes_(bytes_for_bits(size_bits)),
48 data_(lines_for_bits(size_bits)) {}
49
51 explicit AlignedStorage(std::span<const std::uint64_t> words)
52 : AlignedStorage(bit_size_for_words(words.size())) {
53 std::copy(words.begin(), words.end(), writable_words64_impl().begin());
54 }
55
57 std::size_t size_bytes_impl() const { return logical_size_bytes_; }
58
60 position_type begin_position_impl() const { return 0; }
61
63 position_type end_position_impl() const { return logical_size_bytes_; }
64
66 std::size_t logical_size_bytes() const { return logical_size_bytes_; }
67
69 std::size_t padded_size_bytes() const {
70 return data_.size() * kAlignedStorageLineBytes;
71 }
72
81 std::as_bytes(std::span<const CacheLine>(data_)));
82 }
83
85 std::span<const std::byte> as_bytes_impl() const {
86 return std::as_bytes(std::span<const CacheLine>(data_))
87 .first(logical_size_bytes_);
88 }
89
91 SplitSpan<const std::byte> segments_impl(std::size_t offset_bytes,
92 std::size_t count_bytes) const {
93 return SplitSpan(as_bytes_impl().subspan(offset_bytes, count_bytes));
94 }
95
97 SplitSpan<std::byte> segments_impl(std::size_t offset_bytes,
98 std::size_t count_bytes) {
99 return SplitSpan(writable_bytes_impl().subspan(offset_bytes, count_bytes));
100 }
101
103 ReadOnlyStorageView view_impl(std::size_t offset_bytes,
104 std::size_t count_bytes) const {
105 if (offset_bytes > size_bytes_impl() ||
106 count_bytes > size_bytes_impl() - offset_bytes) {
107 throw std::out_of_range("Storage view is outside the allocation");
108 }
109 return ReadOnlyStorageView(
110 as_bytes_impl().subspan(offset_bytes, count_bytes));
111 }
112
114 void resize_impl(std::size_t size_bits) {
115 data_.resize(lines_for_bits(size_bits));
116 logical_size_bytes_ = bytes_for_bits(size_bits);
117 }
118
120 std::span<std::byte> writable_bytes_impl() {
121 return std::as_writable_bytes(std::span<CacheLine>(data_))
122 .first(logical_size_bytes_);
123 }
124
126 std::span<std::uint16_t> writable_words16_impl() {
127 return {reinterpret_cast<std::uint16_t*>(data_.data()),
128 logical_size_bytes_ / sizeof(std::uint16_t)};
129 }
130
132 std::span<std::uint64_t> writable_words64_impl() {
133 return {reinterpret_cast<std::uint64_t*>(data_.data()),
134 logical_size_bytes_ / sizeof(std::uint64_t)};
135 }
136
138 std::size_t allocated_bytes_impl() const {
139 return data_.capacity() * kAlignedStorageLineBytes;
140 }
141
143 void shrink_to_fit_impl() { data_.shrink_to_fit(); }
144
146 std::span<CacheLine> as_lines() { return data_; }
147
149 std::span<const CacheLine> as_lines() const { return data_; }
150
152 static AlignedStorage deserialize_impl(BinaryReader& reader) {
153 const std::size_t size = reader.read_size();
154 if (size > std::numeric_limits<std::size_t>::max() / 8) {
155 throw std::length_error("Serialized aligned storage is too large");
156 }
157 AlignedStorage result(size * 8);
158 const std::span<const std::byte> bytes = reader.read_bytes(size);
159 std::ranges::copy(bytes, result.writable_bytes().begin());
160 return result;
161 }
162
163 private:
164 static std::size_t bit_size_for_words(std::size_t word_count) {
165 constexpr std::size_t kWordBits =
166 std::numeric_limits<std::uint64_t>::digits;
167 if (word_count > std::numeric_limits<std::size_t>::max() / kWordBits) {
168 throw std::length_error("Aligned storage word sequence is too large");
169 }
170 return word_count * kWordBits;
171 }
172
173 static constexpr std::size_t bytes_for_bits(std::size_t size_bits) {
174 return size_bits / 8 + (size_bits % 8 != 0);
175 }
176
177 static constexpr std::size_t lines_for_bits(std::size_t size_bits) {
178 return size_bits / kAlignedStorageLineBits +
179 (size_bits % kAlignedStorageLineBits != 0);
180 }
181
182 std::size_t logical_size_bytes_ = 0;
183 std::vector<CacheLine> data_;
184};
185
186} // namespace pixie
std::span< CacheLine > as_lines()
Return mutable cache-line blocks.
Definition aligned.h:146
std::size_t logical_size_bytes() const
Return the logical number of exposed bytes.
Definition aligned.h:66
static AlignedStorage deserialize_impl(BinaryReader &reader)
Restore an owning copy of one size-prefixed byte sequence.
Definition aligned.h:152
void shrink_to_fit_impl()
Request release of unused vector capacity.
Definition aligned.h:143
std::size_t padded_size_bytes() const
Return the cache-line-rounded backing size in bytes.
Definition aligned.h:69
AlignedStorage(std::size_t size_bits)
Construct storage for at least size_bits bits.
Definition aligned.h:46
std::span< const CacheLine > as_lines() const
Return read-only cache-line blocks.
Definition aligned.h:149
std::size_t size_bytes_impl() const
Return the logical number of exposed bytes.
Definition aligned.h:57
void resize_impl(std::size_t size_bits)
Resize to hold at least size_bits bits.
Definition aligned.h:114
AlignedStorage(std::span< const std::uint64_t > words)
Copy complete 64-bit words into aligned owning storage.
Definition aligned.h:51
std::size_t allocated_bytes_impl() const
Return bytes reserved by the underlying vector.
Definition aligned.h:138
SplitSpan< std::byte > segments_impl(std::size_t offset_bytes, std::size_t count_bytes)
Return a checked logical byte range as one writable segment.
Definition aligned.h:97
std::span< const std::byte > as_bytes_impl() const
Return the logical bytes as a read-only span.
Definition aligned.h:85
std::span< std::byte > writable_bytes_impl()
Return writable logical bytes.
Definition aligned.h:120
ReadOnlyStorageView view_impl(std::size_t offset_bytes, std::size_t count_bytes) const
Return a checked read-only byte subrange.
Definition aligned.h:103
std::span< std::uint64_t > writable_words64_impl()
Return writable logical storage as 64-bit words.
Definition aligned.h:132
ReadOnlyStorageView padded_view() const
Return a non-owning view of the complete cache-line backing.
Definition aligned.h:79
std::span< std::uint16_t > writable_words16_impl()
Return writable logical storage as 16-bit words.
Definition aligned.h:126
SplitSpan< const std::byte > segments_impl(std::size_t offset_bytes, std::size_t count_bytes) const
Return a checked logical byte range as one physical segment.
Definition aligned.h:91
position_type end_position_impl() const
Return the position one past the final logical byte.
Definition aligned.h:63
position_type begin_position_impl() const
Return the first logical byte position.
Definition aligned.h:60
Bounds-checked reader for canonical little-endian binary data.
Definition serialization.h:526
std::span< const std::byte > read_bytes(std::size_t count)
Read exactly count uninterpreted bytes.
Definition serialization.h:604
std::size_t read_size()
Read an unsigned 64-bit size and convert it to size_t.
Definition serialization.h:587
A non-owning, read-only view of a byte sequence.
Definition read_only_view.h:15
A logical contiguous sequence stored in at most two physical spans.
Definition split_span.h:25
CRTP facade for byte-addressable storage.
Definition storage.h:65
std::size_t size_bits() const
Definition storage.h:78
std::uint64_t position_type
Definition storage.h:68
auto writable_bytes()
Return writable storage bytes.
Definition storage.h:228
Common interface for byte-addressable storage.
A 64-byte aligned storage block.
Definition aligned.h:26