All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
instanceRegistry.h
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_IMAGING_HD_INSTANCE_REGISTRY_H
8#define PXR_IMAGING_HD_INSTANCE_REGISTRY_H
9
10#include "pxr/pxr.h"
11#include "pxr/imaging/hd/api.h"
12#include "pxr/imaging/hd/version.h"
13#include "pxr/imaging/hd/perfLog.h"
14#include "pxr/imaging/hf/perfLog.h"
15
16#include <tbb/concurrent_unordered_map.h>
17
18#include <memory>
19#include <mutex>
20
21PXR_NAMESPACE_OPEN_SCOPE
22
23
42template <typename VALUE>
44public:
45 typedef uint64_t KeyType;
46 typedef VALUE ValueType;
47
48 typedef KeyType ID;
49
50 struct ValueHolder {
51 ValueHolder(ValueType const & value = ValueType())
52 : value(value)
53 , recycleCounter(0)
54 { }
55 void ResetRecycleCounter() {
56 recycleCounter = 0;
57 }
58
59 ValueType value;
60 int recycleCounter;
61 };
62 typedef tbb::concurrent_unordered_map<KeyType, ValueHolder> Dictionary;
63
64 typedef std::mutex RegistryMutex;
65 typedef std::unique_lock<RegistryMutex> RegistryLock;
66
67 HdInstance() = delete;
68
71 explicit HdInstance(KeyType const &key,
72 ValueType const &value,
73 RegistryLock &&registryLock,
74 Dictionary *container)
75 : _key(key)
76 , _value(value)
77 , _registryLock(std::move(registryLock))
78 , _container(container)
79 , _isFirstInstance(!bool(_value))
80 { }
81
85 explicit HdInstance(KeyType const &key)
86 : _key(key)
87 , _value(ValueType())
88 , _registryLock()
89 , _container(nullptr)
90 , _isFirstInstance(!bool(_value))
91 { }
92
94 KeyType const &GetKey() const { return _key; }
95
97 ValueType const &GetValue() const { return _value; }
98
100 void SetValue(ValueType const &value) {
101 if (_container) (*_container)[_key] = ValueHolder(value);
102 _value = value;
103 }
104
106 bool IsFirstInstance() const {
107 return _isFirstInstance;
108 }
109
110private:
111 KeyType _key;
112 ValueType _value;
113 RegistryLock _registryLock;
114 Dictionary *_container;
115 bool _isFirstInstance;
116};
117
128template <typename VALUE>
130public:
132
133 HdInstanceRegistry() = default;
134
138 : _dictionary(other._dictionary)
139 , _registryMutex() // mutex is not copied
140 { }
141
144 typename InstanceType::KeyType const &key);
145
149 typename InstanceType::KeyType const &key, bool *found);
150
156 size_t GarbageCollect(int recycleCount = 0);
157
164 template <typename Callback>
165 size_t GarbageCollect(Callback &&callback, int recycleCount = 0);
166
169 typedef typename InstanceType::Dictionary::const_iterator const_iterator;
170 const_iterator begin() const { return _dictionary.begin(); }
171 const_iterator end() const { return _dictionary.end(); }
172
173 size_t size() const { return _dictionary.size(); }
174
175 void Invalidate();
176
177private:
178 template <typename T>
179 static bool _IsUnique(std::shared_ptr<T> const &value) {
180 return value.unique();
181 }
182
183 typename InstanceType::Dictionary _dictionary;
184 typename InstanceType::RegistryMutex _registryMutex;
185
186 HdInstanceRegistry &operator =(HdInstanceRegistry &) = delete;
187};
188
189// ---------------------------------------------------------------------------
190// instance registry impl
191
192template <typename VALUE>
195 typename HdInstance<VALUE>::KeyType const &key)
196{
197 HD_TRACE_FUNCTION();
198 HF_MALLOC_TAG_FUNCTION();
199
200 // Grab Registry lock
201 // (and don't release it in this function, return it instead)
202 typename InstanceType::RegistryLock lock(_registryMutex);
203
204 typename InstanceType::Dictionary::iterator it = _dictionary.find(key);
205 if (it == _dictionary.end()) {
206 // not found. create new one
207 it = _dictionary.insert(
208 std::make_pair(key, typename InstanceType::ValueHolder())).first;
209 }
210
211 it->second.ResetRecycleCounter();
212 return InstanceType(key, it->second.value, std::move(lock), &_dictionary);
213}
214
215template <typename VALUE>
218 typename HdInstance<VALUE>::KeyType const &key, bool *found)
219{
220 HD_TRACE_FUNCTION();
221 HF_MALLOC_TAG_FUNCTION();
222
223 // Grab Registry lock
224 // (and don't release it in this function, return it instead)
225 typename InstanceType::RegistryLock lock(_registryMutex);
226
227 typename InstanceType::Dictionary::iterator it = _dictionary.find(key);
228 if (it == _dictionary.end()) {
229 *found = false;
230 return InstanceType(key, VALUE(), std::move(lock), nullptr);
231 } else {
232 *found = true;
233 it->second.ResetRecycleCounter();
234 return InstanceType(key, it->second.value,std::move(lock),&_dictionary);
235 }
236}
237
238template <typename VALUE>
239size_t
241{
242 // Call GarbageCollect with empty callback function
243 return GarbageCollect([](void*){}, recycleCount);
244}
245
246template <typename VALUE>
247template <typename Callback>
248size_t
249HdInstanceRegistry<VALUE>::GarbageCollect(Callback &&callback, int recycleCount)
250{
251 HD_TRACE_FUNCTION();
252 HF_MALLOC_TAG_FUNCTION();
253
254 // Skip garbage collection entirely when then the recycleCount is < 0
255 if (recycleCount < 0) {
256 return _dictionary.size();
257 }
258
259 size_t inUseCount = 0;
260 for (typename InstanceType::Dictionary::iterator it = _dictionary.begin();
261 it != _dictionary.end();) {
262
263 // erase instance which isn't referred from anyone
264 bool isUnique = _IsUnique(it->second.value);
265 if (isUnique && (++it->second.recycleCounter > recycleCount)) {
266 std::forward<Callback>(callback)(it->second.value.get());
267 it = _dictionary.unsafe_erase(it);
268 } else {
269 ++it;
270 ++inUseCount;
271 }
272 }
273 return inUseCount;
274}
275
276template <typename VALUE>
277void
279{
280 HD_TRACE_FUNCTION();
281 HF_MALLOC_TAG_FUNCTION();
282
283 _dictionary.clear();
284}
285
286
287PXR_NAMESPACE_CLOSE_SCOPE
288
289#endif // PXR_IMAGING_HD_INSTANCE_REGISTRY_H
This class is used as an interface to a shared instance in HdInstanceRegistry.
bool IsFirstInstance() const
Returns true if the value has not been initialized.
void SetValue(ValueType const &value)
Update the value in dictionary indexed by the key.
ValueType const & GetValue() const
Returns the value.
HdInstance(KeyType const &key, ValueType const &value, RegistryLock &&registryLock, Dictionary *container)
Construct an instance holding a registry lock, representing a value held in a registry container.
HdInstance(KeyType const &key)
Construct an instance with no lock or registry container.
KeyType const & GetKey() const
Returns the key.
HdInstanceRegistry is a dictionary container of HdInstance.
InstanceType GetInstance(typename InstanceType::KeyType const &key)
Returns a shared instance for given key.
size_t GarbageCollect(int recycleCount=0)
Removes unreferenced entries and returns the count of remaining entries.
InstanceType::Dictionary::const_iterator const_iterator
Returns a const iterator being/end of dictionary.
InstanceType FindInstance(typename InstanceType::KeyType const &key, bool *found)
Returns a shared instance for a given key only if the key exists in the dictionary.
size_t GarbageCollect(Callback &&callback, int recycleCount=0)
Removes unreferenced entries and returns the count of remaining entries.
HdInstanceRegistry(const HdInstanceRegistry &other)
Copy constructor.
STL namespace.