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>
38PXR_NAMESPACE_OPEN_SCOPE
48 template <
class Derived>
49 static void InitializeStack() {
50 return Derived::_InitializeStack();
55template <
typename T,
bool PerThread>
56class 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
103template <
typename T,
bool PerThread>
104struct Tf_ExportedStackedStorage { };
109template <
typename T,
bool PerThread>
110struct 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;
135template <
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) \
243struct 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>>
252PXR_NAMESPACE_CLOSE_SCOPE
Low-level utilities for informing users of various internal and external diagnostic conditions.
Classes that derive TfStacked may befriend TfStackedAccess if they wish to customize aspects TfStacke...
A TfStacked is used where a class needs to keep a stack of the objects currently in existence.
~TfStacked()
Pops this stacked object from the stack.
static bool IsStackTop(Derived const *p)
Returns true if p is the top of the stack.
static Stack const & GetStack()
Returns a const reference to the entire stack.
static Derived const * GetStackTop()
Returns the top of the stack.
static Derived const * GetStackPrevious()
Returns the element under the top of the stack.
TfStacked()
Pushes this stacked object onto the stack.
Demangle C++ typenames generated by the typeid() facility.
#define TF_FATAL_ERROR(fmt, args)
Issue a fatal error and end the program.