tls_cache.h 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #pragma once
  2. #include <util/generic/buffer.h>
  3. #include <util/generic/deque.h>
  4. #include <util/generic/noncopyable.h>
  5. #include <util/generic/strbuf.h>
  6. #include <util/system/tls.h>
  7. #include <util/thread/singleton.h>
  8. namespace NCodecs {
  9. template <class TItem>
  10. struct TClear {
  11. void operator()(TItem& item) const {
  12. item.Clear();
  13. }
  14. };
  15. template <class TItem, class TCleaner = TClear<TItem>>
  16. class TTlsCache {
  17. using TSelf = TTlsCache<TItem, TCleaner>;
  18. struct TItemHolder: public TIntrusiveListItem<TItemHolder> {
  19. TItemHolder(TSelf& factory)
  20. : Factory(factory)
  21. {
  22. }
  23. void Release() {
  24. Factory.Release(*this);
  25. }
  26. TSelf& Factory;
  27. TItem Item;
  28. };
  29. class TItemGuard {
  30. public:
  31. explicit TItemGuard(TSelf& fact)
  32. : Holder(fact.Acquire())
  33. {
  34. }
  35. TItemGuard(TItemGuard&& other) noexcept {
  36. *this = std::move(other);
  37. }
  38. TItemGuard& operator=(TItemGuard&& other) noexcept {
  39. if (&other != this) {
  40. std::swap(Holder, other.Holder);
  41. }
  42. return *this;
  43. }
  44. ~TItemGuard() {
  45. if (Holder) {
  46. Holder->Release();
  47. }
  48. }
  49. TItem& Get() & {
  50. Y_ASSERT(Holder);
  51. return Holder->Item;
  52. }
  53. TItem& Get() && = delete;
  54. private:
  55. TItemHolder* Holder = nullptr;
  56. };
  57. public:
  58. TItemGuard Item() {
  59. return TItemGuard(*this);
  60. }
  61. static TSelf& TlsInstance() {
  62. return *FastTlsSingleton<TSelf>();
  63. }
  64. private:
  65. TItemHolder* Acquire() {
  66. if (Free.Empty()) {
  67. return new TItemHolder(*this);
  68. } else {
  69. return Free.PopBack();
  70. }
  71. }
  72. void Release(TItemHolder& item) {
  73. Cleaner(item.Item);
  74. Free.PushBack(&item);
  75. }
  76. private:
  77. TIntrusiveListWithAutoDelete<TItemHolder, TDelete> Free;
  78. TCleaner Cleaner;
  79. };
  80. using TBufferTlsCache = TTlsCache<TBuffer>;
  81. }