Rumba C++ SDK
Cache.h
Go to the documentation of this file.
1 /*
2 
3  *
4  ***
5  *****
6  ********************* Mercenaries Engineering SARL
7  ***************** Copyright (C) 2024
8  *************
9  ********* http://www.mercenaries-engineering.com
10  ***********
11  **** ****
12  ** **
13 
14 */
15 
16 #pragma once
17 
18 #include <memory>
19 #include <mutex>
20 #include <unordered_map>
21 
22 // An object cache
23 /* This cache associates a key to a value using a weak pointer.
24  * Once the last shared pointer on the value has been dereferenced, the value is destroyed.
25  * Removal of internal null weak pointers is done when the cache size doubles.
26  * The key must have a hash function available.
27  */
28 template<typename Key, typename Value>
29 class Cache
30 {
31 public:
33  std::shared_ptr<Value> query(const Key& key) const;
34 
36 
42  template<typename Func>
43  std::shared_ptr<Value> test_insert(const Key& key, Func craft);
44 private:
45 
46  void _house_keeping(); // Remove null entries
47 
48  mutable std::mutex _mutex;
49  int _count_to_house_keeping = 2;
50  std::unordered_map<Key, std::weak_ptr<Value>> _map;
51 };
52 
53 template<typename Key, typename Value>
55 {
56  _count_to_house_keeping = 0;
57  for (auto it = _map.begin(); it != _map.end();)
58  {
59  if (it->second.expired())
60  it = _map.erase(it);
61  else
62  {
63  ++_count_to_house_keeping;
64  ++it;
65  }
66  }
67 }
68 
69 template<typename Key, typename Value>
70 std::shared_ptr<Value> Cache<Key, Value>::query(const Key& key) const
71 {
72  std::lock_guard<std::mutex> lock(_mutex);
73  auto ite = _map.find(key);
74  if (ite != _map.end())
75  {
76  std::shared_ptr<Value> v = ite->second.lock();
77  if (v)
78  return v;
79  }
80  return {};
81 }
82 
83 template<typename Key, typename Value>
84 template<typename Func>
85 std::shared_ptr<Value> Cache<Key, Value>::test_insert(const Key& key, Func craft)
86 {
87  std::lock_guard<std::mutex> lock(_mutex);
88 
89  // Try insert first
90  auto result = _map.emplace(key, std::shared_ptr<Value>());
91  std::shared_ptr<Value> v = result.first->second.lock();
92  if (v == nullptr)
93  {
94  v = craft();
95  result.first->second = v;
96 
97  --_count_to_house_keeping;
98  if (_count_to_house_keeping <= 0)
99  _house_keeping();
100  }
101 
102  return v;
103 }
std::shared_ptr< Value > query(const Key &key) const
Query the cache with a key, returns nullptr if no entry is available.
Definition: Cache.h:70
std::shared_ptr< Value > test_insert(const Key &key, Func craft)
Test and insert a cache value.
Definition: Cache.h:85
Definition: Cache.h:29