source: anotherchoice/tags/jsp-1.4.4-full-UTF8/cfg/base/singleton.h@ 26

Last change on this file since 26 was 26, checked in by ykominami, 10 years ago

initial

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