Initial Patch of Auction House bot rev. 135
[auctionmangos.git] / dep / include / zthread / Singleton.h
blobb66c9d0898a01056d0ba55c67df1536ccf6964e2
1 /*
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"
28 #include <assert.h>
30 namespace ZThread {
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&)
43 // }
45 /**
46 * @class LocalStaticInstantiation
47 * @author Eric Crahen <http://www.code-foo.com>
48 * @date <2003-07-16T17:57:45-0400>
49 * @version 2.2.0
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
55 * lifetimes.
57 class LocalStaticInstantiation {
58 protected:
60 /**
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
67 template <class T>
68 static void create(T*& ptr) {
70 static T instance;
71 ptr = &instance;
77 //! Helper class
78 template <class T>
79 class StaticInstantiationHelper {
80 //! Friend class
81 friend class StaticInstantiation;
82 //! Holder
83 static T instance;
87 template <class T>
88 T StaticInstantiationHelper<T>::instance;
90 /**
91 * @class StaticInstantiation
92 * @author Eric Crahen <http://www.code-foo.com>
93 * @date <2003-07-16T17:57:45-0400>
94 * @version 2.2.0
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
100 * lifetimes.
102 class StaticInstantiation {
103 protected:
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
111 template <class T>
112 static void create(T*& ptr) {
113 ptr = &StaticInstantiationHelper<T>::instance;
118 //! SingletonDestroyer
119 template <class T>
120 class Destroyer {
122 T* doomed;
124 public:
126 Destroyer(T* q) : doomed(q) {
127 assert(doomed);
130 ~Destroyer();
134 template <class T>
135 Destroyer<T>::~Destroyer() {
137 try {
139 if(doomed)
140 delete doomed;
142 } catch(...) { }
144 doomed = 0;
150 * @class LazyInstantiation
151 * @author Eric Crahen <http://www.code-foo.com>
152 * @date <2003-07-16T17:57:45-0400>
153 * @version 2.2.0
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 {
162 protected:
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
172 template <class T>
173 static void create(T*& ptr) {
175 ptr = new T;
176 static Destroyer<T> destroyer(ptr);
184 * @class Singleton
185 * @author Eric Crahen <http://www.code-foo.com>
186 * @date <2003-07-16T17:57:45-0400>
187 * @version 2.2.0
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.
198 * @code
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>
209 * @endcode
211 template <class T, class InstantiationPolicy=LazyInstantiation, class LockType=FastMutex>
212 class Singleton : private InstantiationPolicy, private NonCopyable {
213 public:
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)
229 static T* ptr = 0;
230 static LockType lock;
232 if(!ptr) {
234 Guard<LockType, LockedScope> g(lock);
235 if(!ptr)
236 InstantiationPolicy::create(ptr);
240 return const_cast<T*>(ptr);
247 #endif