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
54 explicit AlignedStorage(std::span<const std::byte> bytes)
55 : logical_size_bytes_(bytes.size()),
56 data_(lines_for_bytes(bytes.size())) {
57 std::ranges::copy(bytes, writable_bytes_impl().begin());
58 }
59
61 explicit AlignedStorage(std::span<const std::uint64_t> words)
62 : AlignedStorage(std::as_bytes(words)) {}
63
65 std::size_t size_bytes_impl() const { return logical_size_bytes_; }
66
68 position_type begin_position_impl() const { return 0; }
69
71 position_type end_position_impl() const { return logical_size_bytes_; }
72
74 std::size_t logical_size_bytes() const { return logical_size_bytes_; }
75
77 std::size_t padded_size_bytes() const {
78 return data_.size() * kAlignedStorageLineBytes;
79 }
80
89 std::as_bytes(std::span<const CacheLine>(data_)));
90 }
91
93 std::span<const std::byte> as_bytes_impl() const {
94 return std::as_bytes(std::span<const CacheLine>(data_))
95 .first(logical_size_bytes_);
96 }
97
99 SplitSpan<const std::byte> segments_impl(std::size_t offset_bytes,
100 std::size_t count_bytes) const {
101 return SplitSpan(as_bytes_impl().subspan(offset_bytes, count_bytes));
102 }
103
105 SplitSpan<std::byte> segments_impl(std::size_t offset_bytes,
106 std::size_t count_bytes) {
107 return SplitSpan(writable_bytes_impl().subspan(offset_bytes, count_bytes));
108 }
109
111 ReadOnlyStorageView view_impl(std::size_t offset_bytes,
112 std::size_t count_bytes) const {
113 if (offset_bytes > size_bytes_impl() ||
114 count_bytes > size_bytes_impl() - offset_bytes) {
115 throw std::out_of_range("Storage view is outside the allocation");
116 }
117 return ReadOnlyStorageView(
118 as_bytes_impl().subspan(offset_bytes, count_bytes));
119 }
120
122 void resize_impl(std::size_t size_bits) {
123 data_.resize(lines_for_bits(size_bits));
124 logical_size_bytes_ = bytes_for_bits(size_bits);
125 }
126
128 std::span<std::byte> writable_bytes_impl() {
129 return std::as_writable_bytes(std::span<CacheLine>(data_))
130 .first(logical_size_bytes_);
131 }
132
134 std::span<std::uint16_t> writable_words16_impl() {
135 return {reinterpret_cast<std::uint16_t*>(data_.data()),
136 logical_size_bytes_ / sizeof(std::uint16_t)};
137 }
138
140 std::span<std::uint64_t> writable_words64_impl() {
141 return {reinterpret_cast<std::uint64_t*>(data_.data()),
142 logical_size_bytes_ / sizeof(std::uint64_t)};
143 }
144
146 std::size_t allocated_bytes_impl() const {
147 return data_.capacity() * kAlignedStorageLineBytes;
148 }
149
151 void shrink_to_fit_impl() { data_.shrink_to_fit(); }
152
154 std::span<CacheLine> as_lines() { return data_; }
155
157 std::span<const CacheLine> as_lines() const { return data_; }
158
160 static AlignedStorage deserialize_impl(BinaryReader& reader) {
161 const std::size_t size = reader.read_size();
162 if (size > std::numeric_limits<std::size_t>::max() / 8) {
163 throw std::length_error("Serialized aligned storage is too large");
164 }
165 AlignedStorage result(size * 8);
166 const std::span<const std::byte> bytes = reader.read_bytes(size);
167 std::ranges::copy(bytes, result.writable_bytes().begin());
168 return result;
169 }
170
171 private:
172 static constexpr std::size_t bytes_for_bits(std::size_t size_bits) {
173 return size_bits / 8 + (size_bits % 8 != 0);
174 }
175
176 static constexpr std::size_t lines_for_bits(std::size_t size_bits) {
177 return lines_for_bytes(bytes_for_bits(size_bits));
178 }
179
180 static constexpr std::size_t lines_for_bytes(std::size_t size_bytes) {
181 return size_bytes / kAlignedStorageLineBytes +
182 (size_bytes % kAlignedStorageLineBytes != 0);
183 }
184
185 std::size_t logical_size_bytes_ = 0;
186 std::vector<CacheLine> data_;
187};
188
189} // namespace pixie
std::span< CacheLine > as_lines()
Return mutable cache-line blocks.
Definition aligned.h:154
std::size_t logical_size_bytes() const
Return the logical number of exposed bytes.
Definition aligned.h:74
static AlignedStorage deserialize_impl(BinaryReader &reader)
Restore an owning copy of one size-prefixed byte sequence.
Definition aligned.h:160
void shrink_to_fit_impl()
Request release of unused vector capacity.
Definition aligned.h:151
std::size_t padded_size_bytes() const
Return the cache-line-rounded backing size in bytes.
Definition aligned.h:77
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:157
std::size_t size_bytes_impl() const
Return the logical number of exposed bytes.
Definition aligned.h:65
void resize_impl(std::size_t size_bits)
Resize to hold at least size_bits bits.
Definition aligned.h:122
AlignedStorage(std::span< const std::uint64_t > words)
Copy complete 64-bit words into aligned owning storage.
Definition aligned.h:61
std::size_t allocated_bytes_impl() const
Return bytes reserved by the underlying vector.
Definition aligned.h:146
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:105
std::span< const std::byte > as_bytes_impl() const
Return the logical bytes as a read-only span.
Definition aligned.h:93
std::span< std::byte > writable_bytes_impl()
Return writable logical bytes.
Definition aligned.h:128
ReadOnlyStorageView view_impl(std::size_t offset_bytes, std::size_t count_bytes) const
Return a checked read-only byte subrange.
Definition aligned.h:111
std::span< std::uint64_t > writable_words64_impl()
Return writable logical storage as 64-bit words.
Definition aligned.h:140
ReadOnlyStorageView padded_view() const
Return a non-owning view of the complete cache-line backing.
Definition aligned.h:87
std::span< std::uint16_t > writable_words16_impl()
Return writable logical storage as 16-bit words.
Definition aligned.h:134
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:99
position_type end_position_impl() const
Return the position one past the final logical byte.
Definition aligned.h:71
AlignedStorage(std::span< const std::byte > bytes)
Copy bytes into aligned owning storage.
Definition aligned.h:54
position_type begin_position_impl() const
Return the first logical byte position.
Definition aligned.h:68
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::span< const std::byte > as_bytes() const
Definition storage.h:98
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