#pragma once #include #include #include #include #include #include #include #include class TLocalProcessKeyStateIndexLimiter { public: static constexpr ui32 GetMaxKeysCount() { return 10000; } }; template class TLocalProcessKeyStateIndexConstructor { public: }; template class TLocalProcessKeyState { template friend class TLocalProcessKey; template friend class TLocalProcessExtKey; template friend class TEnumProcessKey; public: static TLocalProcessKeyState& GetInstance() { return *Singleton>(); } ui32 GetCount() const { return MaxKeysCount; } TStringBuf GetNameByIndex(size_t index) const { Y_VERIFY(index < Names.size()); return Names[index]; } size_t GetIndexByName(TStringBuf name) const { TGuard g(Mutex); auto it = Map.find(name); Y_ENSURE(it != Map.end()); return it->second; } TLocalProcessKeyState() { Names.resize(MaxKeysCount); } size_t Register(TStringBuf name) { TGuard g(Mutex); auto it = Map.find(name); if (it != Map.end()) { return it->second; } const ui32 index = TLocalProcessKeyStateIndexConstructor::BuildCurrentIndex(name, Names.size()); auto x = Map.emplace(name, index); if (x.second) { Y_VERIFY(index < Names.size(), "a lot of actors or tags for memory monitoring"); Names[index] = name; } return x.first->second; } private: static constexpr ui32 MaxKeysCount = TLocalProcessKeyStateIndexLimiter::GetMaxKeysCount(); private: TVector Names; THashMap Map; TMutex Mutex; }; template class TLocalProcessKey { public: static TStringBuf GetName() { return Name; } static size_t GetIndex() { return Index; } private: inline static size_t Index = TLocalProcessKeyState::GetInstance().Register(Name); }; template class TLocalProcessExtKey { public: static TStringBuf GetName() { return Name; } static size_t GetIndex() { return Index; } private: static TString TypeNameRobust() { const TString className = TypeName(); if (KeyLengthLimit && className.size() > KeyLengthLimit) { return className.substr(0, KeyLengthLimit - 3) + "..."; } else { return className; } } static const inline TString Name = TypeName(); inline static size_t Index = TLocalProcessKeyState::GetInstance().Register(TypeNameRobust()); }; template class TEnumProcessKey { public: static TStringBuf GetName(const EnumT key) { return TLocalProcessKeyState::GetInstance().GetNameByIndex(GetIndex(key)); } static size_t GetIndex(const EnumT key) { ui32 index = static_cast(key); Y_VERIFY(index < Enum2Index.size()); return Enum2Index[index]; } private: inline static TVector RegisterAll() { static_assert(std::is_enum::value, "Enum is required"); TVector enum2Index; auto names = GetEnumNames(); ui32 maxId = 0; for (const auto& [k, v] : names) { maxId = Max(maxId, static_cast(k)); } enum2Index.resize(maxId + 1); for (const auto& [k, v] : names) { ui32 enumId = static_cast(k); enum2Index[enumId] = TLocalProcessKeyState::GetInstance().Register(v); } return enum2Index; } inline static TVector Enum2Index = RegisterAll(); };