root/trunk/dep/include/zthread/Singleton.h @ 2

Revision 2, 6.0 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

Line 
1/*
2 * Copyright (c) 2005, Eric Crahen
3 *
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:
10 *
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
13 *
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.
20 *
21 */
22
23#ifndef __ZTSINGLETON_H__
24#define __ZTSINGLETON_H__
25
26#include "zthread/Guard.h"
27#include "zthread/FastMutex.h"
28#include <assert.h>
29
30namespace ZThread {
31
32//
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.
38//
39// InstantiationPolicContract {
40//
41//  create(pointer_type&)
42//
43// }
44
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
50 *
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.
56 */
57class LocalStaticInstantiation {
58protected:
59
60  /**
61   * Create an instance of an object, using a local static. The
62   * object will be destroyed by the system.
63   *
64   * @param ptr reference to location to receive the address
65   * of the allocated object
66   */
67  template <class T>
68  static void create(T*& ptr) {
69   
70    static T instance;
71    ptr = &instance;
72
73  }
74
75};
76
77//! Helper class
78template <class T>
79class StaticInstantiationHelper {
80  //! Friend class
81  friend class StaticInstantiation;
82  //! Holder
83  static T instance;
84
85 };
86
87 template <class T>
88 T StaticInstantiationHelper<T>::instance;
89
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
95 *
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.
101 */
102class StaticInstantiation {
103protected:
104
105  /**
106   * Create an instance of an object using by simply allocating it statically.
107   *
108   * @param ptr reference to location to receive the address
109   * of the allocated object
110   */
111  template <class T>
112  static void create(T*& ptr) {
113    ptr = &StaticInstantiationHelper<T>::instance;
114  }
115
116};
117
118//! SingletonDestroyer
119template <class T>
120class Destroyer {
121 
122  T* doomed;
123 
124 public:
125 
126  Destroyer(T* q) : doomed(q) {
127    assert(doomed);
128  }
129 
130  ~Destroyer();
131
132};
133
134template <class T>
135Destroyer<T>::~Destroyer() {
136 
137  try {
138   
139    if(doomed)
140      delete doomed;
141   
142  } catch(...) { }
143 
144  doomed = 0;
145 
146}   
147
148
149/**
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
154 *
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.
160 */
161class LazyInstantiation {
162protected:
163
164  /**
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.
168   *
169   * @param ptr reference to location to receive the address
170   * of the allocated object
171   */
172  template <class T>
173  static void create(T*& ptr) {
174 
175    ptr = new T;
176    static Destroyer<T> destroyer(ptr);
177 
178  }
179
180};
181
182 
183/**
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
188 *
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.
192 *
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.
197 *
198 * @code
199 *
200 * // Most common Singleton
201 * Singletion<LonesomeType>
202 *
203 * // Singleton that uses static storage
204 * Singletion<LonesomeType, StaticInstantiation>
205 *
206 * // Single-threaded singleton that uses static storage (Meyers-like)
207 * Singletion<LonesomeType, LocalStaticInstantiation, NotLocked>
208 *
209 * @endcode
210 */
211template <class T, class InstantiationPolicy=LazyInstantiation, class LockType=FastMutex>
212class Singleton : private InstantiationPolicy, private NonCopyable {
213public:
214
215  /**
216   * Provide access to the single instance through double-checked locking
217   *
218   * @return T* single instance
219   */
220  static T* instance();
221
222};
223
224template <class T, class InstantiationPolicy, class LockType>
225T* Singleton<T, InstantiationPolicy, LockType>::instance() {
226
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;
231
232    if(!ptr) {
233
234      Guard<LockType, LockedScope> g(lock);
235      if(!ptr)       
236        InstantiationPolicy::create(ptr);
237
238    }
239   
240    return const_cast<T*>(ptr);
241   
242  }
243
244
245};
246
247#endif
248
249
Note: See TracBrowser for help on using the browser.