staticData.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 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 //
24 #ifndef PXR_BASE_TF_STATIC_DATA_H
25 #define PXR_BASE_TF_STATIC_DATA_H
26 
29 
30 #include "pxr/pxr.h"
31 #include "pxr/base/arch/hints.h"
33 #include "pxr/base/tf/preprocessorUtilsLite.h"
34 
35 #include <atomic>
36 #include <type_traits>
37 
38 PXR_NAMESPACE_OPEN_SCOPE
39 
108 template <class T>
109 struct Tf_StaticDataDefaultFactory {
110  static T *New() { return new T; }
111 };
112 
113 template <class T, class Factory = Tf_StaticDataDefaultFactory<T> >
115 public:
118  inline T* operator-> () const { return Get(); }
119 
122  inline T& operator* () const { return *Get(); }
123 
126  inline T* Get() const {
127  T *p = _data;
128  return ARCH_LIKELY(p) ? p : _TryToCreateData();
129  }
130 
133  inline bool IsInitialized() const { return _data.load() != nullptr; }
134 
135 private:
136  T *_TryToCreateData() const {
137  // Allocate an instance.
138  T *tmp = Factory::New();
139 
140  // Try to atomically set the pointer from null to tmp.
141  T *n = nullptr;
142  if (ARCH_LIKELY(_data.compare_exchange_strong(n, tmp)))
143  return tmp;
144 
145  // Another thread won the initialization race.
146  delete tmp;
147  return _data;
148  }
149 
150  mutable std::atomic<T *> _data;
151 };
152 
199 #define TF_MAKE_STATIC_DATA(Type, Name) \
200  static void TF_PP_CAT(Name,_Tf_StaticDataFactoryImpl)( \
201  std::remove_const_t<TF_PP_EAT_PARENS(Type)> *); \
202  namespace { \
203  struct TF_PP_CAT(Name,_Tf_StaticDataFactory) { \
204  static TF_PP_EAT_PARENS(Type) *New() { \
205  auto *p = new std::remove_const_t<TF_PP_EAT_PARENS(Type)>; \
206  TF_PP_CAT(Name,_Tf_StaticDataFactoryImpl)(p); \
207  return p; \
208  } \
209  }; \
210  } \
211  static TfStaticData< \
212  TF_PP_EAT_PARENS(Type), TF_PP_CAT(Name,_Tf_StaticDataFactory)> Name; \
213  static void TF_PP_CAT(Name,_Tf_StaticDataFactoryImpl)( \
214  std::remove_const_t<TF_PP_EAT_PARENS(Type)> *Name)
215 
216 PXR_NAMESPACE_CLOSE_SCOPE
217 
218 #endif
bool IsInitialized() const
Return true if the underlying data object is created and initialized.
Definition: staticData.h:133
T * Get() const
Return a pointer to the underlying object, creating and initializing it if necessary.
Definition: staticData.h:126
Compiler hints.
Create or return a previously created object instance of global data.
Definition: staticData.h:114
T * operator->() const
Return a pointer to the underlying data object.
Definition: staticData.h:118
T & operator *() const
Member lookup.
Definition: staticData.h:122