3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Just Standard Profile Kernel
6 * Copyright (C) 2003 by Embedded and Real-Time Systems Laboratory
7 * Toyohashi Univ. of Technology, JAPAN
9 * 上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation
10 * によって公表されている GNU General Public License の Version 2 に記
11 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
12 * を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
14 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
15 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
17 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
18 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
19 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
21 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
24 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
25 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
26 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
28 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
29 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
31 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
32 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
33 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
34 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
36 * @(#) $Id: singleton.h,v 1.3 2012/06/17 00:24:19 suikan Exp $
39 // $Header: /cvsroot/toppersjsp4bf/jsp/cfg/base/singleton.h,v 1.3 2012/06/17 00:24:19 suikan Exp $
41 #include "base/testsuite.h"
47 # pragma warning(disable:4290) //C++ の例外の指定は無視されます。関数が __declspec(nothrow) でないことのみ表示されます。
48 # pragma warning(disable:4291) //初期化コ−ドが例外をスロ−すると、'new' 演算子を使用しているとメモリを解放しません。
49 # pragma warning(disable:4786) //デバッグ情報で識別子が 255 文字に切り捨てられました。
61 // #gccがfriend class Singletonを食ってくれないので基底を作る
67 void (*destructor)(void);
70 //シングルトンでインスタンスを生成したことを示すためのクラス
71 // このクラスはSingletonからしか実体化できないので、
72 // ほかのクラスからこれを引数にもつコンストラクタを使用することはできない
73 class SingletonConstructionLocker
75 friend class SingletonBase;
77 SingletonConstructionLocker() {}
81 static bool initialize; //初期化済みか (atexitを呼んだかどうか)
82 static bool is_valid; //生成に失敗したシングルトンガあるかどうか
83 static struct chain * top; //デストラクタチェーン
86 static void final_release(void) throw()
90 struct chain * node = top;
93 (*node->destructor)();
101 static bool addDestructor(void (* destructor)(void)) throw()
104 SingletonBase::chain * node = new(std::nothrow) SingletonBase::chain;
109 node->destructor = destructor;
115 //要素破棄のために最後に破棄ルーチンを起動させる
117 atexit(final_release);
124 //SingletonConstructionLockerファクトリ
125 inline static SingletonConstructionLocker getLocker(void)
126 { return SingletonConstructionLocker(); }
129 //生成に失敗したシングルトンがないことを取得
130 static bool isValid(void) throw()
135 * コンテキストチェーン (テスト用シングルトンコンテキスト退避チェーン)
142 void (*restore)(void * & context) throw();
143 void (*renew)(void) throw();
148 ContextChain(void) throw() : top(0)
151 ~ContextChain(void) throw()
152 { restoreContext(); }
155 void restoreContext(void) throw()
158 struct chain * node = top;
161 (*node->restore)(node->context);
167 void renewInstance(void) throw(std::bad_alloc)
169 struct chain * node = top;
177 void clearInstance(void) throw(std::bad_alloc)
179 struct chain * node = top;
187 template<class T> void saveContext(void) throw(std::bad_alloc)
189 struct chain * node = new struct chain;
192 node->restore = reinterpret_cast<void(*)(void*&)>(Singleton<T>::restoreContext);
193 node->renew = Singleton<T>::renewInstance;
194 node->clear = Singleton<T>::clearInstance;
196 Singleton<T>::saveContext(reinterpret_cast<Singleton<T>::Context &>(node->context));
204 TESTSUITE_PROTOTYPE(main)
209 class Singleton : SingletonBase
218 static void destructor(void) throw()
221 try{ delete instance; } catch(...) {}
226 //インスタンスの生成 (インスタンス生成 + デストラクタ登録 + エラー処理)
227 static T * createInstance(std::nothrow_t) throw()
231 instance = new(std::nothrow) T(getLocker());
234 if(!addDestructor(destructor))
235 throw false; //catch節を実行させたい
240 try { delete instance; } catch(...) {}
247 //インスタンス生成 (bad_alloc例外をスローする実装)
248 static T * createInstance(void) throw(std::bad_alloc)
250 instance = createInstance(std::nothrow);
252 throw std::bad_alloc();
258 inline static T * getInstance(void) throw(std::bad_alloc)
261 instance = createInstance();
266 inline static T * getInstance(std::nothrow_t) throw()
269 instance = createInstance(std::nothrow);
273 #ifdef TESTSUITE /* テスト用 */
275 typedef T * Context; //退避用
278 static void renewInstance(void) throw(std::bad_alloc)
280 destructor(); //今のインスタンスを破棄
281 instance = new T(getLocker()); //新しいインスタンスを生成 (デストラクタが登録されてしまうのでcreateInstanceを呼んではいけない)
285 static void clearInstance(void) throw()
289 static void saveContext(Context & context) throw()
296 static void restoreContext(Context & context) throw()
298 destructor(); //今のインスタンスを破棄
299 instance = context; //退避したインスタンスを復帰
302 #endif /* TESTSUITE */
309 template<class T> T * Singleton<T>::instance = 0;
311 #define SINGLETON_CONSTRUCTOR(x) explicit x(const SingletonBase::SingletonConstructionLocker &)
312 #define SINGLETON_CONSTRUCTOR_(x) explicit x(const SingletonBase::SingletonConstructionLocker & _singleton)
314 #define SINGLETON_WRAPPER(derived, base) class derived : public base { public: SINGLETON_CONSTRUCTOR_(derived) throw() : base(_singleton) {} };
316 #endif /* SINGLETON_H */