HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
instantiateSingleton.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 /*
25  * This header is not meant to be included in a .h file.
26  * Complain if we see this header twice through.
27  */
28 
29 #ifdef PXR_BASE_TF_INSTANTIATE_SINGLETON_H
30 #error This file should only be included once in any given source (.cpp) file.
31 #endif
32 
33 #define PXR_BASE_TF_INSTANTIATE_SINGLETON_H
34 
35 /// \file tf/instantiateSingleton.h
36 /// \ingroup group_tf_ObjectCreation
37 /// Manage a single instance of an object.
38 
39 #include "pxr/pxr.h"
40 #include "pxr/base/tf/singleton.h"
42 #include "pxr/base/tf/mallocTag.h"
43 #include "pxr/base/arch/demangle.h"
44 
45 #include <thread>
46 
48 
49 template <class T> std::atomic<T *> TfSingleton<T>::_instance;
50 
51 template <class T>
52 void
54 {
55  if (_instance.exchange(&instance) != nullptr) {
56  TF_FATAL_ERROR("this function may not be called after "
57  "GetInstance() or another SetInstanceConstructed() "
58  "has completed");
59  }
60 }
61 
62 template <class T>
63 T *
64 TfSingleton<T>::_CreateInstance(std::atomic<T *> &instance)
65 {
66  static std::atomic<bool> isInitializing;
67 
68  TfAutoMallocTag2 tag("Tf", "TfSingleton::_CreateInstance",
69  "Create Singleton " + ArchGetDemangled<T>());
70 
71  // Try to take isInitializing false -> true. If we do it, then check to see
72  // if we don't yet have an instance. If we don't, then we get to create it.
73  // Otherwise we just wait until the instance shows up.
74  if (isInitializing.exchange(true) == false) {
75  // Do we not yet have an instance?
76  if (!instance) {
77  // Create it. The constructor may set instance via
78  // SetInstanceConstructed(), so check for that.
79  T *newInst = new T;
80 
81  T *curInst = instance.load();
82  if (curInst) {
83  if (curInst != newInst) {
84  TF_FATAL_ERROR("race detected setting singleton instance");
85  }
86  }
87  else {
88  TF_AXIOM(instance.exchange(newInst) == nullptr);
89  }
90  }
91  isInitializing = false;
92  }
93  else {
94  while (!instance) {
96  }
97  }
98 
99  return instance.load();
100 }
101 
102 template <typename T>
103 void
105 {
106  // Try to swap out a non-null instance for nullptr -- if we do it, we delete
107  // it.
108  T *instance = _instance.load();
109  while (instance && !_instance.compare_exchange_weak(instance, nullptr)) {
111  }
112  delete instance;
113 }
114 
115 /// Source file definition that a type is being used as a singleton.
116 ///
117 /// To use a type \c T in conjunction with \c TfSingleton, add
118 /// TF_INSTANTIATE_SINGLETON(T) in one source file (typically the .cpp) file
119 /// for class \c T.
120 ///
121 /// \hideinitializer
122 #define TF_INSTANTIATE_SINGLETON(T) \
123  template class PXR_NS_GLOBAL::TfSingleton<T>
124 
125 
#define TF_FATAL_ERROR
static void SetInstanceConstructed(T &instance)
#define TF_AXIOM(cond)
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1432
void yield() noexcept
Definition: thread.h:93
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
static void DeleteInstance()