2 * Copyright (c) 2005, Eric Crahen
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is furnished
9 * to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 #ifndef __ZTSINGLETON_H__
24 #define __ZTSINGLETON_H__
26 #include "zthread/Guard.h"
27 #include "zthread/FastMutex.h"
33 // This policy controls how an object is instantiated
34 // as well as how and when its destroyed. Phoenix-style
35 // singletons are not supported easily with type of policy,
36 // this is intentional since I do not believe that is in
37 // the true spirit of a singleton.
39 // InstantiationPolicContract {
41 // create(pointer_type&)
46 * @class LocalStaticInstantiation
47 * @author Eric Crahen <http://www.code-foo.com>
48 * @date <2003-07-16T17:57:45-0400>
51 * The LocalStaticInstantiation policy allows the creation
52 * and lifetime of an instance of a particular type
53 * to be managed using static local values. This will
54 * abide by the standard C++ rules for static objects
57 class LocalStaticInstantiation
{
61 * Create an instance of an object, using a local static. The
62 * object will be destroyed by the system.
64 * @param ptr reference to location to receive the address
65 * of the allocated object
68 static void create(T
*& ptr
) {
79 class StaticInstantiationHelper
{
81 friend class StaticInstantiation
;
88 T StaticInstantiationHelper
<T
>::instance
;
91 * @class StaticInstantiation
92 * @author Eric Crahen <http://www.code-foo.com>
93 * @date <2003-07-16T17:57:45-0400>
96 * The StaticInstantiation policy allows the creation
97 * and lifetime of an instance of a particular type
98 * to be managed using static instantiation. This will
99 * abide by the standard C++ rules for static objects
102 class StaticInstantiation
{
106 * Create an instance of an object using by simply allocating it statically.
108 * @param ptr reference to location to receive the address
109 * of the allocated object
112 static void create(T
*& ptr
) {
113 ptr
= &StaticInstantiationHelper
<T
>::instance
;
118 //! SingletonDestroyer
126 Destroyer(T
* q
) : doomed(q
) {
135 Destroyer
<T
>::~Destroyer() {
150 * @class LazyInstantiation
151 * @author Eric Crahen <http://www.code-foo.com>
152 * @date <2003-07-16T17:57:45-0400>
155 * The LazyInstantiation policy allows the creation
156 * and lifetime of an instance of a particular type
157 * to be managed using dynamic allocation and a singleton
158 * destroyer. This will abide by the standard C++ rules
159 * for static objects lifetimes.
161 class LazyInstantiation
{
165 * Create an instance of an object, using new, that will be
166 * destroyed when an associated Destroyer object (allocated
167 * statically) goes out of scope.
169 * @param ptr reference to location to receive the address
170 * of the allocated object
173 static void create(T
*& ptr
) {
176 static Destroyer
<T
> destroyer(ptr
);
185 * @author Eric Crahen <http://www.code-foo.com>
186 * @date <2003-07-16T17:57:45-0400>
189 * Based on the work of John Vlissidles in his book 'Pattern Hatching'
190 * an article by Douglas Schmidtt on double-checked locking and policy
191 * templates described by Andrei Alexandrescu.
193 * This is a thread safe wrapper for creating Singleton classes. The
194 * synchronization method and instantiation methods can be changed
195 * easily by specifying different policy implementations as the
196 * templates parameters.
200 * // Most common Singleton
201 * Singletion<LonesomeType>
203 * // Singleton that uses static storage
204 * Singletion<LonesomeType, StaticInstantiation>
206 * // Single-threaded singleton that uses static storage (Meyers-like)
207 * Singletion<LonesomeType, LocalStaticInstantiation, NotLocked>
211 template <class T
, class InstantiationPolicy
=LazyInstantiation
, class LockType
=FastMutex
>
212 class Singleton
: private InstantiationPolicy
, private NonCopyable
{
216 * Provide access to the single instance through double-checked locking
218 * @return T* single instance
220 static T
* instance();
224 template <class T
, class InstantiationPolicy
, class LockType
>
225 T
* Singleton
<T
, InstantiationPolicy
, LockType
>::instance() {
227 // Uses local static storage to avoid static construction
228 // sequence issues. (regaring when the lock is created)
230 static LockType lock
;
234 Guard
<LockType
, LockedScope
> g(lock
);
236 InstantiationPolicy::create(ptr
);
240 return const_cast<T
*>(ptr
);