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 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_SINGLETON_H
25 #define PXR_BASE_TF_SINGLETON_H
26 
27 /// \file tf/singleton.h
28 /// \ingroup group_tf_ObjectCreation
29 /// Manage a single instance of an object.
30 ///
31 /// Many classes (for example, registries) should have only a single, globally
32 /// available instance that is created as needed on demand. This is a classic
33 /// design pattern known as a \e singleton. Additionally, creation of this
34 /// class (though not access to it per se) must be made threadsafe.
35 ///
36 /// There are two possibilities in creating a singleton: you can create a
37 /// class all of whose member functions and variables are static, and let
38 /// users access this class. Unfortunately, instantiating the static
39 /// variables of this class is prone to difficulty; more importantly, should
40 /// you change your mind and wish to allow multiple instances of the class,
41 /// much rewriting follows.
42 ///
43 /// A better solution is to define the class with regular members and
44 /// variables, and then permit only a single instance of the class to exist.
45 /// This is the philosophy embodied by the \c TfSingleton template. It takes
46 /// care of both multithreaded initialization and initialization before main;
47 /// the cost of this is quite low (a single boolean comparison to access the
48 /// instanced object after initial creation). The \c TfSingleton template
49 /// works in conjunction with a macro in the source file
50 /// TF_INSTANTIATE_SINGLETON(), which is itself defined by including the file
51 /// "pxr/base/tf/instantiateSingleton.h".
52 ///
53 /// \anchor TfSingleton_typicalUse
54 /// <B> Typical Use </B>
55 ///
56 /// The typical use of \c TfSingleton is as follows:
57 /// \code
58 /// // file: registry.h
59 /// #include "pxr/base/tf/singleton.h"
60 ///
61 /// class Registry {
62 /// Registry(const Registry&) = delete;
63 /// Registry& operator=(const Registry&) = delete;
64 /// public:
65 /// static Registry& GetInstance() {
66 /// return TfSingleton<Registry>::GetInstance();
67 /// }
68 ///
69 /// ...
70 ///
71 /// private:
72 /// Registry();
73 /// ~Registry();
74 ///
75 /// friend class TfSingleton<Registry>;
76 /// };
77 ///
78 /// // file: Registry.cpp
79 /// #include "common/astrology/registry.h"
80 /// #include "pxr/base/tf/instantiateSingleton.h"
81 ///
82 /// TF_INSTANTIATE_SINGLETON(Registry);
83 ///
84 ///
85 /// // file: RandomCode.cpp
86 /// #include "common/astrology/registry.h"
87 ///
88 /// void Code() {
89 /// Registry& r = Registry::GetInstance();
90 /// r.Lookup(...);
91 /// ...
92 /// }
93 /// \endcode
94 ///
95 /// The constructor and destructor are declared private, and the singleton
96 /// object will typically delete its copy constructor and assignment operator
97 /// to prevent copying. Note that singleton objects quite commonly also make
98 /// use of \c TfRegistryManager to acquire the data they need throughout a
99 /// program.
100 ///
101 /// The friend class \c TfSingleton<Registry> is the only class allowed to
102 /// create an instance of a Registry. The helper function \c
103 /// Registry::GetInstance() is for convenience only; one can just as well call
104 /// the longer \c TfSingleton<Registry>::GetInstance() to obtain a reference
105 /// to the sole instance of the registry.
106 
107 #include "pxr/pxr.h"
108 #include "pxr/base/arch/pragmas.h"
109 
110 #include <atomic>
111 
113 
114 /// \class TfSingleton
115 /// \ingroup group_tf_ObjectCreation
116 ///
117 /// Manage a single instance of an object (see
118 ///
119 /// \ref TfSingleton_typicalUse "Typical Use" for a canonical example).
120 ///
121 template <class T>
122 class TfSingleton {
123 public:
124  /// Return a reference to an object of type \c T, creating it if
125  /// necessary.
126  ///
127  /// When \c GetInstance() is called for the first time, it creates an
128  /// object of type \c T, and returns a reference to it. The type in
129  /// question must have a default constructor (i.e. a constructor taking no
130  /// arguments).
131  ///
132  /// Subsequent calls to \c GetInstance() return a reference to the same
133  /// object. This call is threadsafe; simultaneous attempts to create an
134  /// object result in only one object being created; locking beyond this
135  /// (for example, letting only one thread at a time call a member
136  /// function) are the responsibility of the class author.
137  inline static T& GetInstance() {
138  // Suppress undefined-var-template warnings from clang; _instance
139  // is expected to be instantiated in another translation unit via
140  // the TF_INSTANTIATE_SINGLETON macro.
143  T *p = _instance.load();
144  if (!p) {
145  p = _CreateInstance(_instance);
146  }
148  return *p;
149  }
150 
151  /// Return whether or not the single object of type \c T is currently in
152  /// existence.
153  ///
154  /// This call tests whether or not the singleton currently exists.
155  inline static bool CurrentlyExists() {
156  // Suppress undefined-var-template warnings from clang; _instance
157  // is expected to be instantiated in another translation unit via
158  // the TF_INSTANTIATE_SINGLETON macro.
161  return static_cast<bool>(_instance.load());
163  }
164 
165  /// Indicate that the sole instance object has already been created.
166  ///
167  /// This function is public, but can only be called usefully from within
168  /// the class T itself. This function is used to allow the constructor of
169  /// T to indicate that the sole instance of T has been created, and that
170  /// future calls to \c GetInstance() can immediately return \p instance.
171  ///
172  /// The need for this function occurs when the constructor of \c T
173  /// generates a call chain that leads to calling \c
174  /// TfSingleton<T>::GetInstance(). Until the constructor for \c T has
175  /// finished, however, \c TfSingleton<T>::GetInstance() is unable to
176  /// return a value. Calling \c SetInstanceConstructed() allows future
177  /// calls to \c TfSingleton<T>::GetInstance() to return before \c T's
178  /// constructor has finished.
179  ///
180  /// Be sure that \c T has been constructed (enough) before calling this
181  /// function. Calling this function anyplace but within the call chain of
182  /// \c T's constructor will generate a fatal coding error.
183  inline static void SetInstanceConstructed(T& instance);
184 
185  /// Destroy the sole instance object of type \c T, if it exists.
186  ///
187  /// A singleton can be destroyed by a call to \c DeleteInstance. This call
188  /// is threadsafe in the sense that competing simultaneous calls will not
189  /// result in double deletion; however, it is up to the user to ensure
190  /// that the instance is not being used in one thread during an attempt to
191  /// delete the instance from another thread. After being destroyed, a
192  /// call to \c GetInstance() will create a new instance.
193  inline static void DeleteInstance();
194 
195 private:
196  static T *_CreateInstance(std::atomic<T *> &instance);
197 
198  static std::atomic<T *> _instance;
199 };
200 
202 
203 #endif
static T & GetInstance()
Definition: singleton.h:137
#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:258
static void SetInstanceConstructed(T &instance)
static bool CurrentlyExists()
Definition: singleton.h:155
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1441
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
static void DeleteInstance()