7#ifndef PXR_BASE_TF_STACKED_H
8#define PXR_BASE_TF_STACKED_H
11#include "pxr/base/tf/api.h"
15#include <tbb/enumerable_thread_specific.h>
21PXR_NAMESPACE_OPEN_SCOPE
31 template <
class Derived>
32 static void InitializeStack() {
33 return Derived::_InitializeStack();
38template <
typename T,
bool PerThread>
39class Tf_StackedStorageType {
41 typedef std::vector<T const *> Stack;
48 _StackHolder() : _initialized(false) { }
53 TfStackedAccess::InitializeStack<T>();
63 struct _PerThreadStackStorage {
64 tbb::enumerable_thread_specific<_StackHolder> stack;
66 return stack.local().Get();
70 struct _GlobalStackStorage {
79 typedef typename std::conditional<
80 PerThread, _PerThreadStackStorage, _GlobalStackStorage
86template <
typename T,
bool PerThread>
87struct Tf_ExportedStackedStorage { };
92template <
typename T,
bool PerThread>
93struct Tf_StackedStorage {
94 typedef typename Tf_StackedStorageType<T, PerThread>::Stack Stack;
95 typedef typename Tf_StackedStorageType<T, PerThread>::Type Type;
96 static std::atomic<Type*> value;
118template <
class Derived,
bool PerThread =
true,
119 class Holder = Tf_StackedStorage<Derived, PerThread>>
123 typedef typename Holder::Type _StorageType;
125 typedef Holder Storage;
126 typedef typename Storage::Stack Stack;
144 return stack.empty() ? 0 : stack.back();
154 size_t size = stack.size();
155 return size <= 1 ? 0 : stack[size-2];
175 static void _InitializeStack() {}
178 static void _Push(Derived
const *p) {
179 _GetStack().push_back(p);
183 static void _Pop(Derived
const *p) {
186 _GetStack().pop_back();
190 ArchGetDemangled<Derived>().c_str());
195 static Stack &_GetStack() {
197 if (ARCH_UNLIKELY(Storage::value.load() ==
nullptr)) {
199 _StorageType *old =
nullptr;
200 _StorageType *tmp =
new _StorageType;
202 if (!Storage::value.compare_exchange_strong(old, tmp)) {
207 return Storage::value.load(std::memory_order_relaxed)->Get();
210 Derived *_AsDerived() {
211 return static_cast<Derived *
>(
this);
214 Derived
const *_AsDerived()
const {
215 return static_cast<Derived
const *
>(
this);
223#define TF_DEFINE_STACKED(Derived, IsPerThread, eiAPI) \
226struct Tf_ExportedStackedStorage<Derived, IsPerThread> { \
227 typedef typename Tf_StackedStorageType<Derived, IsPerThread>::Stack Stack; \
228 typedef typename Tf_StackedStorageType<Derived, IsPerThread>::Type Type; \
229 static eiAPI std::atomic<Type*> value; \
232 public TfStacked<Derived, IsPerThread, \
233 Tf_ExportedStackedStorage<Derived, IsPerThread>>
235PXR_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.