Singleton.h

  1 ////////////////////////////////////////////////////////////////////////////////
  2 // The Loki Library
  3 // Copyright (c) 2001 by Andrei Alexandrescu
  4 // This code accompanies the book:
  5 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
  6 //     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
  7 // Permission to use, copy, modify, distribute and sell this software for any 
  8 //     purpose is hereby granted without fee, provided that the above copyright 
  9 //     notice appear in all copies and that both that copyright notice and this 
 10 //     permission notice appear in supporting documentation.
 11 // The author or Addison-Welsey Longman make no representations about the 
 12 //     suitability of this software for any purpose. It is provided "as is" 
 13 //     without express or implied warranty.
 14 ////////////////////////////////////////////////////////////////////////////////
 15 
 16 // Last update: June 20, 2001
 17 
 18 #ifndef SINGLETON_INC_
 19 #define SINGLETON_INC_
 20 
 21 #include "Threads.h"
 22 #include <algorithm>
 23 #include <stdexcept>
 24 #include <cassert>
 25 #include <cstdlib>
 26 #include <new>
 27 
 28 namespace Loki
 29 {
 30     namespace Private
 31     {
 32 ////////////////////////////////////////////////////////////////////////////////
 33 // class LifetimeTracker
 34 // Helper class for SetLongevity
 35 ////////////////////////////////////////////////////////////////////////////////
 36 
 37         class LifetimeTracker
 38         {
 39         public:
 40             LifetimeTracker(unsigned int x) : longevity_(x) 
 41             {}
 42             
 43             virtual ~LifetimeTracker() = 0;
 44             
 45             static bool Compare(const LifetimeTracker* lhs,
 46                 const LifetimeTracker* rhs)
 47             {
 48                 return rhs->longevity_ > lhs->longevity_;
 49             }
 50             
 51         private:
 52             unsigned int longevity_;
 53         };
 54         
 55         // Definition required
 56         inline LifetimeTracker::~LifetimeTracker() {} 
 57         
 58         // Helper data
 59         typedef LifetimeTracker** TrackerArray;
 60         extern TrackerArray pTrackerArray;
 61         extern unsigned int elements;
 62 
 63         // Helper destroyer function
 64         template <typename T>
 65         struct Deleter
 66         {
 67             static void Delete(T* pObj)
 68             { delete pObj; }
 69         };
 70 
 71         // Concrete lifetime tracker for objects of type T
 72         template <typename T, typename Destroyer>
 73         class ConcreteLifetimeTracker : public LifetimeTracker
 74         {
 75         public:
 76             ConcreteLifetimeTracker(T* p,unsigned int longevity, Destroyer d)
 77                 : LifetimeTracker(longevity)
 78                 , pTracked_(p)
 79                 , destroyer_(d)
 80             {}
 81             
 82             ~ConcreteLifetimeTracker()
 83             { destroyer_(pTracked_); }
 84             
 85         private:
 86             T* pTracked_;
 87             Destroyer destroyer_;
 88         };
 89 
 90         void AtExitFn(); // declaration needed below
 91     
 92     } // namespace Private
 93 
 94 ////////////////////////////////////////////////////////////////////////////////
 95 // function template SetLongevity
 96 // Assigns an object a longevity; ensures ordered destructions of objects 
 97 //     registered thusly during the exit sequence of the application
 98 ////////////////////////////////////////////////////////////////////////////////
 99 
100     template <typename T, typename Destroyer>
101     void SetLongevity(T* pDynObject, unsigned int longevity,
102         Destroyer d = Private::Deleter<T>::Delete)
103     {
104         using namespace Private;
105         
106         TrackerArray pNewArray = static_cast<TrackerArray>(
107                 std::realloc(pTrackerArray, elements + 1));
108         if (!pNewArray) throw std::bad_alloc();
109         
110         LifetimeTracker* p = new ConcreteLifetimeTracker<T, Destroyer>(
111             pDynObject, longevity, d);
112         
113         // Delayed assignment for exception safety
114         pTrackerArray = pNewArray;
115         
116         // Insert a pointer to the object into the queue
117         TrackerArray pos = std::upper_bound(
118             pTrackerArray, 
119             pTrackerArray + elements, 
120             p, 
121             LifetimeTracker::Compare);
122         std::copy_backward(
123             pos, 
124             pTrackerArray + elements,
125             pTrackerArray + elements + 1);
126         *pos = p;
127         ++elements;
128         
129         // Register a call to AtExitFn
130         std::atexit(Private::AtExitFn);
131     }
132 
133 ////////////////////////////////////////////////////////////////////////////////
134 // class template CreateUsingNew
135 // Implementation of the CreationPolicy used by SingletonHolder
136 // Creates objects using a straight call to the new operator 
137 ////////////////////////////////////////////////////////////////////////////////
138 
139     template <class T> struct CreateUsingNew
140     {
141         static T* Create()
142         { return new T; }
143         
144         static void Destroy(T* p)
145         { delete p; }
146     };
147     
148 ////////////////////////////////////////////////////////////////////////////////
149 // class template CreateUsingNew
150 // Implementation of the CreationPolicy used by SingletonHolder
151 // Creates objects using a call to std::malloc, followed by a call to the 
152 //     placement new operator
153 ////////////////////////////////////////////////////////////////////////////////
154 
155     template <class T> struct CreateUsingMalloc
156     {
157         static T* Create()
158         {
159             void* p = std::malloc(sizeof(T));
160             if (!p) return 0;
161             return new(p) T;
162         }
163         
164         static void Destroy(T* p)
165         {
166             p->~T();
167             std::free(p);
168         }
169     };
170     
171 ////////////////////////////////////////////////////////////////////////////////
172 // class template CreateStatic
173 // Implementation of the CreationPolicy used by SingletonHolder
174 // Creates an object in static memory
175 // Implementation is slightly nonportable because it uses the MaxAlign trick 
176 //     (an union of all types to ensure proper memory alignment). This trick is 
177 //     nonportable in theory but highly portable in practice.
178 ////////////////////////////////////////////////////////////////////////////////
179 
180     template <class T> struct CreateStatic
181     {
182         union MaxAlign
183         {
184             char t_[sizeof(T)];
185             short int shortInt_;
186             int int_;
187             long int longInt_;
188             float float_;
189             double double_;
190             long double longDouble_;
191             struct Test;
192             int Test::* pMember_;
193             int (Test::*pMemberFn_)(int);
194         };
195         
196         static T* Create()
197         {
198             static MaxAlign staticMemory_;
199             return new(&staticMemory_) T;
200         }
201         
202         static void Destroy(T* p)
203         {
204             p->~T();
205         }
206     };
207     
208 ////////////////////////////////////////////////////////////////////////////////
209 // class template DefaultLifetime
210 // Implementation of the LifetimePolicy used by SingletonHolder
211 // Schedules an object's destruction as per C++ rules
212 // Forwards to std::atexit
213 ////////////////////////////////////////////////////////////////////////////////
214 
215     template <class T>
216     struct DefaultLifetime
217     {
218         static void ScheduleDestruction(T*, void (*pFun)())
219         { std::atexit(pFun); }
220         
221         static void OnDeadReference()
222         { throw std::logic_error("Dead Reference Detected"); }
223     };
224 
225 ////////////////////////////////////////////////////////////////////////////////
226 // class template PhoenixSingleton
227 // Implementation of the LifetimePolicy used by SingletonHolder
228 // Schedules an object's destruction as per C++ rules, and it allows object 
229 //    recreation by not throwing an exception from OnDeadReference
230 ////////////////////////////////////////////////////////////////////////////////
231 
232     template <class T>
233     class PhoenixSingleton
234     {
235     public:
236         static void ScheduleDestruction(T*, void (*pFun)())
237         {
238 #ifndef ATEXIT_FIXED
239             if (!destroyedOnce_)
240 #endif
241                 std::atexit(pFun);
242         }
243         
244         static void OnDeadReference()
245         {
246 #ifndef ATEXIT_FIXED
247             destroyedOnce_ = true;
248 #endif
249         }
250         
251     private:
252 #ifndef ATEXIT_FIXED
253         static bool destroyedOnce_;
254 #endif
255     };
256     
257 #ifndef ATEXIT_FIXED
258     template <class T> bool PhoenixSingleton<T>::destroyedOnce_ = false;
259 #endif
260         
261 ////////////////////////////////////////////////////////////////////////////////
262 // class template Adapter
263 // Helper for SingletonWithLongevity below
264 ////////////////////////////////////////////////////////////////////////////////
265 
266     namespace Private
267     {
268         template <class T>
269         struct Adapter
270         {
271             void operator()(T*) { return pFun_(); }
272             void (*pFun_)();
273         };
274     }
275 
276 ////////////////////////////////////////////////////////////////////////////////
277 // class template SingletonWithLongevity
278 // Implementation of the LifetimePolicy used by SingletonHolder
279 // Schedules an object's destruction in order of their longevities
280 // Assumes a visible function GetLongevity(T*) that returns the longevity of the
281 //     object
282 ////////////////////////////////////////////////////////////////////////////////
283 
284     template <class T>
285     class SingletonWithLongevity
286     {
287     public:
288         static void ScheduleDestruction(T* pObj, void (*pFun)())
289         {
290             Private::Adapter<T> adapter = { pFun };
291             SetLongevity(pObj, GetLongevity(pObj), adapter);
292         }
293         
294         static void OnDeadReference()
295         { throw std::logic_error("Dead Reference Detected"); }
296     };
297 
298 ////////////////////////////////////////////////////////////////////////////////
299 // class template NoDestroy
300 // Implementation of the LifetimePolicy used by SingletonHolder
301 // Never destroys the object
302 ////////////////////////////////////////////////////////////////////////////////
303 
304     template <class T>
305     struct NoDestroy
306     {
307         static void ScheduleDestruction(T*, void (*)())
308         {}
309         
310         static void OnDeadReference()
311         {}
312     };
313 
314 ////////////////////////////////////////////////////////////////////////////////
315 // class template SingletonHolder
316 // Provides Singleton amenities for a type T
317 // To protect that type from spurious instantiations, you have to protect it
318 //     yourself.
319 ////////////////////////////////////////////////////////////////////////////////
320 
321     template
322     <
323         typename T,
324         template <class> class CreationPolicy = CreateUsingNew,
325         template <class> class LifetimePolicy = DefaultLifetime,
326         template <class> class ThreadingModel = SingleThreaded
327     >
328     class SingletonHolder
329     {
330     public:
331         static T& Instance();
332         
333     private:
334         // Helpers
335         static void MakeInstance();
336         static void DestroySingleton();
337         
338         // Protection
339         SingletonHolder();
340         
341         // Data
342         typedef typename ThreadingModel<T*>::VolatileType PtrInstanceType;
343         static PtrInstanceType pInstance_;
344         static bool destroyed_;
345     };
346     
347 ////////////////////////////////////////////////////////////////////////////////
348 // SingletonHolder's data
349 ////////////////////////////////////////////////////////////////////////////////
350 
351     template
352     <
353         class T,
354         template <class> class C,
355         template <class> class L,
356         template <class> class M
357     >
358     typename SingletonHolder<T, C, L, M>::PtrInstanceType
359         SingletonHolder<T, C, L, M>::pInstance_;
360 
361     template
362     <
363         class T,
364         template <class> class C,
365         template <class> class L,
366         template <class> class M
367     >
368     bool SingletonHolder<T, C, L, M>::destroyed_;
369 
370 ////////////////////////////////////////////////////////////////////////////////
371 // SingletonHolder::Instance
372 ////////////////////////////////////////////////////////////////////////////////
373 
374     template
375     <
376         class T,
377         template <class> class CreationPolicy,
378         template <class> class LifetimePolicy,
379         template <class> class ThreadingModel
380     >
381     inline T& SingletonHolder<T, CreationPolicy, 
382         LifetimePolicy, ThreadingModel>::Instance()
383     {
384         if (!pInstance_)
385         {
386             MakeInstance();
387         }
388         return *pInstance_;
389     }
390 
391 ////////////////////////////////////////////////////////////////////////////////
392 // SingletonHolder::MakeInstance (helper for Instance)
393 ////////////////////////////////////////////////////////////////////////////////
394 
395     template
396     <
397         class T,
398         template <class> class CreationPolicy,
399         template <class> class LifetimePolicy,
400         template <class> class ThreadingModel
401     >
402     void SingletonHolder<T, CreationPolicy, 
403         LifetimePolicy, ThreadingModel>::MakeInstance()
404     {
405         typename ThreadingModel<T>::Lock guard;
406         (void)guard;
407         
408         if (!pInstance_)
409         {
410             if (destroyed_)
411             {
412                 LifetimePolicy<T>::OnDeadReference();
413                 destroyed_ = false;
414             }
415             pInstance_ = CreationPolicy<T>::Create();
416             LifetimePolicy<T>::ScheduleDestruction(pInstance_, 
417                 &DestroySingleton);
418         }
419     }
420 
421     template
422     <
423         class T,
424         template <class> class CreationPolicy,
425         template <class> class L,
426         template <class> class M
427     >
428     void SingletonHolder<T, CreationPolicy, L, M>::DestroySingleton()
429     {
430         assert(!destroyed_);
431         CreationPolicy<T>::Destroy(pInstance_);
432         pInstance_ = 0;
433         destroyed_ = true;
434     }
435 } // namespace Loki
436 
437 ////////////////////////////////////////////////////////////////////////////////
438 // Change log:
439 // May 21, 2001: Correct the volatile qualifier - credit due to Darin Adler
440 // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
441 ////////////////////////////////////////////////////////////////////////////////
442 
443 #endif // SINGLETON_INC_
posted @ 2012-10-31 15:19  crazylhf  阅读(351)  评论(0)    收藏  举报