24 #ifndef PXR_BASE_TF_STACKED_H 25 #define PXR_BASE_TF_STACKED_H 28 #include "pxr/base/tf/api.h" 32 #include <tbb/enumerable_thread_specific.h> 35 #include <type_traits> 38 PXR_NAMESPACE_OPEN_SCOPE
48 template <
class Derived>
49 static void InitializeStack() {
50 return Derived::_InitializeStack();
55 template <
typename T,
bool PerThread>
56 class Tf_StackedStorageType {
58 typedef std::vector<T const *> Stack;
65 _StackHolder() : _initialized(false) { }
70 TfStackedAccess::InitializeStack<T>();
80 struct _PerThreadStackStorage {
81 tbb::enumerable_thread_specific<_StackHolder> stack;
83 return stack.local().Get();
87 struct _GlobalStackStorage {
96 typedef typename std::conditional<
97 PerThread, _PerThreadStackStorage, _GlobalStackStorage
103 template <
typename T,
bool PerThread>
104 struct Tf_ExportedStackedStorage { };
109 template <
typename T,
bool PerThread>
110 struct Tf_StackedStorage {
111 typedef typename Tf_StackedStorageType<T, PerThread>::Stack Stack;
112 typedef typename Tf_StackedStorageType<T, PerThread>::Type Type;
113 static std::atomic<Type*> value;
135 template <
class Derived,
bool PerThread =
true,
136 class Holder = Tf_StackedStorage<Derived, PerThread>>
140 typedef typename Holder::Type _StorageType;
142 typedef Holder Storage;
143 typedef typename Storage::Stack Stack;
161 return stack.empty() ? 0 : stack.back();
171 size_t size = stack.size();
172 return size <= 1 ? 0 : stack[size-2];
192 static void _InitializeStack() {}
195 static void _Push(Derived
const *p) {
196 _GetStack().push_back(p);
200 static void _Pop(Derived
const *p) {
203 _GetStack().pop_back();
207 ArchGetDemangled<Derived>().c_str());
212 static Stack &_GetStack() {
214 if (ARCH_UNLIKELY(Storage::value.load() ==
nullptr)) {
216 _StorageType *old =
nullptr;
217 _StorageType *tmp =
new _StorageType;
219 if (!Storage::value.compare_exchange_strong(old, tmp)) {
224 return Storage::value.load(std::memory_order_relaxed)->Get();
227 Derived *_AsDerived() {
228 return static_cast<Derived *>(
this);
231 Derived
const *_AsDerived()
const {
232 return static_cast<Derived const *>(
this);
240 #define TF_DEFINE_STACKED(Derived, IsPerThread, eiAPI) \ 243 struct Tf_ExportedStackedStorage<Derived, IsPerThread> { \ 244 typedef typename Tf_StackedStorageType<Derived, IsPerThread>::Stack Stack; \ 245 typedef typename Tf_StackedStorageType<Derived, IsPerThread>::Type Type; \ 246 static eiAPI std::atomic<Type*> value; \ 249 public TfStacked<Derived, IsPerThread, \ 250 Tf_ExportedStackedStorage<Derived, IsPerThread>> 252 PXR_NAMESPACE_CLOSE_SCOPE
254 #endif // PXR_BASE_TF_STACKED_H A TfStacked is used where a class needs to keep a stack of the objects currently in existence.
Low-level utilities for informing users of various internal and external diagnostic conditions.
Demangle C++ typenames generated by the typeid() facility.
TfStacked()
Pushes this stacked object onto the stack.
static Derived const * GetStackTop()
Returns the top of the stack.
#define TF_FATAL_ERROR(fmt, args)
Issue a fatal error and end the program.
Classes that derive TfStacked may befriend TfStackedAccess if they wish to customize aspects TfStacke...
static Derived const * GetStackPrevious()
Returns the element under the top of the stack.
~TfStacked()
Pops this stacked object from the stack.
static Stack const & GetStack()
Returns a const reference to the entire stack.
static bool IsStackTop(Derived const *p)
Returns true if p is the top of the stack.