|
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