15class SegmentedVector {
22 SmallVector<T *> segments;
23 unsigned used_segments = 0;
24 std::allocator<T> allocator;
27 SegmentedVector() =
default;
30 deallocate_segments();
33 SegmentedVector(
const SegmentedVector &) =
delete;
35 SegmentedVector &operator=(
const SegmentedVector &) =
delete;
38 size_t size()
const {
return used_segments * SegmentSize - (end - cur); }
40 const T &operator[](
size_t idx)
const {
42 return segments[idx / SegmentSize][idx % SegmentSize];
45 T &operator[](
size_t idx) {
47 return segments[idx / SegmentSize][idx % SegmentSize];
51 if (used_segments == 0) {
52 assert(cur ==
nullptr && end ==
nullptr && segments.empty());
55 for (
unsigned i = 0; i < used_segments - 1; ++i) {
56 std::destroy(segments[i], segments[i] + SegmentSize);
57 util::poison_memory_region(segments[i], SegmentSize *
sizeof(T));
59 T *last_start = segments[used_segments - 1];
60 assert(last_start + SegmentSize == end);
61 assert(last_start <= cur && cur <= end);
62 std::destroy(last_start, cur);
63 util::poison_memory_region(last_start, SegmentSize *
sizeof(T));
67 end = segments[0] + SegmentSize;
70 void push_back(
const T &value) { std::construct_at(allocate(), value); }
72 void push_back(T &&value) { std::construct_at(allocate(), std::move(value)); }
74 template <
typename... Args>
75 T &emplace_back(Args &&...args) {
76 return *std::construct_at(allocate(), std::forward<Args>(args)...);
81 if (cur == end) [[unlikely]] {
84 util::unpoison_memory_region(cur,
sizeof(T));
90 if (used_segments == segments.size()) {
91 T *segment = allocator.allocate(SegmentSize);
92 util::poison_memory_region(segment, SegmentSize *
sizeof(T));
93 segments.push_back(segment);
95 cur = segments[used_segments++];
96 end = cur + SegmentSize;
99 void deallocate_segments() {
100 for (T *segment : segments) {
101 allocator.deallocate(segment, SegmentSize);