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 
97 /// \class TfSingleton
98 /// \ingroup group_tf_ObjectCreation
99 ///
100 /// Manage a single instance of an object (see
101 ///
102 /// \ref TfSingleton_typicalUse "Typical Use" for a canonical example).
103 ///
104 template <class T>
105 class TfSingleton {
106 public:
107  /// Return a reference to an object of type \c T, creating it if
108  /// necessary.
109  ///
110  /// When \c GetInstance() is called for the first time, it creates an
111  /// object of type \c T, and returns a reference to it. The type in
112  /// question must have a default constructor (i.e. a constructor taking no
113  /// arguments).
114  ///
115  /// Subsequent calls to \c GetInstance() return a reference to the same
116  /// object. This call is threadsafe; simultaneous attempts to create an
117  /// object result in only one object being created; locking beyond this
118  /// (for example, letting only one thread at a time call a member
119  /// function) are the responsibility of the class author.
120  inline static T& GetInstance() {
121  // Suppress undefined-var-template warnings from clang; _instance
122  // is expected to be instantiated in another translation unit via
123  // the TF_INSTANTIATE_SINGLETON macro.
126  T *p = _instance.load();
127  if (!p) {
128  p = _CreateInstance(_instance);
129  }
131  return *p;
132  }
133 
134  /// Return whether or not the single object of type \c T is currently in
135  /// existence.
136  ///
137  /// This call tests whether or not the singleton currently exists.
138  inline static bool CurrentlyExists() {
139  // Suppress undefined-var-template warnings from clang; _instance
140  // is expected to be instantiated in another translation unit via
141  // the TF_INSTANTIATE_SINGLETON macro.
144  return static_cast<bool>(_instance.load());
146  }
147 
148  /// Indicate that the sole instance object has already been created.
149  ///
150  /// This function is public, but can only be called usefully from within
151  /// the class T itself. This function is used to allow the constructor of
152  /// T to indicate that the sole instance of T has been created, and that
153  /// future calls to \c GetInstance() can immediately return \p instance.
154  ///
155  /// The need for this function occurs when the constructor of \c T
156  /// generates a call chain that leads to calling \c
157  /// TfSingleton<T>::GetInstance(). Until the constructor for \c T has
158  /// finished, however, \c TfSingleton<T>::GetInstance() is unable to
159  /// return a value. Calling \c SetInstanceConstructed() allows future
160  /// calls to \c TfSingleton<T>::GetInstance() to return before \c T's
161  /// constructor has finished.
162  ///
163  /// Be sure that \c T has been constructed (enough) before calling this
164  /// function. Calling this function anyplace but within the call chain of
165  /// \c T's constructor will generate a fatal coding error.
166  inline static void SetInstanceConstructed(T& instance);
167 
168  /// Destroy the sole instance object of type \c T, if it exists.
169  ///
170  /// A singleton can be destroyed by a call to \c DeleteInstance. This call
171  /// is threadsafe in the sense that competing simultaneous calls will not
172  /// result in double deletion; however, it is up to the user to ensure
173  /// that the instance is not being used in one thread during an attempt to
174  /// delete the instance from another thread. After being destroyed, a
175  /// call to \c GetInstance() will create a new instance.
176  inline static void DeleteInstance();
177 
178 private:
179  static T *_CreateInstance(std::atomic<T *> &instance);
180 
181  static std::atomic<T *> _instance;
182 };
183 
185 
186 #endif
static T & GetInstance()
Definition: singleton.h:120
#define ARCH_PRAGMA_POP
Definition: pragmas.h:159
#define ARCH_PRAGMA_PUSH
Definition: pragmas.h:155
#define ARCH_PRAGMA_UNDEFINED_VAR_TEMPLATE
Definition: pragmas.h:251
static void SetInstanceConstructed(T &instance)
static bool CurrentlyExists()
Definition: singleton.h:138
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
static void DeleteInstance()