aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/actors/util/local_process_key.h
blob: 4d000db19809a72568007ff5420e92274901dce9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#pragma once

#include <util/string/builder.h>
#include <util/generic/strbuf.h>
#include <util/generic/vector.h>
#include <util/generic/hash.h>
#include <util/generic/singleton.h>
#include <util/generic/serialized_enum.h>

template <typename T>
class TLocalProcessKeyState {

template <typename U, const char* Name>
friend class TLocalProcessKey;
template <typename U, class TClass, ui32 KeyLengthLimit>
friend class TLocalProcessExtKey;
template <typename U, typename EnumT>
friend class TEnumProcessKey;

public:
    static TLocalProcessKeyState& GetInstance() {
        return *Singleton<TLocalProcessKeyState<T>>();
    }

    size_t GetCount() const {
        return StartIndex + Names.size();
    }

    TStringBuf GetNameByIndex(size_t index) const {
        if (index < StartIndex) {
            return StaticNames[index];
        } else {
            index -= StartIndex;
            Y_ENSURE(index < Names.size());
            return Names[index];
        }
    }

    size_t GetIndexByName(TStringBuf name) const {
        auto it = Map.find(name);
        Y_ENSURE(it != Map.end());
        return it->second;
    }

private:
    size_t Register(TStringBuf name) {
        auto x = Map.emplace(name, Names.size()+StartIndex);
        if (x.second) {
            Names.emplace_back(name);
        }

        return x.first->second;
    }

    size_t Register(TStringBuf name, ui32 index) {
        Y_VERIFY(index < StartIndex);
        auto x = Map.emplace(name, index);
        Y_VERIFY(x.second || x.first->second == index);
        StaticNames[index] = name;
        return x.first->second;
    }

private:
    static constexpr ui32 StartIndex = 2000;

    TVector<TString> FillStaticNames() {
        TVector<TString> staticNames;
        staticNames.reserve(StartIndex);
        for (ui32 i = 0; i < StartIndex; i++) {
            staticNames.push_back(TStringBuilder() << "Activity_" << i);
        }
        return staticNames;
    }

    TVector<TString> StaticNames = FillStaticNames();
    TVector<TString> Names;
    THashMap<TString, size_t> Map;
};

template <typename T, const char* Name>
class TLocalProcessKey {
public:
    static TStringBuf GetName() {
        return Name;
    }

    static size_t GetIndex() {
        return Index;
    }

private:
    inline static size_t Index = TLocalProcessKeyState<T>::GetInstance().Register(Name);
};

template <typename T, class TClass, ui32 KeyLengthLimit = 0>
class TLocalProcessExtKey {
public:
    static TStringBuf GetName() {
        return Name;
    }

    static size_t GetIndex() {
        return Index;
    }

private:

    static TString TypeNameRobust() {
        const TString className = TypeName<TClass>();
        if (KeyLengthLimit && className.size() > KeyLengthLimit) {
            return className.substr(0, KeyLengthLimit - 3) + "...";
        } else {
            return className;
        }
    }

    static const inline TString Name = TypeName<TClass>();
    inline static size_t Index = TLocalProcessKeyState<T>::GetInstance().Register(TypeNameRobust());
};

template <typename T, typename EnumT>
class TEnumProcessKey {
public:
    static TStringBuf GetName(EnumT key) {
        return TLocalProcessKeyState<T>::GetInstance().GetNameByIndex(GetIndex(key));
    }

    static size_t GetIndex(EnumT key) {
        ui32 index = static_cast<ui32>(key);
        if (index < TLocalProcessKeyState<T>::StartIndex) {
            return index;
        }
        Y_VERIFY(index < Enum2Index.size());
        return Enum2Index[index];
    }

private:
    inline static TVector<size_t> RegisterAll() {
        static_assert(std::is_enum<EnumT>::value, "Enum is required");

        TVector<size_t> enum2Index;
        auto names = GetEnumNames<EnumT>();
        ui32 maxId = 0;
        for (const auto& [k, v] : names) {
            maxId = Max(maxId, static_cast<ui32>(k));
        }
        enum2Index.resize(maxId+1);
        for (ui32 i = 0; i <= maxId && i < TLocalProcessKeyState<T>::StartIndex; i++) {
            enum2Index[i] = i;
        }

        for (const auto& [k, v] : names) {
            ui32 enumId = static_cast<ui32>(k);
            enum2Index[enumId] = TLocalProcessKeyState<T>::GetInstance().Register(v, enumId);
        }
        return enum2Index;
    }

    inline static TVector<size_t> Enum2Index = RegisterAll();
};