All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 HD_INSTANCE_REGISTRY_H
25 #define 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 <boost/shared_ptr.hpp>
34 #include <tbb/concurrent_unordered_map.h>
35 
36 #include <mutex>
37 
38 PXR_NAMESPACE_OPEN_SCOPE
39 
40 
55 template <typename KEY, typename VALUE>
56 class HdInstance {
57 public:
58  typedef KEY KeyType;
59  typedef VALUE ValueType;
60 
61  typedef tbb::concurrent_unordered_map<KeyType, ValueType> Dictionary;
62 
65 
67  void Create(KeyType const &key,
68  ValueType const &value,
69  Dictionary *parent,
70  bool isFirstInstance)
71  {
72  _key = key;
73  _value = value;
74  _parent = parent;
75  _isFirstInstance = isFirstInstance;
76  }
77 
79  KeyType const &GetKey() const { return _key; }
80 
82  ValueType const &GetValue() const { return _value; }
83 
85  void SetValue(ValueType const &value) {
86  if (_parent) (*_parent)[_key] = value;
87  _value = value;
88  }
89 
91  bool IsFirstInstance() const {
92  return _isFirstInstance;
93  }
94 
95 private:
96  KeyType _key;
97  ValueType _value;
98  Dictionary *_parent;
99  bool _isFirstInstance;
100 };
101 
112 template <typename INSTANCE>
114 public:
115  HdInstanceRegistry() = default;
116 
120  : _dictionary(other._dictionary),
121  _regLock() // Lock is not copied
122  {
123  }
124 
126  std::unique_lock<std::mutex> GetInstance(typename INSTANCE::KeyType const &key,
127  INSTANCE *instance);
128 
131  std::unique_lock<std::mutex> FindInstance(typename INSTANCE::KeyType const &key,
132  INSTANCE *instance, bool *found);
133 
136  size_t GarbageCollect();
137 
140  typedef typename INSTANCE::Dictionary::const_iterator const_iterator;
141  const_iterator begin() const { return _dictionary.begin(); }
142  const_iterator end() const { return _dictionary.end(); }
143 
144  void Invalidate();
145 
146 private:
147  template <typename T>
148  static bool _IsUnique(boost::shared_ptr<T> const &value) {
149  return value.unique();
150  }
151 
152  typedef typename INSTANCE::Dictionary _Dictionary;
153  _Dictionary _dictionary;
154  std::mutex _regLock;
155 
156  HdInstanceRegistry &operator =(HdInstanceRegistry &) = delete;
157 };
158 
159 // ---------------------------------------------------------------------------
160 // instance registry impl
161 
162 template <typename INSTANCE>
163 std::unique_lock<std::mutex>
164 HdInstanceRegistry<INSTANCE>::GetInstance(typename INSTANCE::KeyType const &key,
165  INSTANCE *instance)
166 {
167  HD_TRACE_FUNCTION();
168  HF_MALLOC_TAG_FUNCTION();
169 
170  // Grab Registry lock
171  // (and don't release it in this function, return it instead)
172  std::unique_lock<std::mutex> lock(_regLock);
173 
174  typename _Dictionary::iterator it = _dictionary.find(key);
175  bool firstInstance = false;
176  if (it == _dictionary.end()) {
177  // not found. create new one
178  it = _dictionary.insert(
179  std::make_pair(key, typename INSTANCE::ValueType())).first;
180 
181  firstInstance = true;
182  }
183 
184  instance->Create(key, it->second, &_dictionary, firstInstance);
185 
186  return lock;
187 }
188 
189 template <typename INSTANCE>
190 std::unique_lock<std::mutex>
191 HdInstanceRegistry<INSTANCE>::FindInstance(typename INSTANCE::KeyType const &key,
192  INSTANCE *instance, bool *found)
193 {
194  HD_TRACE_FUNCTION();
195  HF_MALLOC_TAG_FUNCTION();
196 
197  // Grab Registry lock
198  // (and don't release it in this function, return it instead)
199  std::unique_lock<std::mutex> lock(_regLock);
200 
201  typename _Dictionary::iterator it = _dictionary.find(key);
202  if (it == _dictionary.end()) {
203  *found = false;
204  } else {
205  *found = true;
206  instance->Create(key, it->second, &_dictionary, false /*firstInstance*/);
207  }
208 
209  return lock;
210 }
211 
212 template <typename INSTANCE>
213 size_t
215 {
216  HD_TRACE_FUNCTION();
217  HF_MALLOC_TAG_FUNCTION();
218 
219  size_t count = 0;
220  for (typename _Dictionary::iterator it = _dictionary.begin();
221  it != _dictionary.end();) {
222 
223  // erase instance which isn't referred from anyone
224  if (_IsUnique(it->second)) {
225  it = _dictionary.unsafe_erase(it);
226  } else {
227  ++it;
228  ++count;
229  }
230  }
231  return count;
232 }
233 
234 template <typename INSTANCE>
235 void
237 {
238  HD_TRACE_FUNCTION();
239  HF_MALLOC_TAG_FUNCTION();
240 
241  _dictionary.clear();
242 }
243 
244 
245 PXR_NAMESPACE_CLOSE_SCOPE
246 
247 #endif // HD_INSTANCE_REGISTRY_H
HdInstance()
Constructor.
size_t GarbageCollect()
Remove entries which has unreferenced key and returns the count of remaining entries.
bool IsFirstInstance() const
Returns true if the value has not been initialized.
std::unique_lock< std::mutex > GetInstance(typename INSTANCE::KeyType const &key, INSTANCE *instance)
Returns a shared instance for given key as a pair of (key, value).
HdInstanceRegistry is a dictionary container of HdInstance.
ValueType const & GetValue() const
Returns the value.
HdInstanceRegistry(const HdInstanceRegistry &other)
Copy constructor.
std::unique_lock< std::mutex > FindInstance(typename INSTANCE::KeyType const &key, INSTANCE *instance, bool *found)
Returns a shared instance for a given key as a pair of (key, value) only if the key exists in the dic...
INSTANCE::Dictionary::const_iterator const_iterator
Returns a const iterator being/end of dictionary.
void SetValue(ValueType const &value)
Update the value in dictionary indexed by the key.
This class is used as a pointer to the shared instance in HdInstanceRegistry.
KeyType const & GetKey() const
Returns the key.
void Create(KeyType const &key, ValueType const &value, Dictionary *parent, bool isFirstInstance)
Initalize the members of HdInstance.