4#include "../Common/CompilerMacrosLifetimeBound.h"
5#include "../Common/CompilerMinMax.h"
6#include "../Common/Span.h"
7#include "../Memory/Memory.h"
16enum class SegmentAllocator
24struct SC_MEMORY_EXPORT SegmentHeader;
25struct alignas(uint64_t) SegmentHeader
27 static constexpr uint32_t MaxCapacity = (~static_cast<uint32_t>(0)) >> 1;
29 SegmentHeader(uint32_t capacity = 0, SegmentAllocator allocator = SegmentAllocator::Global)
32 allocatorType =
static_cast<uint32_t
>(allocator);
33 capacityBytes = capacity;
34 hasInlineData = capacity > 0;
36 uint32_t sizeBytes :
sizeof(uint32_t) * 8 - 1;
37 uint32_t allocatorType : 1;
38 uint32_t capacityBytes :
sizeof(uint32_t) * 8 - 1;
39 uint32_t hasInlineData : 1;
42struct SC_MEMORY_EXPORT SegmentHeaderOffset
44 using PtrOffset = size_t;
50inline zexact_ptrtable* filcExactPtrTable() noexcept
52 static zexact_ptrtable* table = zexact_ptrtable_new();
57inline T* filcResolveRelativePointer(
const void* self,
size_t address)
noexcept
59 const size_t lower =
reinterpret_cast<size_t>(zgetlower(
const_cast<void*
>(self)));
60 const size_t upper =
reinterpret_cast<size_t>(zgetupper(
const_cast<void*
>(self)));
61 if (address >= lower and address < upper)
62 return static_cast<T*
>(zmkptr(
const_cast<void*
>(self),
static_cast<unsigned long>(address)));
63 return static_cast<T*
>(zexact_ptrtable_decode(filcExactPtrTable(), address));
68struct SC_MEMORY_EXPORT SegmentSelfRelativePointer :
protected SegmentHeaderOffset
71 SC_COMPILER_FORCE_INLINE T* data() noexcept
76 const auto address = toOffset(
this) + offset;
77 if (header.hasInlineData and offset == inlineDataOffset())
78 return static_cast<T*
>(zmkptr(
this,
static_cast<unsigned long>(address)));
79 return filcResolveRelativePointer<T>(
this, address);
81 return offset == 0 ? nullptr : toPtr(toOffset(
this) + offset);
84 SC_COMPILER_FORCE_INLINE
const T* data() const noexcept
89 const auto address = toOffset(
this) + offset;
90 if (header.hasInlineData and offset == inlineDataOffset())
91 return static_cast<const T*
>(zmkptr(
const_cast<SegmentSelfRelativePointer*
>(
this),
static_cast<unsigned long>(address)));
92 return filcResolveRelativePointer<const T>(
this, address);
94 return offset == 0 ? nullptr : toPtr(toOffset(
this) + offset);
97 SC_COMPILER_FORCE_INLINE
bool isInline() const noexcept {
return (offset == inlineDataOffset()) and header.hasInlineData; }
100 struct InlineData :
public SegmentHeaderOffset
109 SC_COMPILER_FORCE_INLINE
static constexpr PtrOffset inlineDataOffset() noexcept {
return sizeof(SegmentHeaderOffset) +
sizeof(uint64_t); }
110 SC_COMPILER_FORCE_INLINE
static auto toOffset(
const volatile void* src)
noexcept {
return reinterpret_cast<PtrOffset
>(src); }
111 SC_COMPILER_FORCE_INLINE
static T* toPtr(PtrOffset src)
noexcept {
return reinterpret_cast<T*
>(src); }
112 SC_COMPILER_FORCE_INLINE
void setData(T* mem)
noexcept
114 offset = mem ==
nullptr ? 0 : toOffset(mem) - toOffset(
this);
116 if (mem !=
nullptr and not (header.hasInlineData and mem == getInlineData()))
117 (void)zexact_ptrtable_encode(filcExactPtrTable(), mem);
120 SC_COMPILER_FORCE_INLINE T* getInlineData() noexcept {
return (T*)
reinterpret_cast<volatile InlineData*
>(
this)->data; }
121 SC_COMPILER_FORCE_INLINE
auto getInlineCapacity() noexcept {
return reinterpret_cast<volatile InlineData*
>(
this)->capacity; }
127struct SC_MEMORY_EXPORT SegmentTrivial
130 inline static void destruct(Span<T> data)
noexcept;
132 template <
typename U>
inline static void copyConstructAs(Span<T> data, Span<const U> value)
noexcept;
133 template <
typename U>
inline static void copyConstruct(Span<T> data,
const U* src)
noexcept;
134 template <
typename U>
inline static void copyAssign(Span<T> data,
const U* src)
noexcept;
135 template <
typename U>
inline static void copyInsert(Span<T> data, Span<const U> values)
noexcept;
136 template <
typename U>
inline static void moveConstruct(Span<T> data, U* src)
noexcept;
137 template <
typename U>
inline static void moveAssign(Span<T> data, U* src)
noexcept;
139 inline static void remove(Span<T> data,
size_t numElements)
noexcept;
143template <
typename ParentSegment,
typename CommonParent,
int N = 0,
144 SegmentAllocator Allocator = SegmentAllocator::ThreadLocal>
145struct SC_MEMORY_EXPORT SegmentCustom :
public ParentSegment
147 SegmentCustom() : ParentSegment(N, Allocator) {}
148 SegmentCustom(
const CommonParent& other) : SegmentCustom() { CommonParent::operator=(other); }
149 SegmentCustom(CommonParent&& other) : SegmentCustom() { CommonParent::operator=(move(other)); }
151 SegmentCustom(
const SegmentCustom& other) : SegmentCustom() { ParentSegment::operator=(other); }
152 SegmentCustom(SegmentCustom&& other) : SegmentCustom() { ParentSegment::operator=(move(other)); }
154 SegmentCustom& operator=(
const SegmentCustom& other) { ParentSegment::operator=(other);
return *
this; }
155 SegmentCustom& operator=(SegmentCustom&& other) { ParentSegment::operator=(move(other));
return *
this; }
166template <
typename VTable>
167struct SC_MEMORY_EXPORT
Segment :
public VTable
170 using T =
typename VTable::Type;
171 Segment(uint32_t capacityInBytes, SegmentAllocator allocator = SegmentAllocator::Global)
noexcept;
181 template <
typename U = T>
Segment(Span<const U> span) noexcept :
Segment() { SC_MEMORY_ASSERT_RELEASE(assign(span)); }
183 Segment(std::initializer_list<T> list)
noexcept;
190 [[nodiscard]]
bool resize(
size_t newSize,
const T& value = T()) noexcept;
193 [[nodiscard]]
bool reserve(
size_t capacity) noexcept;
196 template <typename U = T>
197 [[nodiscard]]
bool append(Span<const U> span) noexcept;
200 template <typename VTable2>
201 [[nodiscard]]
bool appendMove(
Segment<VTable2>&& other) noexcept;
205 [[nodiscard]]
bool shrink_to_fit() noexcept;
208 void clear() noexcept;
212 template <typename U = T>
213 [[nodiscard]]
bool assign(Span<const U> span) noexcept;
217 template <typename VTable2>
218 [[nodiscard]]
bool assignMove(
Segment<VTable2>&& other) noexcept;
221 [[nodiscard]]
bool push_back(const T& value) noexcept {
return resize(size() + 1, value); }
227 [[nodiscard]]
bool push_front(
const T& value)
noexcept {
return insert(0, value); }
232 [[nodiscard]]
bool pop_back(T* removedValue =
nullptr) noexcept;
237 [[nodiscard]]
bool pop_front(T* removedValue =
nullptr) noexcept;
240 [[nodiscard]] T* begin() noexcept SC_LANGUAGE_LIFETIME_BOUND {
return data(); }
241 [[nodiscard]]
const T* begin() const noexcept SC_LANGUAGE_LIFETIME_BOUND {
return data(); }
242 [[nodiscard]] T* end() noexcept SC_LANGUAGE_LIFETIME_BOUND {
return data() + size(); }
243 [[nodiscard]]
const T* end() const noexcept SC_LANGUAGE_LIFETIME_BOUND {
return data() + size(); }
245 [[nodiscard]] T& back() noexcept SC_LANGUAGE_LIFETIME_BOUND { SC_MEMORY_ASSERT_RELEASE(not isEmpty());
return *(data() + size() - 1);}
246 [[nodiscard]] T& front() noexcept SC_LANGUAGE_LIFETIME_BOUND { SC_MEMORY_ASSERT_RELEASE(not isEmpty());
return *data();}
247 [[nodiscard]]
const T& back() const noexcept SC_LANGUAGE_LIFETIME_BOUND { SC_MEMORY_ASSERT_RELEASE(not isEmpty());
return *(data() + size() - 1);}
248 [[nodiscard]]
const T& front() const noexcept SC_LANGUAGE_LIFETIME_BOUND { SC_MEMORY_ASSERT_RELEASE(not isEmpty());
return *data();}
250 [[nodiscard]] T& operator[](
size_t idx)
noexcept SC_LANGUAGE_LIFETIME_BOUND { SC_MEMORY_ASSERT_DEBUG(idx < size());
return *(data() + idx);}
251 [[nodiscard]]
const T& operator[](
size_t idx)
const noexcept SC_LANGUAGE_LIFETIME_BOUND { SC_MEMORY_ASSERT_DEBUG(idx < size());
return *(data() + idx);}
255 [[nodiscard]]
bool isEmpty() const noexcept {
return VTable::header.sizeBytes == 0; }
258 [[nodiscard]] Span<T>
toSpan() noexcept SC_LANGUAGE_LIFETIME_BOUND {
return {data(), size()}; }
261 [[nodiscard]] Span<const T>
toSpanConst() const noexcept SC_LANGUAGE_LIFETIME_BOUND {
return {data(), size()}; }
264 [[nodiscard]]
size_t size() const noexcept {
return VTable::header.sizeBytes /
sizeof(T); }
267 [[nodiscard]]
size_t capacity() const noexcept {
return VTable::header.capacityBytes /
sizeof(T); }
273 [[nodiscard]]
bool removeRange(
size_t start,
size_t length)
noexcept;
278 [[nodiscard]]
bool removeAt(
size_t index)
noexcept {
return removeRange(index, 1); }
284 [[nodiscard]]
bool insert(
size_t index, Span<const T> data)
noexcept;
287 template <
typename VTable2>
A slice of contiguous memory, prefixed by and header containing size and capacity.
Definition Segment.h:168
size_t size() const noexcept
Returns current size.
Definition Segment.h:264
bool resize(size_t newSize, const T &value=T()) noexcept
Re-allocates to the requested new size, preserving its contents and setting new items to value.
size_t capacity() const noexcept
Returns current capacity (always >= of size())
Definition Segment.h:267
Span< T > toSpan() noexcept SC_LANGUAGE_LIFETIME_BOUND
Obtains a Span of internal contents.
Definition Segment.h:258
bool isEmpty() const noexcept
Check if is empty (size() == 0)
Definition Segment.h:255
bool removeRange(size_t start, size_t length) noexcept
Removes the range [start, start + length] from the segment.
bool push_front(const T &value) noexcept
Appends a single element to the start of the segment.
Definition Segment.h:227
bool removeAt(size_t index) noexcept
Removes the element at index.
Definition Segment.h:278
bool pop_back(T *removedValue=nullptr) noexcept
Removes the last element of the segment.
bool push_back(T &&value) noexcept
Moves a single element to the end of the segment.
bool insert(size_t index, Span< const T > data) noexcept
Insert a span at the given index.
bool resizeWithoutInitializing(size_t newSize) noexcept
Re-allocates to the requested new size, preserving its contents.
Span< const T > toSpanConst() const noexcept SC_LANGUAGE_LIFETIME_BOUND
Obtains a Span of internal contents.
Definition Segment.h:261