OSDN Git Service

release_3.3.0
[toppersjsp4bf/jsp.git] / jsp / cfg / base / singleton.h
1 /*
2  *  TOPPERS/JSP Kernel
3  *      Toyohashi Open Platform for Embedded Real-Time Systems/
4  *      Just Standard Profile Kernel
5  * 
6  *  Copyright (C) 2003 by Embedded and Real-Time Systems Laboratory
7  *                              Toyohashi Univ. of Technology, JAPAN
8  * 
9  *  上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation 
10  *  によって公表されている GNU General Public License の Version 2 に記
11  *  述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
12  *  を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
13  *  利用と呼ぶ)することを無償で許諾する.
14  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
15  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
16  *      スコード中に含まれていること.
17  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
18  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
19  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
20  *      の無保証規定を掲載すること.
21  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
23  *      と.
24  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
25  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
26  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
27  *        報告すること.
28  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
29  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
30  * 
31  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
32  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
33  *  含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
34  *  接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
35  * 
36  *  @(#) $Id: singleton.h,v 1.3 2012/06/17 00:24:19 suikan Exp $
37  */
38
39 // $Header: /cvsroot/toppersjsp4bf/jsp/cfg/base/singleton.h,v 1.3 2012/06/17 00:24:19 suikan Exp $
40
41 #include "base/testsuite.h"
42
43 #ifndef SINGLETON_H
44 #define SINGLETON_H
45
46 #ifdef _MSC_VER
47 #  pragma warning(disable:4290) //C++ の例外の指定は無視されます。関数が __declspec(nothrow) でないことのみ表示されます。
48 #  pragma warning(disable:4291) //初期化コ−ドが例外をスロ−すると、'new' 演算子を使用しているとメモリを解放しません。
49 #  pragma warning(disable:4786) //デバッグ情報で識別子が 255 文字に切り捨てられました。
50 #endif
51
52 #include <new>
53 #include <stdexcept>
54 #include <cstdlib>
55
56 /*
57  *  シングルトンパターン 実装
58  */
59
60     //シングルトン基底クラス
61     //  #gccがfriend class Singletonを食ってくれないので基底を作る
62 class SingletonBase {
63 public:
64         //デストラクタのチェーン
65     struct chain {
66         struct chain * next;
67         void (*destructor)(void);
68     };
69
70         //シングルトンでインスタンスを生成したことを示すためのクラス
71         //    このクラスはSingletonからしか実体化できないので、
72         //    ほかのクラスからこれを引数にもつコンストラクタを使用することはできない
73     class SingletonConstructionLocker
74     {
75     friend class SingletonBase;
76     protected:
77         SingletonConstructionLocker() {}
78     };
79
80 private:
81     static bool   initialize;       //初期化済みか (atexitを呼んだかどうか)
82     static bool   is_valid;         //生成に失敗したシングルトンガあるかどうか
83     static struct chain * top;      //デストラクタチェーン
84
85         //デストラクタの起動
86     static void final_release(void) throw()
87     {
88             //先頭から削除 (先入れ後出し)
89         while(top != 0) {
90             struct chain * node = top;
91             top = node->next;
92
93             (*node->destructor)();
94
95             delete node;
96         }
97     }
98
99 protected:
100         //チェーンにデストラクタを追加
101     static bool addDestructor(void (* destructor)(void)) throw()
102     {
103         bool result = false;
104         SingletonBase::chain * node = new(std::nothrow) SingletonBase::chain;
105         if(node != 0) {
106
107                 //新しい要素を先頭に追加
108             node->next       = top;
109             node->destructor = destructor;
110             
111             top = node;
112
113             result = true;
114
115                 //要素破棄のために最後に破棄ルーチンを起動させる
116             if(!initialize) {
117                 atexit(final_release);
118                 initialize = true;
119             }
120         }
121         return result;
122     }
123
124         //SingletonConstructionLockerファクトリ
125     inline static SingletonConstructionLocker getLocker(void)
126     {   return SingletonConstructionLocker();   }
127
128 public:
129         //生成に失敗したシングルトンがないことを取得
130     static bool isValid(void) throw()
131     {   return is_valid;   }
132
133 #ifdef TESTSUITE
134         /*
135          *   コンテキストチェーン (テスト用シングルトンコンテキスト退避チェーン)
136          */
137     class ContextChain {
138     protected:
139         struct chain {
140             struct chain * next;
141             void * context;
142             void (*restore)(void * & context) throw();
143             void (*renew)(void) throw();
144             void (*clear)(void);
145         } * top;
146
147     public:
148         ContextChain(void) throw() : top(0)
149         {}
150
151         ~ContextChain(void) throw()
152         {   restoreContext();   }
153
154             /* コンテキストの復帰 */
155         void restoreContext(void) throw()
156         {
157             while(top != 0) {
158                 struct chain * node = top;
159                 top = top->next;
160
161                 (*node->restore)(node->context);
162                 delete node;
163             }
164         }
165
166             /* 全てのインスタンスを再生成 */
167         void renewInstance(void) throw(std::bad_alloc)
168         {
169             struct chain * node = top;
170             while(node != 0) {
171                 (*node->renew)();
172                 node = node->next;
173             }
174         }
175             
176             /* 全てのインスタンスを破棄 */
177         void clearInstance(void) throw(std::bad_alloc)
178         {
179             struct chain * node = top;
180             while(node != 0) {
181                 (*node->clear)();
182                 node = node->next;
183             }
184         }
185             
186             /* コンテキストの退避 */
187         template<class T> void saveContext(void) throw(std::bad_alloc)
188         {
189             struct chain * node = new struct chain;
190
191             node->next = top;
192             node->restore = reinterpret_cast<void(*)(void*&)>(Singleton<T>::restoreContext);
193             node->renew   = Singleton<T>::renewInstance;
194             node->clear   = Singleton<T>::clearInstance;
195
196             Singleton<T>::saveContext(reinterpret_cast<Singleton<T>::Context &>(node->context));
197
198             top = node;
199         }
200     };
201 #endif
202
203
204     TESTSUITE_PROTOTYPE(main)
205 };
206
207
208 template<class T>
209 class Singleton : SingletonBase
210 {
211 protected:
212     Singleton(void);
213     ~Singleton(void);
214
215     static T * instance;
216
217         //デストラクタ
218     static void destructor(void) throw()
219     {
220         if(instance != 0) {
221             try{ delete instance; } catch(...) {}
222             instance = 0;
223         }
224     }
225
226         //インスタンスの生成 (インスタンス生成 + デストラクタ登録 + エラー処理)
227     static T * createInstance(std::nothrow_t) throw()
228     {
229         T * instance = 0;
230         try {
231             instance = new(std::nothrow) T(getLocker());
232
233             if(instance != 0) {
234                 if(!addDestructor(destructor))
235                     throw false;    //catch節を実行させたい
236             }
237         }
238         catch(...) {
239             if(instance != 0) {
240                 try { delete instance; } catch(...) {}
241                 instance = 0;
242             }
243         }
244         return instance;
245     }
246
247         //インスタンス生成 (bad_alloc例外をスローする実装)
248     static T * createInstance(void) throw(std::bad_alloc)
249     {
250         instance = createInstance(std::nothrow);
251         if(instance == 0)
252             throw std::bad_alloc();
253         return instance;
254     }
255
256 public:
257         //インスタンスの取得
258     inline static T * getInstance(void) throw(std::bad_alloc)
259     {
260         if(instance == 0)
261             instance = createInstance();
262         return instance;
263     }
264
265         //インスタンスの取得
266     inline static T * getInstance(std::nothrow_t) throw()
267     {
268         if(instance == 0)
269             instance = createInstance(std::nothrow);
270         return instance;
271     }
272
273 #ifdef TESTSUITE    /* テスト用 */
274
275     typedef T * Context;    //退避用
276
277         //新しいインスタンスの生成
278     static void renewInstance(void) throw(std::bad_alloc)
279     {
280         destructor();                     //今のインスタンスを破棄
281         instance = new T(getLocker());    //新しいインスタンスを生成 (デストラクタが登録されてしまうのでcreateInstanceを呼んではいけない)
282     }
283
284         //インスタンス破棄
285     static void clearInstance(void) throw()
286     {   destructor();   }
287
288         //コンテキスト退避
289     static void saveContext(Context & context) throw()
290     {
291         context  = instance;
292         instance = 0;
293     }
294
295         //コンテキスト復帰
296     static void restoreContext(Context & context) throw()
297     {
298         destructor();           //今のインスタンスを破棄
299         instance = context;     //退避したインスタンスを復帰
300     }
301
302 #endif /* TESTSUITE */
303
304 };
305
306
307
308     //Singleton 静的変数
309 template<class T> T * Singleton<T>::instance = 0;
310
311 #define SINGLETON_CONSTRUCTOR(x)  explicit x(const SingletonBase::SingletonConstructionLocker &)
312 #define SINGLETON_CONSTRUCTOR_(x) explicit x(const SingletonBase::SingletonConstructionLocker & _singleton)
313
314 #define SINGLETON_WRAPPER(derived, base) class derived : public base { public: SINGLETON_CONSTRUCTOR_(derived) throw() : base(_singleton) {} };
315
316 #endif /* SINGLETON_H */
317