Skip to content

Commit c48cfba

Browse files
committed
add cache class
1 parent fc1ba7a commit c48cfba

File tree

6 files changed

+449
-6
lines changed

6 files changed

+449
-6
lines changed

Source/Library/CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
#file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS *.cpp)
1+
# file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS *.cpp)
22

3-
add_library(SandboxLib
3+
add_library(SandboxLib
44
LinkedList.cpp
55
Map.cpp
6+
Cache.cpp
67
MemoryManager.cpp
78
DependencyInjector.cpp
89
)

Source/Library/Cache.cpp

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#include "Cache.hpp"
2+
#include <optional>
3+
4+
namespace sd
5+
{
6+
bool Cache::Add(std::unique_ptr<ICacheItem> itemPtr, std::unique_ptr<ICachePolicy> policy)
7+
{
8+
if (!itemPtr)
9+
{
10+
return false;
11+
}
12+
return AddData({.item = std::move(itemPtr), .policy = std::move(policy)});
13+
}
14+
15+
const void *Cache::AddOrGetExisting(std::unique_ptr<ICacheItem> itemPtr, std::unique_ptr<ICachePolicy> policy)
16+
{
17+
if (!itemPtr)
18+
{
19+
return nullptr;
20+
}
21+
if (auto value = Get(itemPtr->GetKey()))
22+
{
23+
return value;
24+
}
25+
Add(std::move(itemPtr), std::move(policy));
26+
return nullptr;
27+
}
28+
29+
bool Cache::Set(std::unique_ptr<ICacheItem> itemPtr, std::unique_ptr<ICachePolicy> policy)
30+
{
31+
if (!itemPtr)
32+
{
33+
return false;
34+
}
35+
auto data = GetEditableData(itemPtr->GetKey());
36+
if (!data)
37+
{
38+
return false;
39+
}
40+
itemPtr.swap(data->item);
41+
if (data->policy && data->item && itemPtr)
42+
{
43+
data->policy->CallOnUpdate(itemPtr->GetValue(), data->item->GetValue());
44+
}
45+
if (policy)
46+
{
47+
data->policy = std::move(policy);
48+
}
49+
return true;
50+
}
51+
52+
const void *Cache::Get(const std::string &key) const
53+
{
54+
if (auto data = GetData(key); data && data->item)
55+
{
56+
return data->item->GetValue();
57+
}
58+
return nullptr;
59+
}
60+
61+
bool Cache::Remove(const std::string &key)
62+
{
63+
auto data = RemoveData(key);
64+
if (!data)
65+
{
66+
return false;
67+
}
68+
auto &item = data->item;
69+
auto &policy = data->policy;
70+
if (item && policy)
71+
{
72+
policy->CallOnRemove(item->GetValue());
73+
}
74+
return true;
75+
}
76+
77+
bool Cache::Contains(const std::string &key) const { return ContainsData(key); }
78+
79+
size_t Cache::Count() const { return CountData(); }
80+
81+
Cache::Data *Cache::GetEditableData(const std::string &key) { return const_cast<Data *>(GetData(key)); }
82+
83+
bool Cache::AddData(Cache::Data data) { return _items.insert({data.item->GetKey(), std::move(data)}).second; }
84+
85+
std::optional<Cache::Data> Cache::RemoveData(const std::string &key)
86+
{
87+
auto it = _items.find(key);
88+
if (it == _items.end())
89+
{
90+
return std::nullopt;
91+
}
92+
auto data = std::move(it->second);
93+
_items.erase(it);
94+
return std::move(data);
95+
}
96+
97+
const Cache::Data *Cache::GetData(const std::string &key) const
98+
{
99+
if (auto it = _items.find(key); it != _items.end())
100+
{
101+
return &it->second;
102+
}
103+
return nullptr;
104+
}
105+
106+
bool Cache::ContainsData(const std::string &key) const { return _items.contains(key); }
107+
108+
size_t Cache::CountData() const { return _items.size(); }
109+
} // namespace sd

Source/Library/h/Cache.hpp

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
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

Tests/CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
2-
#file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS *.cpp)
1+
# file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS *.cpp)
32

43
add_executable(Test
54
RunTests.cpp
65
ListTest.cpp
76
MapTest.cpp
87
MemoryManagerTest.cpp
98
DependencyInjectorTest.cpp
9+
CacheTest.cpp
1010
)
1111

12-
target_link_libraries(Test
12+
target_link_libraries(Test
1313
SandboxLib
1414
CONAN_PKG::gtest
1515
)

0 commit comments

Comments
 (0)