#pragma once #include #include #include #include #include #include namespace NCodecs { template struct TClear { void operator()(TItem& item) const { item.Clear(); } }; template > class TTlsCache { using TSelf = TTlsCache; struct TItemHolder: public TIntrusiveListItem { TItemHolder(TSelf& factory) : Factory(factory) { } void Release() { Factory.Release(*this); } TSelf& Factory; TItem Item; }; class TItemGuard { public: explicit TItemGuard(TSelf& fact) : Holder(fact.Acquire()) { } TItemGuard(TItemGuard&& other) noexcept { *this = std::move(other); } TItemGuard& operator=(TItemGuard&& other) noexcept { if (&other != this) { std::swap(Holder, other.Holder); } return *this; } ~TItemGuard() { if (Holder) { Holder->Release(); } } TItem& Get() & { Y_ASSERT(Holder); return Holder->Item; } TItem& Get() && = delete; private: TItemHolder* Holder = nullptr; }; public: TItemGuard Item() { return TItemGuard(*this); } static TSelf& TlsInstance() { return *FastTlsSingleton(); } private: TItemHolder* Acquire() { if (Free.Empty()) { return new TItemHolder(*this); } else { return Free.PopBack(); } } void Release(TItemHolder& item) { Cleaner(item.Item); Free.PushBack(&item); } private: TIntrusiveListWithAutoDelete Free; TCleaner Cleaner; }; using TBufferTlsCache = TTlsCache; }