aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/codecs/tls_cache.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/codecs/tls_cache.h
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/codecs/tls_cache.h')
-rw-r--r--library/cpp/codecs/tls_cache.h100
1 files changed, 100 insertions, 0 deletions
diff --git a/library/cpp/codecs/tls_cache.h b/library/cpp/codecs/tls_cache.h
new file mode 100644
index 0000000000..0184e4bb6c
--- /dev/null
+++ b/library/cpp/codecs/tls_cache.h
@@ -0,0 +1,100 @@
+#pragma once
+
+#include <util/generic/buffer.h>
+#include <util/generic/deque.h>
+#include <util/generic/noncopyable.h>
+#include <util/generic/strbuf.h>
+#include <util/system/tls.h>
+#include <util/thread/singleton.h>
+
+namespace NCodecs {
+ template <class TItem>
+ struct TClear {
+ void operator()(TItem& item) const {
+ item.Clear();
+ }
+ };
+
+ template <class TItem, class TCleaner = TClear<TItem>>
+ class TTlsCache {
+ using TSelf = TTlsCache<TItem, TCleaner>;
+
+ struct TItemHolder: public TIntrusiveListItem<TItemHolder> {
+ 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<TSelf>();
+ }
+
+ 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<TItemHolder, TDelete> Free;
+ TCleaner Cleaner;
+ };
+
+ using TBufferTlsCache = TTlsCache<TBuffer>;
+}