All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_CappedCache.h
Go to the documentation of this file.
1 //
2 // Copyright 2017 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 //
28 #ifndef _GUSD_UT_CAPPEDCACHE_H_
29 #define _GUSD_UT_CAPPEDCACHE_H_
30 
31 #include "pxr/pxr.h"
32 
33 #include <SYS/SYS_AtomicInt.h>
34 #include <UT/UT_Assert.h>
35 #include <UT/UT_CappedCache.h>
36 #include <UT/UT_ConcurrentHashMap.h>
37 #include <UT/UT_IntrusivePtr.h>
38 
39 PXR_NAMESPACE_OPEN_SCOPE
40 
45 template <typename KeyT,
46  typename HashCompare=tbb::tbb_hash_compare<KeyT> >
47 class GusdUT_CappedKey : public UT_CappedKey
48 {
49 public:
50  GusdUT_CappedKey() : UT_CappedKey() {}
51  GusdUT_CappedKey(const KeyT& key) : UT_CappedKey(), _key(key) {}
52 
53  virtual ~GusdUT_CappedKey() {}
54 
55  virtual UT_CappedKey* duplicate() const
56  { return new GusdUT_CappedKey(_key); }
57 
58  virtual unsigned getHash() const
59  { return HashCompare().hash(_key); }
60 
61  virtual bool isEqual(const UT_CappedKey& key) const
62  {
63  return HashCompare().equal(_key,
64  UTverify_cast<const GusdUT_CappedKey*>(
65  &key)->_key);
66  }
67 
68  KeyT* operator->() { return &_key; }
69  const KeyT* operator->() const { return &_key; }
70  KeyT& operator*() { return _key; }
71  const KeyT& operator*() const { return _key; }
72 
73 private:
74  KeyT _key;
75 };
76 
77 
82 class GusdUT_CappedCache : public UT_CappedCache
83 {
84 public:
85  GusdUT_CappedCache(const char* name, int64 size_in_mb=32)
86  : UT_CappedCache(name, size_in_mb) {}
87  ~GusdUT_CappedCache() {}
88 
89  template <typename Item>
90  UT_IntrusivePtr<const Item> Find(const UT_CappedKey& key);
91 
92  template <typename Item,typename Creator,typename... Args>
93  UT_IntrusivePtr<const Item> FindOrCreate(const UT_CappedKey& key,
94  const Creator& creator,
95  Args&... args);
96 
97  template <typename T>
98  bool FindVal(const UT_CappedKey& key);
99 
100  template <typename T,typename Creator,typename... Args>
101  bool FindOrCreateVal(const UT_CappedKey& key,
102  const Creator& creator,
103  Args&... args);
104 
105  template <typename MatchFn>
106  int64 ClearEntries(const MatchFn& matchFn);
107 
108 private:
109 
110  struct _HashCompare
111  {
112  static size_t hash(const UT_CappedKeyHandle& k)
113  { return (size_t)k->getHash(); }
114  static bool equal(const UT_CappedKeyHandle& a,
115  const UT_CappedKeyHandle& b)
116  { return a->isEqual(*b); }
117  };
118 
119 
120  typedef UT_ConcurrentHashMap<UT_CappedKeyHandle,
121  UT_CappedItemHandle,
122  _HashCompare> _ConstructMap;
123  _ConstructMap _constructMap;
124 };
125 
126 
127 template <typename Item>
128 UT_IntrusivePtr<const Item>
129 GusdUT_CappedCache::Find(const UT_CappedKey& key)
130 {
131  if(UT_CappedItemHandle hnd = findItem(key))
132  return UT_IntrusivePtr<const Item>(
133  UTverify_cast<const Item*>(hnd.get()));
134  return UT_IntrusivePtr<const Item>();
135 }
136 
137 
138 template <typename Item, typename Creator, typename... Args>
139 UT_IntrusivePtr<const Item>
140 GusdUT_CappedCache::FindOrCreate(const UT_CappedKey& key,
141  const Creator& creator,
142  Args&... args)
143 {
144  if(auto item = Find<Item>(key))
145  return item;
146 
147  UT_CappedKeyHandle keyHnd(key.duplicate());
148 
149  _ConstructMap::accessor a;
150  if(_constructMap.insert(a, keyHnd)) {
151  // Make sure another thread didn't beat us to it.
152  a->second = findItem(key);
153  if(!a->second) {
154  if((a->second = creator(args...))) {
155  addItem(key, a->second);
156  } else {
157  _constructMap.erase(a);
158  return UT_IntrusivePtr<const Item>();
159  }
160  }
161  }
162  UT_IntrusivePtr<const Item> item(
163  UTverify_cast<const Item*>(a->second.get()));
164  _constructMap.erase(a);
165  return item;
166 }
167 
168 template <typename MatchFn>
169 int64
170 GusdUT_CappedCache::ClearEntries(const MatchFn& matchFn)
171 {
172  int64 freed = 0;
173 
174  auto traverseFn([&](const UT_CappedKeyHandle& key,
175  const UT_CappedItemHandle& item)
176  {
177  if(matchFn(key, item)) {
178  freed += item->getMemoryUsage();
179  // XXX: deleteItem() is safe in threadSafeTraversal!
180  this->deleteItem(*key);
181  }
182  return true;
183  });
184  threadSafeTraversal(traverseFn);
185  return freed;
186 }
187 
188 PXR_NAMESPACE_CLOSE_SCOPE
189 
190 #endif /*_GUSD_UT_CAPPEDCACHE_H_*/
Convenience wrapper around UT_CappedKey.
Variant of UT_CappedCache that improves on item construction.