12#include <unordered_map>
16template<
typename T,
typename U>
17void memswap(T &dst, U &src)
19 static_assert(
sizeof(T) ==
sizeof(U),
"memswap requires both objects of equal size");
20 std::byte tmp[
sizeof(T)];
21 memcpy(tmp, &src,
sizeof(T));
22 memcpy(&src, &dst,
sizeof(U));
23 memcpy(&dst, tmp,
sizeof(T));
36template<
typename InputIt,
typename T>
37T *placement_copy(InputIt src, T *dst)
39 tt_axiom(dst !=
nullptr);
40 return new (dst) T(*src);
47template<
typename InputIt,
typename T>
48void placement_copy(InputIt src_first, InputIt src_last, T *dst_first)
50 tt_axiom(src_first != dst_first);
51 tt_axiom(src_last >= src_first);
55 while (src != src_last) {
56 placement_copy(src++, dst++);
74T *placement_move(T *src, T *dst)
76 tt_axiom(src !=
nullptr);
77 tt_axiom(dst !=
nullptr);
94void placement_move_within_array(T *src_first, T *src_last, T *dst_first)
96 tt_axiom(src_last >= src_first);
98 if (src_first < dst_first) {
99 auto dst_last = dst_first + (src_last - src_first);
103 while (src != src_first) {
104 placement_move(--src, --dst);
107 }
else if (src_first > dst_first) {
108 auto src = src_first;
109 auto dst = dst_first;
110 while (src != src_last) {
111 placement_move(src++, dst++);
128void placement_move(T *src, T *src_last, T *dst)
130 tt_axiom(src_last >= src);
132 while (src != src_last) {
133 placement_move(src++, dst++);
140constexpr bool is_aligned(T *p)
150template<std::
unsigned_
integral T>
151constexpr T
floor(T value, T alignment)
noexcept
153 return (value / alignment) * alignment;
161template<std::
unsigned_
integral T>
162constexpr T
ceil(T value, T alignment)
noexcept
164 return floor(value + (alignment - 1), alignment);
168constexpr T *
ceil(T *ptr,
size_t alignment)
noexcept
170 ttlet aligned_byte_offset =
ceil(
reinterpret_cast<uintptr_t
>(ptr),
static_cast<uintptr_t
>(alignment));
171 return reinterpret_cast<T *
>(aligned_byte_offset);
175constexpr T *
floor(T *ptr,
size_t alignment)
noexcept
177 ttlet aligned_byte_offset =
floor(
reinterpret_cast<uintptr_t
>(ptr),
static_cast<uintptr_t
>(alignment));
178 return reinterpret_cast<T *
>(aligned_byte_offset);
185 while (i != v.end()) {
194template<
typename K,
typename T>
198 while (i != v.end()) {
199 if (i->second.expired()) {
207template<
typename K,
typename T>
211 while (i != v.end()) {
212 cleanupWeakPointers(i->second);
213 if (i->second.size() == 0) {
221template<
typename Value,
typename Map,
typename Key,
typename... Args>
226 ttlet i = map.find(key);
227 if (i == map.end()) {
228 value = std::make_shared<Value>(std::forward<Args>(args)...);
229 map.insert_or_assign(key, value);
246inline uint64_t ptr_to_uint48(
auto *ptr)
noexcept
248 tt_axiom(
static_cast<uint64_t
>(ptr) % 16 == 0);
250 if constexpr (Processor::current == Processor::x64) {
253 (
static_cast<uint64_t
>(ptr) & 0xffff'8000'0000'0000) == 0 ||
254 (
static_cast<uint64_t
>(ptr) & 0xffff'8000'0000'0000) == 0xffff'8000'0000'0000);
255 return (
static_cast<uint64_t
>(ptr) << 16) >> 16;
257 }
else if constexpr (Processor::current == Processor::ARM) {
260 (
static_cast<uint64_t
>(ptr) & 0x00ff'8000'0000'0000) == 0 ||
261 (
static_cast<uint64_t
>(ptr) & 0x00ff'8000'0000'0000) == 0x00ff'8000'0000'0000);
264 auto u64 = (
static_cast<uint64_t
>(ptr) << 12) >> 16;
267 auto key = (
static_cast<uint64_t
>(ptr) >> 56) << 44;
273 tt_static_no_default();
288T *uint48_to_ptr(uint64_t x)
noexcept
290 tt_axiom((x >> 48) == 0);
292 if constexpr (Processor::current == Processor::x64) {
294 auto i64 = (
static_cast<int64_t
>(x) << 16) >> 16;
295 return reinterpret_cast<T *
>(i64);
297 }
else if constexpr (Processor::current == Processor::ARM) {
299 auto key = (
static_cast<uint64_t
>(x) >> 44) << 56;
302 auto i64 = (
static_cast<int64_t
>(x) << 20) >> 16;
305 return reinterpret_cast<T *
>(key ^
static_cast<uint64_t
>(i64));
308 tt_static_no_default();