Loading...
Searching...
No Matches
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
38
39#include "pxr/pxr.h"
44
45#include <thread>
46
47PXR_NAMESPACE_OPEN_SCOPE
48
49template <class T> std::atomic<T *> TfSingleton<T>::_instance;
50
51template <class T>
52void
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
62template <class T>
63T *
64TfSingleton<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) {
95 std::this_thread::yield();
96 }
97 }
98
99 return instance.load();
100}
101
102template <typename T>
103void
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)) {
110 std::this_thread::yield();
111 }
112 delete instance;
113}
114
122#define TF_INSTANTIATE_SINGLETON(T) \
123 template class PXR_NS_GLOBAL::TfSingleton<T>
124
125
126PXR_NAMESPACE_CLOSE_SCOPE
Scoped (i.e.
Definition: mallocTag.h:255
Manage a single instance of an object (see.
Definition: singleton.h:122
static void DeleteInstance()
Destroy the sole instance object of type T, if it exists.
static void SetInstanceConstructed(T &instance)
Indicate that the sole instance object has already been created.
Demangle C++ typenames generated by the typeid() facility.
Stripped down version of diagnostic.h that doesn't define std::string.
#define TF_AXIOM(cond)
Aborts if the condition cond is not met.
Definition: diagnostic.h:210
#define TF_FATAL_ERROR(fmt, args)
Issue a fatal error and end the program.
Definition: diagnostic.h:108
Manage a single instance of an object.