Loading...
Searching...
No Matches
instanceRegistry.h
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the Apache License, Version 2.0 (the "Apache License")
5// with the following modification; you may not use this file except in
6// compliance with the Apache License and the following modification to it:
7// Section 6. Trademarks. is deleted and replaced with:
8//
9// 6. Trademarks. This License does not grant permission to use the trade
10// names, trademarks, service marks, or product names of the Licensor
11// and its affiliates, except as required to comply with Section 4(c) of
12// the License and to reproduce the content of the NOTICE file.
13//
14// You may obtain a copy of the Apache License at
15//
16// http://www.apache.org/licenses/LICENSE-2.0
17//
18// Unless required by applicable law or agreed to in writing, software
19// distributed under the Apache License with the above modification is
20// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21// KIND, either express or implied. See the Apache License for the specific
22// language governing permissions and limitations under the Apache License.
23//
24#ifndef PXR_IMAGING_HD_INSTANCE_REGISTRY_H
25#define PXR_IMAGING_HD_INSTANCE_REGISTRY_H
26
27#include "pxr/pxr.h"
28#include "pxr/imaging/hd/api.h"
29#include "pxr/imaging/hd/version.h"
30#include "pxr/imaging/hd/perfLog.h"
31#include "pxr/imaging/hf/perfLog.h"
32
33#include <tbb/concurrent_unordered_map.h>
34
35#include <memory>
36#include <mutex>
37
38PXR_NAMESPACE_OPEN_SCOPE
39
40
59template <typename VALUE>
61public:
62 typedef uint64_t KeyType;
63 typedef VALUE ValueType;
64
65 typedef KeyType ID;
66
67 struct ValueHolder {
68 ValueHolder(ValueType const & value = ValueType())
69 : value(value)
70 , recycleCounter(0)
71 { }
72 void ResetRecycleCounter() {
73 recycleCounter = 0;
74 }
75
76 ValueType value;
77 int recycleCounter;
78 };
79 typedef tbb::concurrent_unordered_map<KeyType, ValueHolder> Dictionary;
80
81 typedef std::mutex RegistryMutex;
82 typedef std::unique_lock<RegistryMutex> RegistryLock;
83
84 HdInstance() = delete;
85
88 explicit HdInstance(KeyType const &key,
89 ValueType const &value,
90 RegistryLock &&registryLock,
91 Dictionary *container)
92 : _key(key)
93 , _value(value)
94 , _registryLock(std::move(registryLock))
95 , _container(container)
96 , _isFirstInstance(!bool(_value))
97 { }
98
102 explicit HdInstance(KeyType const &key)
103 : _key(key)
104 , _value(ValueType())
105 , _registryLock()
106 , _container(nullptr)
107 , _isFirstInstance(!bool(_value))
108 { }
109
111 KeyType const &GetKey() const { return _key; }
112
114 ValueType const &GetValue() const { return _value; }
115
117 void SetValue(ValueType const &value) {
118 if (_container) (*_container)[_key] = ValueHolder(value);
119 _value = value;
120 }
121
123 bool IsFirstInstance() const {
124 return _isFirstInstance;
125 }
126
127private:
128 KeyType _key;
129 ValueType _value;
130 RegistryLock _registryLock;
131 Dictionary *_container;
132 bool _isFirstInstance;
133};
134
145template <typename VALUE>
147public:
149
150 HdInstanceRegistry() = default;
151
155 : _dictionary(other._dictionary)
156 , _registryMutex() // mutex is not copied
157 { }
158
161 typename InstanceType::KeyType const &key);
162
166 typename InstanceType::KeyType const &key, bool *found);
167
173 size_t GarbageCollect(int recycleCount = 0);
174
181 template <typename Callback>
182 size_t GarbageCollect(Callback &&callback, int recycleCount = 0);
183
186 typedef typename InstanceType::Dictionary::const_iterator const_iterator;
187 const_iterator begin() const { return _dictionary.begin(); }
188 const_iterator end() const { return _dictionary.end(); }
189
190 size_t size() const { return _dictionary.size(); }
191
192 void Invalidate();
193
194private:
195 template <typename T>
196 static bool _IsUnique(std::shared_ptr<T> const &value) {
197 return value.unique();
198 }
199
200 typename InstanceType::Dictionary _dictionary;
201 typename InstanceType::RegistryMutex _registryMutex;
202
203 HdInstanceRegistry &operator =(HdInstanceRegistry &) = delete;
204};
205
206// ---------------------------------------------------------------------------
207// instance registry impl
208
209template <typename VALUE>
212 typename HdInstance<VALUE>::KeyType const &key)
213{
214 HD_TRACE_FUNCTION();
215 HF_MALLOC_TAG_FUNCTION();
216
217 // Grab Registry lock
218 // (and don't release it in this function, return it instead)
219 typename InstanceType::RegistryLock lock(_registryMutex);
220
221 typename InstanceType::Dictionary::iterator it = _dictionary.find(key);
222 if (it == _dictionary.end()) {
223 // not found. create new one
224 it = _dictionary.insert(
225 std::make_pair(key, typename InstanceType::ValueHolder())).first;
226 }
227
228 it->second.ResetRecycleCounter();
229 return InstanceType(key, it->second.value, std::move(lock), &_dictionary);
230}
231
232template <typename VALUE>
235 typename HdInstance<VALUE>::KeyType const &key, bool *found)
236{
237 HD_TRACE_FUNCTION();
238 HF_MALLOC_TAG_FUNCTION();
239
240 // Grab Registry lock
241 // (and don't release it in this function, return it instead)
242 typename InstanceType::RegistryLock lock(_registryMutex);
243
244 typename InstanceType::Dictionary::iterator it = _dictionary.find(key);
245 if (it == _dictionary.end()) {
246 *found = false;
247 return InstanceType(key, VALUE(), std::move(lock), nullptr);
248 } else {
249 *found = true;
250 it->second.ResetRecycleCounter();
251 return InstanceType(key, it->second.value,std::move(lock),&_dictionary);
252 }
253}
254
255template <typename VALUE>
256size_t
258{
259 // Call GarbageCollect with empty callback function
260 return GarbageCollect([](void*){}, recycleCount);
261}
262
263template <typename VALUE>
264template <typename Callback>
265size_t
266HdInstanceRegistry<VALUE>::GarbageCollect(Callback &&callback, int recycleCount)
267{
268 HD_TRACE_FUNCTION();
269 HF_MALLOC_TAG_FUNCTION();
270
271 // Skip garbage collection entirely when then the recycleCount is < 0
272 if (recycleCount < 0) {
273 return _dictionary.size();
274 }
275
276 size_t inUseCount = 0;
277 for (typename InstanceType::Dictionary::iterator it = _dictionary.begin();
278 it != _dictionary.end();) {
279
280 // erase instance which isn't referred from anyone
281 bool isUnique = _IsUnique(it->second.value);
282 if (isUnique && (++it->second.recycleCounter > recycleCount)) {
283 std::forward<Callback>(callback)(it->second.value.get());
284 it = _dictionary.unsafe_erase(it);
285 } else {
286 ++it;
287 ++inUseCount;
288 }
289 }
290 return inUseCount;
291}
292
293template <typename VALUE>
294void
296{
297 HD_TRACE_FUNCTION();
298 HF_MALLOC_TAG_FUNCTION();
299
300 _dictionary.clear();
301}
302
303
304PXR_NAMESPACE_CLOSE_SCOPE
305
306#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.