|
11 | 11 | #ifndef UR_SINGLETON_H
|
12 | 12 | #define UR_SINGLETON_H 1
|
13 | 13 |
|
| 14 | +#include <cassert> |
14 | 15 | #include <memory>
|
15 | 16 | #include <mutex>
|
16 | 17 | #include <unordered_map>
|
17 | 18 |
|
18 | 19 | //////////////////////////////////////////////////////////////////////////
|
19 | 20 | /// a abstract factory for creation of singleton objects
|
20 | 21 | template <typename singleton_tn, typename key_tn> class singleton_factory_t {
|
| 22 | + struct entry_t { |
| 23 | + std::unique_ptr<singleton_tn> ptr; |
| 24 | + size_t ref_count; |
| 25 | + }; |
| 26 | + |
21 | 27 | protected:
|
22 | 28 | using singleton_t = singleton_tn;
|
23 | 29 | using key_t = typename std::conditional<std::is_pointer<key_tn>::value,
|
24 | 30 | size_t, key_tn>::type;
|
25 | 31 |
|
26 | 32 | using ptr_t = std::unique_ptr<singleton_t>;
|
27 |
| - using map_t = std::unordered_map<key_t, ptr_t>; |
| 33 | + using map_t = std::unordered_map<key_t, entry_t>; |
28 | 34 |
|
29 | 35 | std::mutex mut; ///< lock for thread-safety
|
30 | 36 | map_t map; ///< single instance of singleton for each unique key
|
@@ -60,16 +66,31 @@ template <typename singleton_tn, typename key_tn> class singleton_factory_t {
|
60 | 66 | if (map.end() == iter) {
|
61 | 67 | auto ptr =
|
62 | 68 | std::make_unique<singleton_t>(std::forward<Ts>(params)...);
|
63 |
| - iter = map.emplace(key, std::move(ptr)).first; |
| 69 | + iter = map.emplace(key, entry_t{std::move(ptr), 0}).first; |
| 70 | + } else { |
| 71 | + iter->second.ref_count++; |
64 | 72 | }
|
65 |
| - return iter->second.get(); |
| 73 | + return iter->second.ptr.get(); |
| 74 | + } |
| 75 | + |
| 76 | + void retain(key_tn key) { |
| 77 | + std::lock_guard<std::mutex> lk(mut); |
| 78 | + auto iter = map.find(getKey(key)); |
| 79 | + assert(iter != map.end()); |
| 80 | + iter->second.ref_count++; |
66 | 81 | }
|
67 | 82 |
|
68 | 83 | //////////////////////////////////////////////////////////////////////////
|
69 | 84 | /// once the key is no longer valid, release the singleton
|
70 | 85 | void release(key_tn key) {
|
71 | 86 | std::lock_guard<std::mutex> lk(mut);
|
72 |
| - map.erase(getKey(key)); |
| 87 | + auto iter = map.find(getKey(key)); |
| 88 | + assert(iter != map.end()); |
| 89 | + if (iter->second.ref_count == 0) { |
| 90 | + map.erase(iter); |
| 91 | + } else { |
| 92 | + iter->second.ref_count--; |
| 93 | + } |
73 | 94 | }
|
74 | 95 |
|
75 | 96 | void clear() {
|
|
0 commit comments