HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
threadLocalScopedCache.h
Go to the documentation of this file.
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_USD_AR_THREAD_LOCAL_SCOPED_CACHE_H
8 #define PXR_USD_AR_THREAD_LOCAL_SCOPED_CACHE_H
9 
10 #include "pxr/pxr.h"
11 #include "pxr/usd/ar/api.h"
12 
13 #include "pxr/base/vt/value.h"
14 #include "pxr/base/tf/diagnostic.h"
15 
16 #include <tbb/enumerable_thread_specific.h>
17 #include <memory>
18 #include <vector>
19 
21 
22 /// \class ArThreadLocalScopedCache
23 ///
24 /// Utility class for custom resolver implementations. This class wraps up
25 /// a common pattern for implementing thread-local scoped caches for
26 /// ArResolver::BeginCacheScope and ArResolver::EndCacheScope.
27 ///
28 /// \code{.cpp}
29 /// class MyResolver : public ArResolver {
30 /// using ResolveCache = ArThreadLocalScopedCache<...>;
31 /// ResolveCache _cache;
32 ///
33 /// void BeginCacheScope(VtValue* data) { _cache.BeginCacheScope(data); }
34 /// void EndCacheScope(VtValue* data) { _cache.EndCacheScope(data); }
35 /// void Resolve(...) {
36 /// // If caching is active in this thread, retrieve the current
37 /// // cache and use it to lookup/store values.
38 /// if (ResolveCache::CachePtr cache = _cache.GetCurrentCache()) {
39 /// // ...
40 /// }
41 /// // Otherwise, caching is not active
42 /// // ...
43 /// }
44 /// };
45 /// \endcode
46 ///
47 /// \see \ref ArResolver_scopedCache "Scoped Resolution Cache"
48 template <class CachedType>
50 {
51 public:
52  using CachePtr = std::shared_ptr<CachedType>;
53 
54  void BeginCacheScope(VtValue* cacheScopeData)
55  {
56  // Since this is intended to be used by ArResolver implementations,
57  // we expect cacheScopeData to never be NULL and to either be empty
58  // or holding a cache pointer that we've filled in previously.
59  if (!cacheScopeData ||
60  (!cacheScopeData->IsEmpty() &&
61  !cacheScopeData->IsHolding<CachePtr>())) {
62  TF_CODING_ERROR("Unexpected cache scope data");
63  return;
64  }
65 
66  _CachePtrStack& cacheStack = _threadCacheStack.local();
67  if (cacheScopeData->IsHolding<CachePtr>()) {
68  cacheStack.push_back(cacheScopeData->UncheckedGet<CachePtr>());
69  }
70  else {
71  if (cacheStack.empty()) {
72  cacheStack.push_back(std::make_shared<CachedType>());
73  }
74  else {
75  cacheStack.push_back(cacheStack.back());
76  }
77  }
78  *cacheScopeData = cacheStack.back();
79  }
80 
81  void EndCacheScope(VtValue* cacheScopeData)
82  {
83  _CachePtrStack& cacheStack = _threadCacheStack.local();
84  if (TF_VERIFY(!cacheStack.empty())) {
85  cacheStack.pop_back();
86  }
87  }
88 
90  {
91  _CachePtrStack& cacheStack = _threadCacheStack.local();
92  return (cacheStack.empty() ? CachePtr() : cacheStack.back());
93  }
94 
95 private:
96  using _CachePtrStack = std::vector<CachePtr>;
97  using _ThreadLocalCachePtrStack =
98  tbb::enumerable_thread_specific<_CachePtrStack>;
99  _ThreadLocalCachePtrStack _threadCacheStack;
100 };
101 
103 
104 #endif // PXR_USD_AR_THREAD_LOCAL_SCOPED_CACHE_H
T const & UncheckedGet() const &
Definition: value.h:1104
#define TF_CODING_ERROR
bool IsEmpty() const
Returns true iff this value is empty.
Definition: value.h:1285
void BeginCacheScope(VtValue *cacheScopeData)
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
bool IsHolding() const
Definition: value.h:1064
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
std::shared_ptr< CachedType > CachePtr
void EndCacheScope(VtValue *cacheScopeData)
Definition: value.h:146