1
+ #pragma once
2
+ #include < cstddef>
3
+ #include < memory>
4
+ #include < string>
5
+ #include < unordered_map>
6
+
7
+ namespace sd
8
+ {
9
+
10
+ struct ICacheItem
11
+ {
12
+ virtual const std::string &GetKey () const = 0;
13
+ virtual const void *GetValue () const = 0;
14
+
15
+ virtual ~ICacheItem (){};
16
+ };
17
+
18
+ template <class TValue > class CacheItem final : public ICacheItem
19
+ {
20
+ private:
21
+ std::string _key;
22
+ TValue _value;
23
+
24
+ public:
25
+ using Ptr = std::unique_ptr<CacheItem<TValue>>;
26
+
27
+ static Ptr Make (const std::string &key, TValue &&value)
28
+ {
29
+ return Ptr (new CacheItem<TValue>(key, std::move (value)));
30
+ }
31
+
32
+ CacheItem (const std::string &key, TValue &&value) : _key(key), _value(value) {}
33
+
34
+ const std::string &GetKey () const final { return _key; }
35
+ const void *GetValue () const final { return &GetTypedValue (); }
36
+ const TValue &GetTypedValue () const { return _value; }
37
+ };
38
+
39
+ struct ICachePolicy
40
+ {
41
+ virtual void CallOnRemove (const void *value) const = 0;
42
+ virtual void CallOnUpdate (const void *oldValue, const void *newValue) const = 0;
43
+
44
+ virtual ~ICachePolicy () {}
45
+ };
46
+
47
+ template <class TValue > class CachePolicy final : public ICachePolicy
48
+ {
49
+ public:
50
+ using UpdateCallback = std::function<void (const TValue *, const TValue *)>;
51
+ using RemoveCallback = std::function<void (const TValue *)>;
52
+
53
+ private:
54
+ UpdateCallback _updateCallback;
55
+ RemoveCallback _removeCallback;
56
+
57
+ public:
58
+ std::unique_ptr<CachePolicy<TValue>> static Make (UpdateCallback updateCallback = nullptr ,
59
+ RemoveCallback removeCallback = nullptr )
60
+ {
61
+ return std::unique_ptr<CachePolicy<TValue>>(new CachePolicy<TValue>(updateCallback, removeCallback));
62
+ }
63
+
64
+ CachePolicy (UpdateCallback updateCallback = nullptr , RemoveCallback removeCallback = nullptr )
65
+ : _updateCallback(updateCallback), _removeCallback(removeCallback)
66
+ {
67
+ }
68
+
69
+ void SetOnUpdateCallback (UpdateCallback updateCallback) { _updateCallback = updateCallback; }
70
+
71
+ void SetOnRemoveCallback (RemoveCallback removeCallback) { _removeCallback = removeCallback; }
72
+
73
+ void CallOnRemove (const void *value) const final
74
+ {
75
+ if (_removeCallback)
76
+ {
77
+ _removeCallback (static_cast <const TValue *>(value));
78
+ }
79
+ }
80
+
81
+ void CallOnUpdate (const void *oldValue, const void *newValue) const final
82
+ {
83
+ if (_updateCallback)
84
+ {
85
+ _updateCallback (static_cast <const TValue *>(oldValue), static_cast <const TValue *>(newValue));
86
+ }
87
+ }
88
+ };
89
+
90
+ struct ICache
91
+ {
92
+ virtual bool Add (std::unique_ptr<ICacheItem> itemPtr, std::unique_ptr<ICachePolicy> policy = nullptr ) = 0;
93
+
94
+ virtual bool Set (std::unique_ptr<ICacheItem> itemPtr, std::unique_ptr<ICachePolicy> policy = nullptr ) = 0;
95
+
96
+ virtual const void *AddOrGetExisting (std::unique_ptr<ICacheItem> itemPtr,
97
+ std::unique_ptr<ICachePolicy> policy = nullptr ) = 0;
98
+
99
+ virtual const void *Get (const std::string &key) const = 0;
100
+
101
+ virtual bool Remove (const std::string &key) = 0;
102
+
103
+ virtual bool Contains (const std::string &key) const = 0;
104
+
105
+ virtual size_t Count () const = 0;
106
+
107
+ virtual ~ICache () {}
108
+ };
109
+
110
+ class Cache final : public ICache
111
+ {
112
+ private:
113
+ struct Data
114
+ {
115
+ std::unique_ptr<ICacheItem> item;
116
+ std::unique_ptr<ICachePolicy> policy;
117
+ };
118
+
119
+ std::unordered_map<std::string, Data> _items;
120
+
121
+ public:
122
+ template <class TValue >
123
+ bool Add (const std::string &key, TValue &&value, std::unique_ptr<CachePolicy<TValue>> policy = nullptr )
124
+ {
125
+ return Add (CacheItem<TValue>::Make (key, std::move (value)), std::move (policy));
126
+ }
127
+
128
+ bool Add (std::unique_ptr<ICacheItem> itemPtr, std::unique_ptr<ICachePolicy> policy = nullptr ) final ;
129
+
130
+ template <class TValue >
131
+ const TValue *AddOrGetExisting (const std::string &key, TValue &&value,
132
+ std::unique_ptr<CachePolicy<TValue>> policy = nullptr )
133
+ {
134
+ return AddOrGetExisting (CacheItem<TValue>::Make (key, std::move (value)), std::move (policy));
135
+ }
136
+
137
+ template <class TValue >
138
+ const TValue *AddOrGetExisting (std::unique_ptr<CacheItem<TValue>> itemPtr,
139
+ std::unique_ptr<CachePolicy<TValue>> policy = nullptr )
140
+ {
141
+ return static_cast <const TValue *>(AddOrGetExisting (std::move (itemPtr), std::move (policy)));
142
+ }
143
+
144
+ const void *AddOrGetExisting (std::unique_ptr<ICacheItem> itemPtr,
145
+ std::unique_ptr<ICachePolicy> policy = nullptr ) final ;
146
+
147
+ template <class TValue >
148
+ bool Set (const std::string &key, TValue &&value, std::unique_ptr<CachePolicy<TValue>> policy = nullptr )
149
+ {
150
+ return Set (CacheItem<TValue>::Make (key, std::move (value)), std::move (policy));
151
+ }
152
+
153
+ template <class TValue >
154
+ bool Set (std::unique_ptr<CacheItem<TValue>> itemPtr, std::unique_ptr<CachePolicy<TValue>> policy = nullptr )
155
+ {
156
+ return Set (std::move (itemPtr), std::move (policy));
157
+ }
158
+
159
+ bool Set (std::unique_ptr<ICacheItem> itemPtr, std::unique_ptr<ICachePolicy> policy = nullptr ) final ;
160
+
161
+ template <class TValue > const TValue *Get (const std::string &key) const
162
+ {
163
+ return static_cast <const TValue *>(Get (key));
164
+ }
165
+
166
+ const void *Get (const std::string &key) const final ;
167
+
168
+ bool Remove (const std::string &key) final ;
169
+
170
+ bool Contains (const std::string &key) const final ;
171
+
172
+ size_t Count () const final ;
173
+
174
+ private:
175
+ bool AddData (Data data);
176
+
177
+ Data *GetEditableData (const std::string &key);
178
+
179
+ const Data *GetData (const std::string &key) const ;
180
+
181
+ std::optional<Cache::Data> RemoveData (const std::string &key);
182
+
183
+ bool ContainsData (const std::string &key) const ;
184
+
185
+ size_t CountData () const ;
186
+ };
187
+ } // namespace sd
0 commit comments