MEL
Microthread & Execution library
Singleton.h
1 // Singleton.h
3 // Implementation of the Class Singleton
4 // Created on: 29-mar-2005 10:00:13
5 // CLASS FOR SINGLETONS THAT ARE ABSTRACT CLASSES
6 // YOU MUST IMPLEMENT A CREATION FUNCITON: See createSingleton at this file.
7 //
8 // TODO no est� bien del todo el lock/unlock en los accessos. REVISAR
9 // DETENIDAMENTE
10 
12 
13 #pragma once
14 
15 #include <MelLibType.h>
16 #include <memory>
17 #include <stdexcept>
18 
19 #include <mpl/Type2Type.h>
21 #include <mpl/_If.h>
22 using mel::mpl::_if;
23 
24 #include <core/Singleton_Singlethread_Policy.h>
26 namespace mel
27 {
28  namespace core
29  {
53  template <class T, bool useSmartPtr,
54  template <class> class ThreadingPolicy>
55  class Singleton_Base
56  {
57  public:
58  static bool isSingletonCreated() { return mObject != 0; }
59 
60  protected:
61  typedef typename _if<useSmartPtr, std::shared_ptr<T>, T*>::Result
62  Tpointer;
63  typedef
64  typename ThreadingPolicy<Tpointer>::VolatileType InstanceType;
65  static InstanceType
66  mObject; // TODO considerar el VolatileType, importante
67 
68  //@warning ignominia absoluta para poder establecer el mObject desde
69  // una clase hija ya que no me deja con dllexport solo puede
70  // llamarse
71  // una vez por singleton
72  static void setObject( T* ob ) { mObject = ob; }
73  };
74 
75  template <class T, bool> struct GetObjectPtr
76  {
77  static T* get( T* p ) { return p; }
78  };
79  // specialization for SmartPtr
80  template <class T> struct GetObjectPtr<T, true>
81  {
82  static T* get( std::shared_ptr<T>& p ) { return p.get(); }
83  };
84 
85  template <class T, bool, bool, template <class> class>
86  class Singleton; // predeclaration
87  // version for non-abstract singletons
88  template <class T, template <class> class ThreadingPolicy,
89  bool useSmartPtr, bool isAbstract>
90  class Singleton_Middle
91  : public Singleton_Base<T, useSmartPtr,
92  ThreadingPolicy> //�nombre cutre!!
93  {
94  public:
95  typedef ThreadingPolicy<T> TThreadingPolicy;
96  inline static T& getSingleton() { return *getSingletonPtr(); }
97  inline static T* getSingletonPtr()
98  {
99  typename ThreadingPolicy<T>::Lock block;
100  if ( Singleton_Base<T, useSmartPtr, ThreadingPolicy>::mObject ==
101  (T*)NULL )
102  {
103  Singleton_Base<T, useSmartPtr, ThreadingPolicy>::mObject =
104  Singleton<T, isAbstract, useSmartPtr, ThreadingPolicy>::
105  createObject( Type2Type<T>() );
106  }
107  return GetObjectPtr<T, useSmartPtr>::get(
108  Singleton_Base<T, useSmartPtr, ThreadingPolicy>::mObject );
109  }
110  };
111  // specialization for abstract
112  template <class T, template <class> class ThreadingPolicy,
113  bool useSmartPtr>
114  class Singleton_Middle<T, ThreadingPolicy, useSmartPtr, true>
115  : public Singleton_Base<T, useSmartPtr,
116  ThreadingPolicy> //�nombre cutre!!
117  {
118  public:
119  inline static T& getSingleton()
120  {
121  typename ThreadingPolicy<T>::Lock block;
122  return *Singleton_Base<T, useSmartPtr,
123  ThreadingPolicy>::mObject;
124  }
125  inline static T* getSingletonPtr()
126  {
127  typename ThreadingPolicy<T>::Lock block;
128  return GetObjectPtr<T, useSmartPtr>::get(
129  Singleton_Base<T, useSmartPtr, ThreadingPolicy>::mObject );
130  // return
131  // Singleton_Base<T,useSmartPtr,ThreadingPolicy>::mObject;
132  }
133  };
135  template <class T, bool isAbstract = true, bool useSmartPtr = true,
136  template <class> class ThreadingPolicy =
138  class Singleton : public Singleton_Middle<T, ThreadingPolicy,
139  useSmartPtr, isAbstract>
140  {
141  friend class Singleton_Middle<T, ThreadingPolicy, useSmartPtr,
142  isAbstract>;
143 
144  public:
145  static void deleteSingleton()
146  {
147  typename ThreadingPolicy<T>::Lock block;
148  ObjectDeleter<T, useSmartPtr>::doDelete(
149  &Singleton_Base<T, useSmartPtr, ThreadingPolicy>::mObject );
150  }
151 
157  // static void createSingleton();
158 
159  private:
163  template <class U> static U* createObject( Type2Type<U> )
164  {
165  return new U();
166  }
167  static void deleteObject( T* obj ) { delete obj; }
168 
169  template <class U, bool> class ObjectDeleter
170  {
171  // deleter for plain pointer
172  public:
173  static void doDelete( U** obj )
174  {
175  Singleton<T, isAbstract, useSmartPtr,
176  ThreadingPolicy>::deleteObject( *obj );
177  *obj = NULL;
178  }
179  };
180 
181  template <class U> class ObjectDeleter<U, true>
182  {
183  // deleter for SmartPtr
184  public:
185  static void doDelete( std::shared_ptr<U>* obj )
186  {
187  // throw exception if obj has other references
188  if ( obj->getPtr() && ( *obj )->getRefCount() > 1 )
189  {
190  throw std::runtime_error(
191  "Singleton::deleteSingleton. Other references to "
192  "obj still alive" );
193  }
194  *obj = 0;
195  }
196  };
197  };
199  template <class T, bool useSmartPtr,
200  template <class> class ThreadingPolicy>
201  typename Singleton_Base<T, useSmartPtr, ThreadingPolicy>::InstanceType
202  Singleton_Base<T, useSmartPtr, ThreadingPolicy>::mObject = 0;
204  // default version
205  // normally each child will need his own version
206 
207  /*//con dllexport no me vale esto!!
208  template <class T > void Singleton<T>::createSingleton()
209  {
210  if ( !mObject )
211  {
212  mObject = new T();
213  }
214  }*/
215 
216  } // namespace core
217 } // namespace mel
Definition: Singleton_Singlethread_Policy.h:10
Definition: Singleton.h:140
Definition: Callback_Impl.h:11
Definition: _If.h:16
Definition: Type2Type.h:12