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 /// #include <hboost/noncopyable.hpp>
61 ///
62 /// class Registry : hboost::noncopyable {
63 /// public:
64 /// static Registry& GetInstance() {
65 /// return TfSingleton<Registry>::GetInstance();
66 /// }
67 ///
68 /// ...
69 ///
70 /// private:
71 /// Registry();
72 /// ~Registry();
73 ///
74 /// friend class TfSingleton<Registry>;
75 /// };
76 ///
77 /// // file: Registry.cpp
78 /// #include "common/astrology/registry.h"
79 /// #include "pxr/base/tf/instantiateSingleton.h"
80 ///
81 /// TF_INSTANTIATE_SINGLETON(Registry);
82 ///
83 ///
84 /// // file: RandomCode.cpp
85 /// #include "common/astrology/registry.h"
86 ///
87 /// void Code() {
88 /// Registry& r = Registry::GetInstance();
89 /// r.Lookup(...);
90 /// ...
91 /// }
92 /// \endcode
93 ///
94 /// The constructor and destructor are declared private, and the singleton
95 /// object will typically derive off of \c hboost::noncopyable to prevent
96 /// copying. Note that singleton objects quite commonly also make use of \c
97 /// TfRegistryManager to acquire the data they need throughout a program.
98 ///
99 /// The friend class \c TfSingleton<Registry> is the only class allowed to
100 /// create an instance of a Registry. The helper function \c
101 /// Registry::GetInstance() is for convenience only; one can just as well call
102 /// the longer \c TfSingleton<Registry>::GetInstance() to obtain a reference
103 /// to the sole instance of the registry.
104 
105 #include "pxr/pxr.h"
106 #include "pxr/base/arch/hints.h"
107 #include "pxr/base/arch/pragmas.h"
109 
110 #include <mutex>
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() {
139  // Suppress warnings from clang. TfSingletons are explicitly
140  // instantiated, so the warning around this usage is a false positive.
142  return ARCH_LIKELY(_instance) ? *_instance : _CreateInstance();
144  }
145 
146  /// Return whether or not the single object of type \c T is currently in
147  /// existence.
148  ///
149  /// This call tests whether or not the singleton currently exists.
150  static bool CurrentlyExists() {
151  return _instance ? true : false;
152  }
153 
154  /// Indicate that the sole instance object has already been created.
155  ///
156  /// This function is public, but can only be called usefully from within
157  /// the class T itself. This function is used to allow the constructor of
158  /// T to indicate that the sole instance of T has been created, and that
159  /// future calls to \c GetInstance() can immediately return \p instance.
160  ///
161  /// The need for this function occurs when the constructor of \c T
162  /// generates a call chain that leads to calling \c
163  /// TfSingleton<T>::GetInstance(). Until the constructor for \c T has
164  /// finished, however, \c TfSingleton<T>::GetInstance() is unable to
165  /// return a value. Calling \c SetInstanceConstructed() allows future
166  /// calls to \c TfSingleton<T>::GetInstance() to return before \c T's
167  /// constructor has finished.
168  ///
169  /// Be sure that \c T has been constructed (enough) before calling this
170  /// function. Calling this function anyplace but within the call chain of
171  /// \c T's constructor will generate a fatal coding error.
172  static void SetInstanceConstructed(T& instance) {
173  if (_instance)
174  TF_FATAL_ERROR("this function may not be called after "
175  "GetInstance() has completed");
176  _instance = &instance;
177  }
178 
179  /// Destroy the sole instance object of type \c T, if it exists.
180  ///
181  /// A singleton can be destroyed by a call to \c DeleteInstance. This call
182  /// is threadsafe in the sense that competing simultaneous calls will not
183  /// result in double deletion; however, it is up to the user to ensure
184  /// that the instance is not being used in one thread during an attempt to
185  /// delete the instance from another thread. After being destroyed, a
186  /// call to \c GetInstance() will create a new instance.
187  static void DeleteInstance() {
188  if (_instance)
189  _DestroyInstance();
190  }
191 private:
192  static T& _CreateInstance();
193  static void _DestroyInstance();
194  static T* _instance;
197  static std::mutex* _mutex;
199 };
200 
202 
203 #endif
#define ARCH_LIKELY(x)
Definition: hints.h:46
static T & GetInstance()
Definition: singleton.h:137
#define ARCH_PRAGMA_POP
Definition: pragmas.h:167
static void SetInstanceConstructed(T &instance)
Definition: singleton.h:172
#define ARCH_PRAGMA_PUSH
Definition: pragmas.h:163
#define TF_FATAL_ERROR
#define ARCH_PRAGMA_UNDEFINED_VAR_TEMPLATE
Definition: pragmas.h:251
static void DeleteInstance()
Definition: singleton.h:187
static bool CurrentlyExists()
Definition: singleton.h:150
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1394
#define ARCH_PRAGMA_NEEDS_EXPORT_INTERFACE
Definition: pragmas.h:211
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91