HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
singleton.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_BASE_TF_SINGLETON_H
8 #define PXR_BASE_TF_SINGLETON_H
9 
10 /// \file tf/singleton.h
11 /// \ingroup group_tf_ObjectCreation
12 /// Manage a single instance of an object.
13 ///
14 /// Many classes (for example, registries) should have only a single, globally
15 /// available instance that is created as needed on demand. This is a classic
16 /// design pattern known as a \e singleton. Additionally, creation of this
17 /// class (though not access to it per se) must be made threadsafe.
18 ///
19 /// There are two possibilities in creating a singleton: you can create a
20 /// class all of whose member functions and variables are static, and let
21 /// users access this class. Unfortunately, instantiating the static
22 /// variables of this class is prone to difficulty; more importantly, should
23 /// you change your mind and wish to allow multiple instances of the class,
24 /// much rewriting follows.
25 ///
26 /// A better solution is to define the class with regular members and
27 /// variables, and then permit only a single instance of the class to exist.
28 /// This is the philosophy embodied by the \c TfSingleton template. It takes
29 /// care of both multithreaded initialization and initialization before main;
30 /// the cost of this is quite low (a single boolean comparison to access the
31 /// instanced object after initial creation). The \c TfSingleton template
32 /// works in conjunction with a macro in the source file
33 /// TF_INSTANTIATE_SINGLETON(), which is itself defined by including the file
34 /// "pxr/base/tf/instantiateSingleton.h".
35 ///
36 /// \anchor TfSingleton_typicalUse
37 /// <B> Typical Use </B>
38 ///
39 /// The typical use of \c TfSingleton is as follows:
40 /// \code
41 /// // file: registry.h
42 /// #include "pxr/base/tf/singleton.h"
43 ///
44 /// class Registry {
45 /// Registry(const Registry&) = delete;
46 /// Registry& operator=(const Registry&) = delete;
47 /// public:
48 /// static Registry& GetInstance() {
49 /// return TfSingleton<Registry>::GetInstance();
50 /// }
51 ///
52 /// ...
53 ///
54 /// private:
55 /// Registry();
56 /// ~Registry();
57 ///
58 /// friend class TfSingleton<Registry>;
59 /// };
60 ///
61 /// // file: Registry.cpp
62 /// #include "common/astrology/registry.h"
63 /// #include "pxr/base/tf/instantiateSingleton.h"
64 ///
65 /// TF_INSTANTIATE_SINGLETON(Registry);
66 ///
67 ///
68 /// // file: RandomCode.cpp
69 /// #include "common/astrology/registry.h"
70 ///
71 /// void Code() {
72 /// Registry& r = Registry::GetInstance();
73 /// r.Lookup(...);
74 /// ...
75 /// }
76 /// \endcode
77 ///
78 /// The constructor and destructor are declared private, and the singleton
79 /// object will typically delete its copy constructor and assignment operator
80 /// to prevent copying. Note that singleton objects quite commonly also make
81 /// use of \c TfRegistryManager to acquire the data they need throughout a
82 /// program.
83 ///
84 /// The friend class \c TfSingleton<Registry> is the only class allowed to
85 /// create an instance of a Registry. The helper function \c
86 /// Registry::GetInstance() is for convenience only; one can just as well call
87 /// the longer \c TfSingleton<Registry>::GetInstance() to obtain a reference
88 /// to the sole instance of the registry.
89 
90 #include "pxr/pxr.h"
91 #include "pxr/base/arch/pragmas.h"
92 
93 #include <atomic>
94 
96 
98 
99 /// \class TfSingleton
100 /// \ingroup group_tf_ObjectCreation
101 ///
102 /// Manage a single instance of an object (see
103 ///
104 /// \ref TfSingleton_typicalUse "Typical Use" for a canonical example).
105 ///
106 template <class T>
107 class TfSingleton {
108 public:
109  /// Return a reference to an object of type \c T, creating it if
110  /// necessary.
111  ///
112  /// When \c GetInstance() is called for the first time, it creates an
113  /// object of type \c T, and returns a reference to it. The type in
114  /// question must have a default constructor (i.e. a constructor taking no
115  /// arguments).
116  ///
117  /// Subsequent calls to \c GetInstance() return a reference to the same
118  /// object. This call is threadsafe; simultaneous attempts to create an
119  /// object result in only one object being created; locking beyond this
120  /// (for example, letting only one thread at a time call a member
121  /// function) are the responsibility of the class author.
122  inline static T& GetInstance() {
123  // Suppress undefined-var-template warnings from clang; _instance
124  // is expected to be instantiated in another translation unit via
125  // the TF_INSTANTIATE_SINGLETON macro.
128  T *p = _instance.load();
129  if (!p) {
130  p = _CreateOrWaitForInstance(_instance);
131  }
133  return *p;
134  }
135 
136  /// Return whether or not the single object of type \c T is currently in
137  /// existence.
138  ///
139  /// This call tests whether or not the singleton currently exists.
140  inline static bool CurrentlyExists() {
141  // Suppress undefined-var-template warnings from clang; _instance
142  // is expected to be instantiated in another translation unit via
143  // the TF_INSTANTIATE_SINGLETON macro.
146  return static_cast<bool>(_instance.load());
148  }
149 
150  /// Indicate that the sole instance object has already been created.
151  ///
152  /// This function is public, but should only be called by \c T 's
153  /// constructor. It makes the instance available to the calling thread for
154  /// initialization purposes during the remainder of \c T 's construction.
155  /// In contrast, concurrent threads that call GetInstance() will continue to
156  /// wait until construction is fully complete before returning the instance.
157  ///
158  /// The need for this function occurs when \c T's constructor generates a
159  /// call chain that calls back to \c TfSingleton<T>::GetInstance(). Normally
160  /// calls to \c TfSingleton<T>::GetInstance() during \c T's construction
161  /// will wait for construction to complete. Calling \c
162  /// SetInstanceConstructed() lets future calls to \c
163  /// TfSingleton<T>::GetInstance() *by the same thread* that called
164  /// SetInstanceConstructed() to access the instance before \c T's
165  /// constructor has finished. This is useful when the singleton's
166  /// constuctor calls TfRegistryManager::SubscribeTo(), for example. The
167  /// invoked TF_REGISTRY_FUNCTION()s can successfully call GetInstance() to
168  /// access the singleton.
169  ///
170  /// Be sure that \c T has been constructed (enough) before calling this
171  /// function. Calling this function anywhere but within the call chain of \c
172  /// T's constructor will generate a fatal coding error.
173  inline static void SetInstanceConstructed(T& instance);
174 
175  /// Destroy the sole instance object of type \c T, if it exists.
176  ///
177  /// A singleton can be destroyed by a call to \c DeleteInstance. This call
178  /// is threadsafe in the sense that competing simultaneous calls will not
179  /// result in double deletion; however, it is up to the user to ensure
180  /// that the instance is not being used in one thread during an attempt to
181  /// delete the instance from another thread. After being destroyed, a
182  /// call to \c GetInstance() will create a new instance.
183  inline static void DeleteInstance();
184 
185 private:
186  static T *_CreateOrWaitForInstance(std::atomic<T *> &instance);
187 
188  static std::atomic<T *> _instance;
189  static std::atomic<Tf_SingletonInitState *> _initState;
190 };
191 
193 
194 #endif
static T & GetInstance()
Definition: singleton.h:122
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
#define ARCH_PRAGMA_POP
Definition: pragmas.h:170
#define ARCH_PRAGMA_PUSH
Definition: pragmas.h:166
#define ARCH_PRAGMA_UNDEFINED_VAR_TEMPLATE
Definition: pragmas.h:262
static void SetInstanceConstructed(T &instance)
static bool CurrentlyExists()
Definition: singleton.h:140
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
static void DeleteInstance()