OSDN Git Service

Fix no pic
[uclinux-h8/uClinux-dist.git] / user / gnugk / singleton.h
1 //////////////////////////////////////////////////////////////////
2 //
3 // singleton.h
4 //
5 // All singleton objects are put into a list
6 // so that it would be delete when program exits.
7 //
8 //
9 // This work is published under the GNU Public License (GPL)
10 // see file COPYING for details.
11 // We also explicitely grant the right to link this code
12 // with the OpenH323 library.
13 //
14 //////////////////////////////////////////////////////////////////
15
16 #ifndef SINGLETON_H
17 #define SINGLETON_H "@(#) $Id: singleton.h,v 1.14 2007/03/21 22:30:16 willamowius Exp $"
18
19 // STL
20 #include <list>
21 #include <algorithm>
22 #include <stdexcept>
23
24 //
25 // a list of pointers that would delete all objects
26 // referred by the pointers in the list on destruction
27 //
28 template<class T> class listptr : public std::list<void *> {
29   public:
30         listptr() : clear_list(false) {}
31         ~listptr();
32         bool clear_list;
33
34   private:
35         static void delete_obj(void *t) { delete static_cast<T *>(t); }
36 };
37
38 template<class T> listptr<T>::~listptr()
39 {
40         clear_list=true;
41         std::for_each(begin(), end(), delete_obj);
42 }
43
44
45 // Base class for all singletons
46 class SingletonBase {
47   public:
48         SingletonBase(const char *);
49         virtual ~SingletonBase();
50
51   private:
52         const char *m_name;
53         // Note the SingletonBase instance is not singleton itself :p
54         // However, list of singletons *are* singleton
55         // But we can't put the singleton into the list :(
56         static listptr<SingletonBase> _instance_list;
57 };
58
59 //
60 // A singleton class should be derived from this template.
61 // class Ts : public Singleton<Ts> {
62 //     ...
63 // };
64 //
65 // If the class is instantiated more than once,
66 // a runtime error would be thrown
67 //
68 // I provide two ways to access the singleton:
69 // (since I'm not sure which is better)
70 // T::Instance()  or  InstanceOf<T>
71 //
72 template<class T> class Singleton : public SingletonBase {
73   public:
74         static T *Instance();
75         template<class U> static T *Instance(const U &);
76
77   protected:
78         Singleton(const char *);
79         ~Singleton();
80
81   public:
82         static T *m_Instance;
83         static PMutex m_CreationLock;
84 };
85
86 template<class T> Singleton<T>::Singleton(const char *n) : SingletonBase(n)
87 {
88 //      if (m_Instance != 0)
89 //              throw std::runtime_error("Duplicate instances");
90 }
91
92 template<class T> Singleton<T>::~Singleton()
93 {
94         PWaitAndSignal lock(m_CreationLock);
95         m_Instance = 0;
96 }
97
98 // Function to access the singleton
99 template<class T> T *Singleton<T>::Instance()
100 {
101         if (m_Instance == 0) {
102                 PWaitAndSignal lock(m_CreationLock);
103                 // We have to check it again after we got the lock
104                 if (m_Instance == 0)
105                         m_Instance = new T;
106         }
107         return m_Instance;
108 }
109
110 #ifndef _WIN32  // VC++ doesn't support nested template?
111 template<class T> template <class U> T *Singleton<T>::Instance(const U &u)
112 {
113         if (m_Instance == 0) {
114                 PWaitAndSignal lock(m_CreationLock);
115                 // We have to check it again after we got the lock
116                 if (m_Instance == 0)
117                         m_Instance = new T(u);
118         }
119         return m_Instance;
120 }
121 #endif
122
123 // Function to access the singleton
124 template<class T> T *InstanceOf()
125 {
126         if (Singleton<T>::m_Instance == 0) {
127                 PWaitAndSignal lock(Singleton<T>::m_CreationLock);
128                 // We have to check it again after we got the lock
129                 if (Singleton<T>::m_Instance == 0)
130                         Singleton<T>::m_Instance = new T;
131         }
132         return Singleton<T>::m_Instance;
133 }
134
135 // static members
136 template<class T> T *Singleton<T>::m_Instance=0;
137 template<class T> PMutex Singleton<T>::m_CreationLock;
138
139
140 #endif // SINGLETON_H