22 SmallVector<T *> segments;
23 unsigned used_segments = 0;
24 std::allocator<T> allocator;
30 deallocate_segments();
38 size_t size() const noexcept {
39 return used_segments * SegmentSize - (end - cur);
42 const T &operator[](
size_t idx)
const noexcept {
44 return segments[idx / SegmentSize][idx % SegmentSize];
47 T &operator[](
size_t idx)
noexcept {
49 return segments[idx / SegmentSize][idx % SegmentSize];
52 void clear() noexcept {
53 if (used_segments == 0) {
54 assert(cur ==
nullptr && end ==
nullptr && segments.empty());
57 for (
unsigned i = 0; i < used_segments - 1; ++i) {
58 std::destroy(segments[i], segments[i] + SegmentSize);
59 util::poison_memory_region(segments[i], SegmentSize *
sizeof(T));
61 T *last_start = segments[used_segments - 1];
62 assert(last_start + SegmentSize == end);
63 assert(last_start <= cur && cur <= end);
64 std::destroy(last_start, cur);
65 util::poison_memory_region(last_start, SegmentSize *
sizeof(T));
69 end = segments[0] + SegmentSize;
72 void push_back(
const T &value)
noexcept {
73 std::construct_at(allocate(), value);
76 void push_back(T &&value)
noexcept {
77 std::construct_at(allocate(), std::move(value));
80 template <
typename... Args>
81 T &emplace_back(Args &&...args)
noexcept {
82 return *std::construct_at(allocate(), std::forward<Args>(args)...);
86 T *allocate() noexcept {
87 if (cur == end) [[unlikely]] {
90 util::unpoison_memory_region(cur,
sizeof(T));
94 void next_segment() noexcept {
96 if (used_segments == segments.size()) {
97 T *segment = allocator.allocate(SegmentSize);
98 util::poison_memory_region(segment, SegmentSize *
sizeof(T));
99 segments.push_back(segment);
101 cur = segments[used_segments++];
102 end = cur + SegmentSize;
105 void deallocate_segments() noexcept {
106 for (T *segment : segments) {
107 allocator.deallocate(segment, SegmentSize);