]> git.cworth.org Git - vogl/blob - src/extlib/loki/include/loki/Singleton.h
Initial vogl checkin
[vogl] / src / extlib / loki / include / loki / 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-Wesley 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 #ifndef LOKI_SINGLETON_INC_
16 #define LOKI_SINGLETON_INC_
17
18 // $Id: Singleton.h 834 2007-08-02 19:36:10Z syntheticpp $
19
20
21 #include "LokiExport.h"
22 #include "Threads.h"
23 #include <algorithm>
24 #include <stdexcept>
25 #include <cassert>
26 #include <cstdlib>
27 #include <new>
28 #include <vector>
29 #include <list>
30 #include <memory>
31
32 #ifdef _MSC_VER
33 #define LOKI_C_CALLING_CONVENTION_QUALIFIER __cdecl
34 #else
35 #define LOKI_C_CALLING_CONVENTION_QUALIFIER
36 #endif
37
38 ///  \defgroup  SingletonGroup Singleton
39 ///  \defgroup  CreationGroup Creation policies
40 ///  \ingroup   SingletonGroup
41 ///  \defgroup  LifetimeGroup Lifetime policies
42 ///  \ingroup   SingletonGroup
43 ///  The lifetimes of the singleton.
44 ///  \par Special lifetime for SmallObjects
45 ///  When the holded object is a Small(Value)Object or the holded object
46 ///  uses objects which are or inherit from Small(Value)Object
47 ///  then you can't use the default lifetime: you must use the lifetime
48 ///  \code Loki::LongevityLifetime::DieAsSmallObjectChild \endcode
49 ///  Be aware of this when you use Loki::Factory, Loki::Functor, or Loki::Function.
50
51
52
53 namespace Loki
54 {
55 typedef void (LOKI_C_CALLING_CONVENTION_QUALIFIER *atexit_pfn_t)();
56
57 namespace Private
58 {
59
60 #ifndef LOKI_MAKE_DLL
61 void LOKI_C_CALLING_CONVENTION_QUALIFIER AtExitFn(); // declaration needed below
62 #else
63 void LOKI_EXPORT AtExitFn();
64 #endif
65
66 class LifetimeTracker;
67
68 #define LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL
69 #ifdef LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL
70
71 // Helper data
72 // std::list because of the inserts
73 typedef std::list<LifetimeTracker *> TrackerArray;
74 extern LOKI_EXPORT TrackerArray *pTrackerArray;
75 #else
76 // Helper data
77 typedef LifetimeTracker **TrackerArray;
78 extern TrackerArray pTrackerArray;
79 extern unsigned int elements;
80 #endif
81
82 ////////////////////////////////////////////////////////////////////////////////
83 // class LifetimeTracker
84 // Helper class for SetLongevity
85 ////////////////////////////////////////////////////////////////////////////////
86
87 class LifetimeTracker
88 {
89 public:
90         LifetimeTracker(unsigned int x) : longevity_(x)
91         {}
92
93         virtual ~LifetimeTracker() = 0;
94
95         static bool Compare(const LifetimeTracker *lhs,
96                             const LifetimeTracker *rhs)
97         {
98                 return lhs->longevity_ > rhs->longevity_;
99         }
100
101 private:
102         unsigned int longevity_;
103 };
104
105 // Definition required
106 inline LifetimeTracker::~LifetimeTracker() {}
107
108 // Helper destroyer function
109 template <typename T>
110 struct Deleter
111 {
112         typedef void (*Type)(T *);
113         static void Delete(T *pObj)
114         {
115                 delete pObj;
116         }
117 };
118
119 // Concrete lifetime tracker for objects of type T
120 template <typename T, typename Destroyer>
121 class ConcreteLifetimeTracker : public LifetimeTracker
122 {
123 public:
124         ConcreteLifetimeTracker(T *p,unsigned int longevity, Destroyer d)
125                 : LifetimeTracker(longevity)
126                 , pTracked_(p)
127                 , destroyer_(d)
128         {}
129
130         ~ConcreteLifetimeTracker()
131         {
132                 destroyer_(pTracked_);
133         }
134
135 private:
136         T *pTracked_;
137         Destroyer destroyer_;
138 };
139
140 } // namespace Private
141
142 ////////////////////////////////////////////////////////////////////////////////
143 ///  \ingroup LifetimeGroup
144 ///
145 ///  Assigns an object a longevity; ensures ordered destructions of objects
146 ///  registered thusly during the exit sequence of the application
147 ////////////////////////////////////////////////////////////////////////////////
148
149 #ifdef LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL
150
151 template <typename T, typename Destroyer>
152 void SetLongevity(T *pDynObject, unsigned int longevity,
153                   Destroyer d)
154 {
155         using namespace Private;
156
157         // manage lifetime of stack manually
158         if(pTrackerArray==0)
159                 pTrackerArray = new TrackerArray;
160
161         // automatically delete the ConcreteLifetimeTracker object when a exception is thrown
162         std::auto_ptr<LifetimeTracker>
163         p( new ConcreteLifetimeTracker<T, Destroyer>(pDynObject, longevity, d) );
164
165         // Find correct position
166         TrackerArray::iterator pos = std::upper_bound(
167                                          pTrackerArray->begin(),
168                                          pTrackerArray->end(),
169                                          p.get(),
170                                          LifetimeTracker::Compare);
171
172         // Insert the pointer to the ConcreteLifetimeTracker object into the queue
173         pTrackerArray->insert(pos, p.get());
174
175         // nothing has thrown: don't delete the ConcreteLifetimeTracker object
176         p.release();
177
178         // Register a call to AtExitFn
179         std::atexit(Private::AtExitFn);
180 }
181
182 #else
183
184 template <typename T, typename Destroyer>
185 void SetLongevity(T *pDynObject, unsigned int longevity,
186                   Destroyer d)
187 {
188         using namespace Private;
189
190         TrackerArray pNewArray = static_cast<TrackerArray>(
191                                      std::realloc(pTrackerArray,
192                                              sizeof(*pTrackerArray) * (elements + 1)));
193         if (!pNewArray) throw std::bad_alloc();
194
195         // Delayed assignment for exception safety
196         pTrackerArray = pNewArray;
197
198         LifetimeTracker *p = new ConcreteLifetimeTracker<T, Destroyer>(
199             pDynObject, longevity, d);
200
201         // Insert a pointer to the object into the queue
202         TrackerArray pos = std::upper_bound(
203                                pTrackerArray,
204                                pTrackerArray + elements,
205                                p,
206                                LifetimeTracker::Compare);
207         std::copy_backward(
208             pos,
209             pTrackerArray + elements,
210             pTrackerArray + elements + 1);
211         *pos = p;
212         ++elements;
213
214         // Register a call to AtExitFn
215         std::atexit(Private::AtExitFn);
216 }
217
218 #endif
219
220 template <typename T>
221 void SetLongevity(T *pDynObject, unsigned int longevity,
222                   typename Private::Deleter<T>::Type d = Private::Deleter<T>::Delete)
223 {
224         SetLongevity<T, typename Private::Deleter<T>::Type>(pDynObject, longevity, d);
225 }
226
227 ////////////////////////////////////////////////////////////////////////////////
228 ///  \struct CreateUsingNew
229 ///
230 ///  \ingroup CreationGroup
231 ///  Implementation of the CreationPolicy used by SingletonHolder
232 ///  Creates objects using a straight call to the new operator
233 ////////////////////////////////////////////////////////////////////////////////
234 template <class T> struct CreateUsingNew
235 {
236         static T *Create()
237         {
238                 return new T;
239         }
240
241         static void Destroy(T *p)
242         {
243                 delete p;
244         }
245 };
246
247 ////////////////////////////////////////////////////////////////////////////////
248 ///  \struct CreateUsing
249 ///
250 ///  \ingroup CreationGroup
251 ///  Implementation of the CreationPolicy used by SingletonHolder
252 ///  Creates objects using a custom allocater.
253 ///  Usage: e.g. CreateUsing<std::allocator>::Allocator
254 ////////////////////////////////////////////////////////////////////////////////
255 template<template<class> class Alloc>
256 struct CreateUsing
257 {
258         template <class T>
259         struct Allocator
260         {
261                 static Alloc<T> allocator;
262
263                 static T *Create()
264                 {
265                         return new (allocator.allocate(1)) T;
266                 }
267
268                 static void Destroy(T *p)
269                 {
270                         //allocator.destroy(p);
271                         p->~T();
272                         allocator.deallocate(p,1);
273                 }
274         };
275 };
276
277 ////////////////////////////////////////////////////////////////////////////////
278 ///  \struct CreateUsingMalloc
279 ///
280 ///  \ingroup CreationGroup
281 ///  Implementation of the CreationPolicy used by SingletonHolder
282 ///  Creates objects using a call to std::malloc, followed by a call to the
283 ///  placement new operator
284 ////////////////////////////////////////////////////////////////////////////////
285 template <class T> struct CreateUsingMalloc
286 {
287         static T *Create()
288         {
289                 void *p = std::malloc(sizeof(T));
290                 if (!p) return 0;
291                 return new(p) T;
292         }
293
294         static void Destroy(T *p)
295         {
296                 p->~T();
297                 std::free(p);
298         }
299 };
300
301
302 ////////////////////////////////////////////////////////////////////////////////
303 ///  \struct CreateStatic
304 ///
305 ///  \ingroup CreationGroup
306 ///  Implementation of the CreationPolicy used by SingletonHolder
307 ///  Creates an object in static memory
308 ///  Implementation is slightly nonportable because it uses the MaxAlign trick
309 ///  (an union of all types to ensure proper memory alignment). This trick is
310 ///  nonportable in theory but highly portable in practice.
311 ////////////////////////////////////////////////////////////////////////////////
312 template <class T> struct CreateStatic
313 {
314
315 #ifdef _MSC_VER
316 #pragma warning( push )
317 #pragma warning( disable : 4121 )
318 // alignment of a member was sensitive to packing
319 #endif // _MSC_VER
320
321         union MaxAlign
322         {
323                 char t_[sizeof(T)];
324                 short int shortInt_;
325                 int int_;
326                 long int longInt_;
327                 float float_;
328                 double double_;
329                 long double longDouble_;
330                 struct Test;
331                 int Test::*pMember_;
332                 int (Test::*pMemberFn_)(int);
333         };
334
335 #ifdef _MSC_VER
336 #pragma warning( pop )
337 #endif // _MSC_VER
338
339         static T *Create()
340         {
341                 static MaxAlign staticMemory_;
342                 return new(&staticMemory_) T;
343         }
344
345         static void Destroy(T *p)
346         {
347                 p->~T();
348         }
349 };
350
351 ////////////////////////////////////////////////////////////////////////////////
352 ///  \struct DefaultLifetime
353 ///
354 ///  \ingroup LifetimeGroup
355 ///  Implementation of the LifetimePolicy used by SingletonHolder
356 ///  Schedules an object's destruction as per C++ rules
357 ///  Forwards to std::atexit
358 ////////////////////////////////////////////////////////////////////////////////
359 template <class T>
360 struct DefaultLifetime
361 {
362         static void ScheduleDestruction(T *, atexit_pfn_t pFun)
363         {
364                 std::atexit(pFun);
365         }
366
367         static void OnDeadReference()
368         {
369                 throw std::logic_error("Dead Reference Detected");
370         }
371 };
372
373 ////////////////////////////////////////////////////////////////////////////////
374 ///  \struct  PhoenixSingleton
375 ///
376 ///  \ingroup LifetimeGroup
377 ///  Implementation of the LifetimePolicy used by SingletonHolder
378 ///  Schedules an object's destruction as per C++ rules, and it allows object
379 ///  recreation by not throwing an exception from OnDeadReference
380 ////////////////////////////////////////////////////////////////////////////////
381 template <class T>
382 class PhoenixSingleton
383 {
384 public:
385         static void ScheduleDestruction(T *, atexit_pfn_t pFun)
386         {
387 #ifndef ATEXIT_FIXED
388                 if (!destroyedOnce_)
389 #endif
390                         std::atexit(pFun);
391         }
392
393         static void OnDeadReference()
394         {
395 #ifndef ATEXIT_FIXED
396                 destroyedOnce_ = true;
397 #endif
398         }
399
400 private:
401 #ifndef ATEXIT_FIXED
402         static bool destroyedOnce_;
403 #endif
404 };
405
406 #ifndef ATEXIT_FIXED
407 template <class T> bool PhoenixSingleton<T>::destroyedOnce_ = false;
408 #endif
409
410 ////////////////////////////////////////////////////////////////////////////////
411 // Copyright (c) 2004 by Curtis Krauskopf - curtis@decompile.com
412 ///
413 ///  \struct  DeletableSingleton
414 ///
415 ///  \ingroup LifetimeGroup
416 ///
417 ///  A DeletableSingleton allows the instantiated singleton to be
418 ///  destroyed at any time. The singleton can be reinstantiated at
419 ///  any time, even during program termination.
420 ///  If the singleton exists when the program terminates, it will
421 ///  be automatically deleted.
422 ///
423 ///  \par Usage:
424 ///  The singleton can be deleted manually:
425 ///
426 ///  DeletableSingleton<MyClass>::GracefulDelete();
427 ////////////////////////////////////////////////////////////////////////////////
428 template <class T>
429 class DeletableSingleton
430 {
431 public:
432
433         static void ScheduleDestruction(T *, atexit_pfn_t pFun)
434         {
435                 static bool firstPass = true;
436                 isDead = false;
437                 deleter = pFun;
438                 if (firstPass || needCallback)
439                 {
440                         std::atexit(atexitCallback);
441                         firstPass = false;
442                         needCallback = false;
443                 }
444         }
445
446         static void OnDeadReference()
447         {
448         }
449         ///  delete singleton object manually
450         static void GracefulDelete()
451         {
452                 if (isDead)
453                         return;
454                 isDead = true;
455                 deleter();
456         }
457
458 protected:
459         static atexit_pfn_t deleter;
460         static bool isDead;
461         static bool needCallback;
462
463         static void atexitCallback()
464         {
465 #ifdef ATEXIT_FIXED
466                 needCallback = true;
467 #else
468                 needCallback = false;
469 #endif
470                 GracefulDelete();
471         }
472 };
473
474 template <class T>
475 atexit_pfn_t DeletableSingleton<T>::deleter = 0;
476
477 template <class T>
478 bool DeletableSingleton<T>::isDead = true;
479
480 template <class T>
481 bool DeletableSingleton<T>::needCallback = true;
482
483 ////////////////////////////////////////////////////////////////////////////////
484 // class template Adapter
485 // Helper for SingletonWithLongevity below
486 ////////////////////////////////////////////////////////////////////////////////
487
488 namespace Private
489 {
490 template <class T>
491 struct Adapter
492 {
493         void operator()(T *)
494         {
495                 return pFun_();
496         }
497         atexit_pfn_t pFun_;
498 };
499 }
500
501 ////////////////////////////////////////////////////////////////////////////////
502 ///  \struct SingletonWithLongevity
503 ///
504 ///  \ingroup LifetimeGroup
505 ///  Implementation of the LifetimePolicy used by SingletonHolder
506 ///  Schedules an object's destruction in order of their longevities
507 ///  Assumes a visible function GetLongevity(T*) that returns the longevity of the
508 ///  object.
509 ////////////////////////////////////////////////////////////////////////////////
510 template <class T>
511 class SingletonWithLongevity
512 {
513 public:
514         static void ScheduleDestruction(T *pObj, atexit_pfn_t pFun)
515         {
516                 Private::Adapter<T> adapter = { pFun };
517                 SetLongevity(pObj, GetLongevity(pObj), adapter);
518         }
519
520         static void OnDeadReference()
521         {
522                 throw std::logic_error("Dead Reference Detected");
523         }
524 };
525
526 ////////////////////////////////////////////////////////////////////////////////
527 ///  \struct NoDestroy
528 ///
529 ///  \ingroup LifetimeGroup
530 ///  Implementation of the LifetimePolicy used by SingletonHolder
531 ///  Never destroys the object
532 ////////////////////////////////////////////////////////////////////////////////
533 template <class T>
534 struct NoDestroy
535 {
536         static void ScheduleDestruction(T *, atexit_pfn_t)
537         {}
538
539         static void OnDeadReference()
540         {}
541 };
542
543
544 ////////////////////////////////////////////////////////////////////////////////
545 ///  \defgroup LongevityLifetimeGroup LongevityLifetime
546 ///  \ingroup LifetimeGroup
547 ///
548 ///  \namespace LongevityLifetime
549 ///
550 ///  \ingroup LongevityLifetimeGroup
551 ///  \brief  In this namespace are special lifetime policies to manage lifetime
552 ///  dependencies.
553 ////////////////////////////////////////////////////////////////////////////////
554 namespace LongevityLifetime
555 {
556 ////////////////////////////////////////////////////////////////////////////////
557 ///  \struct  SingletonFixedLongevity
558 ///
559 ///  \ingroup LongevityLifetimeGroup
560 ///  Add your own lifetimes into the namespace 'LongevityLifetime'
561 ///  with your prefered lifetime by adding a struct like this:
562 ///
563 ///  template<class T>
564 ///  struct MyLifetime  : SingletonFixedLongevity< MyLifetimeNumber ,T> {}
565 ////////////////////////////////////////////////////////////////////////////////
566 template <unsigned int Longevity, class T>
567 class SingletonFixedLongevity
568 {
569 public:
570         virtual ~SingletonFixedLongevity() {}
571
572         static void ScheduleDestruction(T *pObj, atexit_pfn_t pFun)
573         {
574                 Private::Adapter<T> adapter = { pFun };
575                 SetLongevity(pObj, Longevity , adapter);
576         }
577
578         static void OnDeadReference()
579         {
580                 throw std::logic_error("Dead Reference Detected");
581         }
582 };
583
584 ///  \struct DieLast
585 ///  \ingroup LongevityLifetimeGroup
586 ///  \brief  Longest possible SingletonWithLongevity lifetime: 0xFFFFFFFF
587 template <class T>
588 struct DieLast  : SingletonFixedLongevity<0xFFFFFFFF ,T>
589         {};
590
591 ///  \struct DieDirectlyBeforeLast
592 ///  \ingroup LongevityLifetimeGroup
593 ///  \brief  Lifetime is a one less than DieLast: 0xFFFFFFFF-1
594 template <class T>
595 struct DieDirectlyBeforeLast  : SingletonFixedLongevity<0xFFFFFFFF-1 ,T>
596         {};
597
598 ///  \struct DieFirst
599 ///  \ingroup LongevityLifetimeGroup
600 ///  \brief  Shortest possible SingletonWithLongevity lifetime: 0
601 template <class T>
602 struct DieFirst : SingletonFixedLongevity<0,T>
603         {};
604
605 }//namespace LongevityLifetime
606
607 ////////////////////////////////////////////////////////////////////////////////
608 ///  \class FollowIntoDeath
609 ///
610 ///  \ingroup LifetimeGroup
611 ///
612 ///  Lifetime policyfor the SingletonHolder tempalte.
613 ///  Followers will die after the master dies Followers will not die, if
614 ///    - master never dies (NoDestroy policy)
615 ///    - master never created
616 ///    - master dies not in the function registered with atexit
617 ///    - master dies not by a call of a the atexit registerd function (DeletableSingleton::GracefulDelete)
618 ///
619 ///  \par Usage:
620 ///
621 ///  Lifetimes of the master and the follower singletons,  e.g. with a M and a F class:
622 ///   \code SingletonHolder< M , FollowIntoDeath::With<DefaultLifetime>::AsMasterLifetime > MasterSingleton; \endcode
623 ///   \code SingletonHolder< F , CreateUsingNew, FollowIntoDeath::AfterMaster< MasterSingleton >::IsDestroyed > FollowerSingleton \endcode
624 ////////////////////////////////////////////////////////////////////////////////
625 class FollowIntoDeath
626 {
627         template<class T>
628         class Followers
629         {
630                 typedef std::vector<atexit_pfn_t> Container;
631                 typedef typename Container::iterator iterator;
632                 static Container *followers_;
633
634         public:
635                 static void Init()
636                 {
637                         static bool done = false;
638                         if(!done)
639                         {
640                                 followers_ = new Container;
641                                 done = true;
642                         }
643                 }
644
645                 static void AddFollower(atexit_pfn_t ae)
646                 {
647                         Init();
648                         followers_->push_back(ae);
649                 }
650
651                 static void DestroyFollowers()
652                 {
653                         Init();
654                         for(iterator it = followers_->begin(); it != followers_->end(); ++it)
655                                 (*it)();
656                         delete followers_;
657                 }
658         };
659
660 public:
661
662         ///  \struct With
663         ///  Template for the master
664         ///  \param Lifetime Lifetime policy for the master
665         template<template <class> class Lifetime>
666         struct With
667         {
668                 ///  \struct AsMasterLifetime
669                 ///  Policy for master
670                 template<class Master>
671                 struct AsMasterLifetime
672                 {
673                         static void ScheduleDestruction(Master *pObj, atexit_pfn_t pFun)
674                         {
675                                 Followers<Master>::Init();
676                                 Lifetime<Master>::ScheduleDestruction(pObj, pFun);
677
678                                 // use same policy for the followers and force a new
679                                 // template instantiation,  this adds a additional atexit entry
680                                 // does not work with SetLonlevity, but there you can control
681                                 // the lifetime with the GetLongevity function.
682                                 Lifetime<Followers<Master> >::ScheduleDestruction(0,Followers<Master>::DestroyFollowers);
683                         }
684
685                         static void OnDeadReference()
686                         {
687                                 throw std::logic_error("Dead Reference Detected");
688                         }
689                 };
690         };
691
692         ///  \struct AfterMaster
693         ///  Template for the follower
694         ///  \param Master Master to follow into death
695         template<class Master>
696         struct AfterMaster
697         {
698                 ///  \struct IsDestroyed
699                 ///  Policy for followers
700                 template<class F>
701                 struct IsDestroyed
702                 {
703                         static void ScheduleDestruction(F *, atexit_pfn_t pFun)
704                         {
705                                 Followers<Master>::AddFollower(pFun);
706                         }
707
708                         static void OnDeadReference()
709                         {
710                                 throw std::logic_error("Dead Reference Detected");
711                         }
712                 };
713         };
714 };
715
716 template<class T>
717 typename FollowIntoDeath::Followers<T>::Container *
718 FollowIntoDeath::Followers<T>::followers_ = 0;
719
720
721
722 ////////////////////////////////////////////////////////////////////////////////
723 ///  \class  SingletonHolder
724 ///
725 ///  \ingroup SingletonGroup
726 ///
727 ///  Provides Singleton amenities for a type T
728 ///  To protect that type from spurious instantiations,
729 ///  you have to protect it yourself.
730 ///
731 ///  \param CreationPolicy Creation policy, default: CreateUsingNew
732 ///  \param LifetimePolicy Lifetime policy, default: DefaultLifetime,
733 ///  \param ThreadingModel Threading policy,
734 ///                         default: LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL
735 ////////////////////////////////////////////////////////////////////////////////
736 template
737 <
738 typename T,
739          template <class> class CreationPolicy = CreateUsingNew,
740          template <class> class LifetimePolicy = DefaultLifetime,
741          template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL,
742          class MutexPolicy = LOKI_DEFAULT_MUTEX
743          >
744 class SingletonHolder
745 {
746 public:
747
748         ///  Type of the singleton object
749         typedef T ObjectType;
750
751         ///  Returns a reference to singleton object
752         static T &Instance();
753
754 private:
755         // Helpers
756         static void MakeInstance();
757         static void LOKI_C_CALLING_CONVENTION_QUALIFIER DestroySingleton();
758
759         // Protection
760         SingletonHolder();
761
762         // Data
763         typedef typename ThreadingModel<T *,MutexPolicy>::VolatileType PtrInstanceType;
764         static PtrInstanceType pInstance_;
765         static bool destroyed_;
766 };
767
768 ////////////////////////////////////////////////////////////////////////////////
769 // SingletonHolder's data
770 ////////////////////////////////////////////////////////////////////////////////
771
772 template
773 <
774 class T,
775       template <class> class C,
776       template <class> class L,
777       template <class, class> class M,
778       class X
779       >
780 typename SingletonHolder<T, C, L, M, X>::PtrInstanceType
781 SingletonHolder<T, C, L, M, X>::pInstance_ = 0;
782
783 template
784 <
785 class T,
786       template <class> class C,
787       template <class> class L,
788       template <class, class> class M,
789       class X
790       >
791 bool SingletonHolder<T, C, L, M, X>::destroyed_ = false;
792
793 ////////////////////////////////////////////////////////////////////////////////
794 // SingletonHolder::Instance
795 ////////////////////////////////////////////////////////////////////////////////
796
797 template
798 <
799 class T,
800       template <class> class CreationPolicy,
801       template <class> class LifetimePolicy,
802       template <class, class> class ThreadingModel,
803       class MutexPolicy
804       >
805 inline T &SingletonHolder<T, CreationPolicy,
806        LifetimePolicy, ThreadingModel, MutexPolicy>::Instance()
807 {
808         if (!pInstance_)
809         {
810                 MakeInstance();
811         }
812         return *pInstance_;
813 }
814
815 ////////////////////////////////////////////////////////////////////////////////
816 // SingletonHolder::MakeInstance (helper for Instance)
817 ////////////////////////////////////////////////////////////////////////////////
818
819 template
820 <
821 class T,
822 template <class> class CreationPolicy,
823 template <class> class LifetimePolicy,
824 template <class, class> class ThreadingModel,
825 class MutexPolicy
826 >
827 void SingletonHolder<T, CreationPolicy,
828      LifetimePolicy, ThreadingModel, MutexPolicy>::MakeInstance()
829 {
830         typename ThreadingModel<SingletonHolder,MutexPolicy>::Lock guard;
831         (void)guard;
832
833         if (!pInstance_)
834         {
835                 if (destroyed_)
836                 {
837                         destroyed_ = false;
838                         LifetimePolicy<T>::OnDeadReference();
839                 }
840                 pInstance_ = CreationPolicy<T>::Create();
841                 LifetimePolicy<T>::ScheduleDestruction(pInstance_,
842                                                        &DestroySingleton);
843         }
844 }
845
846 template
847 <
848 class T,
849 template <class> class CreationPolicy,
850 template <class> class L,
851 template <class, class> class M,
852 class X
853 >
854 void LOKI_C_CALLING_CONVENTION_QUALIFIER
855 SingletonHolder<T, CreationPolicy, L, M, X>::DestroySingleton()
856 {
857         assert(!destroyed_);
858         CreationPolicy<T>::Destroy(pInstance_);
859         pInstance_ = 0;
860         destroyed_ = true;
861 }
862
863
864 ////////////////////////////////////////////////////////////////////////////////
865 ///  \class  Singleton
866 ///
867 ///  \ingroup SingletonGroup
868 ///
869 ///  Convenience template to implement a getter function for a singleton object.
870 ///  Often needed in a shared library which hosts singletons.
871 ///
872 ///  \par Usage
873 ///
874 ///  see test/SingletonDll
875 ///
876 ////////////////////////////////////////////////////////////////////////////////
877
878 #ifndef LOKI_SINGLETON_EXPORT
879 #define LOKI_SINGLETON_EXPORT
880 #endif
881
882 template<class T>
883 class LOKI_SINGLETON_EXPORT Singleton
884 {
885 public:
886         static T &Instance();
887 };
888
889 } // namespace Loki
890
891
892 /// \def LOKI_SINGLETON_INSTANCE_DEFINITION(SHOLDER)
893 /// Convenience macro for the definition of the static Instance member function
894 /// Put this macro called with a SingletonHolder typedef into your cpp file.
895
896 #define LOKI_SINGLETON_INSTANCE_DEFINITION(SHOLDER)                     \
897 namespace Loki                                                          \
898 {                                                                        \
899     template<>                                                          \
900     SHOLDER::ObjectType&  Singleton<SHOLDER::ObjectType>::Instance()    \
901     {                                                                   \
902         return SHOLDER::Instance();                                     \
903     }                                                                    \
904 }
905
906
907 #endif // end file guardian
908