14 alignas(T)::std::byte mData[
sizeof(T)];
16 [[nodiscard]] T* value()
noexcept { return ::std::launder(
reinterpret_cast<T*
>(mData)); }
20 using ItemAllocator = typename ::std::allocator_traits<Alloc>::template rebind_alloc<Item>;
21 using ItemTraits = ::std::allocator_traits<ItemAllocator>;
25 friend InstancedThreadLocal;
27 typename ItemList::iterator mIterator;
29 explicit IteratorType(
typename ItemList::iterator iterator) noexcept : mIterator(iterator) {}
32 [[nodiscard]] T& operator*()
const noexcept {
return *mIterator->value(); }
33 [[nodiscard]] T* operator->()
const noexcept {
return mIterator->value(); }
35 IteratorType& operator++()
noexcept {
40 [[nodiscard]]
bool operator==(IteratorType
const&)
const noexcept =
default;
43 InstancedThreadLocal() : mConstructor([](T* value) { ::std::construct_at(value); }) {}
45 explicit InstancedThreadLocal(::std::function<
void(T*)> constructor) : mConstructor(::
std::move(constructor)) {}
47 InstancedThreadLocal(InstancedThreadLocal
const&) =
delete;
48 InstancedThreadLocal& operator=(InstancedThreadLocal
const&) =
delete;
50 ~InstancedThreadLocal() { destroyItems(); }
52 [[nodiscard]] T& operator*() {
return *load(); }
53 [[nodiscard]] T* operator->() {
return load(); }
60 if (
auto item =
static_cast<Item*
>(mKey.getValue())) {
63 ItemAllocator allocator;
64 Item* item = ItemTraits::allocate(allocator, 1);
65 ::std::construct_at(item);
66 mConstructor(item->value());
68 ::std::lock_guard lock{mMutex};
69 mItems.push_back(*item);
74 ItemAllocator allocator;
75 ::std::lock_guard lock{mMutex};
76 while (!mItems.empty()) {
77 Item& item = mItems.front();
78 ::std::destroy_at(item.value());
79 ::std::destroy_at(&item);
80 ItemTraits::deallocate(allocator, &item, 1);
84 ::std::function<void(T*)> mConstructor;
85 mutable ItemList mItems;
87 ::Bedrock::Threading::TlsSlot mKey;