3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Just Standard Profile Kernel
6 * Copyright (C) 2000-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: garbage.cpp,v 1.1 2009/01/31 05:27:37 suikan Exp $
39 // $Header: /cvsroot/toppersjsp4bf/jsp/cfg/base/garbage.cpp,v 1.1 2009/01/31 05:27:37 suikan Exp $
41 #include "base/garbage.h"
48 TrashBox * TrashBox::current_box = 0;
50 //----------------------------------------------------------------
54 Garbage::Garbage(void) throw()
57 assigned_box = TrashBox::getCurrentTrashBox();
58 if(assigned_box->isValid())
59 cookie = assigned_box->addGarbage(this);
63 Garbage::~Garbage(void) throw()
69 void Garbage::rescue(void) throw()
71 if(assigned_box->isValid()) {
72 assigned_box->recoverGarbage(cookie);
78 //----------------------------------------------------------------
81 TrashBox::TrashBox(void) throw()
84 previous_box = current_box;
88 TrashBox::~TrashBox(void) throw()
91 while(!garbage.empty()) {
98 current_box = previous_box;
103 void TrashBox::recoverGarbage(Garbage * _garbage, TrashBox::Cookie cookie) throw()
105 if(isValid() && _garbage != 0) {
107 list<Garbage *>::iterator scope;
109 if(!garbage.empty()) {
110 scope = garbage.erase(cookie);
113 if(scope != garbage.end() || garbage.empty())
118 if(forward && previous_box->isValid())
119 previous_box->recoverGarbage(_garbage, cookie);
124 関連付けられたゴミ箱が消えることは無い(生成期間はゴミ箱のほうが長いはず)ので、親に回送する必要は無い。よってif(forward...節は不要。
125 自分が始末できないゴミは無いので(cleanupはrecoverGargabeを呼ばない)、eraseの返却値のチェックは不要。
126 個別削除要求はゴミから出されるので、実行された時点でゴミは1つ以上存在するはずなので、emptyチェックは不要.
127 この時点でeraseだけになり、第一引数は不要。
131 void TrashBox::recoverGarbage(TrashBox::Cookie cookie) throw()
132 { garbage.erase(cookie); }
135 void TrashBox::cleanup(void)
137 //自分がトップレベルゴミ箱でなかったら失敗
138 if(current_box != this)
139 throw std::runtime_error("TrashBox::cleanup can be performed from the top level trash box only.");
142 while(!garbage.empty())
143 delete *garbage.begin(); //ゴミリストから要素を外すのは子の役目
146 garbage.erase(garbage.begin()); //例外を起こした最初の要素を削除
153 /****************************************** テストスィート ******************************************/
156 #include "coverage_undefs.h"
158 namespace { int counter = 0; }
161 class DummyGarbage : public Garbage
165 bool throw_exception;
167 DummyGarbage(int * _count = 0) : count(_count), throw_exception(false)
168 { TestSuite::check("DummyGarbage::DummyGarbage"); }
170 ~DummyGarbage(void) throw(int)
172 if(count != 0) *count = ++counter;
173 if(throw_exception) throw 0;
174 TestSuite::check("DummyGarbage::~DummyGarbage");
179 class DummyGarbage : public Garbage
184 DummyGarbage(int * _count = 0) : count(_count)
185 { TestSuite::check("DummyGarbage::DummyGarbage"); }
187 ~DummyGarbage(void) throw()
189 if(count != 0) *count = ++counter;
190 TestSuite::check("DummyGarbage::~DummyGarbage");
195 TESTSUITE(main, TrashBox)
197 BEGIN_CASE("1","ゴミ箱を作ると登録される") {
199 TEST_CASE("1", "作ったゴミ箱が現在のゴミ箱になっている", TrashBox::current_box == &mybox);
203 TEST_CASE("2", "作ったゴミ箱が現在のゴミ箱になっている (2)", TrashBox::current_box == &mybox2);
204 TEST_CASE("3", "もともとのゴミ箱が保存されている", mybox2.previous_box == &mybox);
207 TEST_CASE("4", "もとのゴミ箱に戻る", TrashBox::current_box == &mybox);
210 BEGIN_CASE("2","isValid") {
213 TEST_CASE("1","作ったゴミ箱は正常", mybox.isValid());
214 TEST_CASE("2","NULL箱は異常", !((TrashBox *)0)->isValid());
217 BEGIN_CASE("3","operator new") {
218 BEGIN_CASE("1","new TrashBoxはbad_alloc例外を返す") {
221 try { TrashBox * box = new TrashBox; }
222 catch(bad_alloc) { result = true; }
228 BEGIN_CASE("2","new(nothrow) TrashBoxはNULLを返す") {
232 try { box = new(nothrow) TrashBox; }
233 catch(...) { result = false; }
235 TEST_CASE("1", "new(nothrow)は例外を返さない", result);
236 TEST_CASE("2", "new(nothrow)はNULLを返す", box == 0);
240 BEGIN_CASE("4","基本的な生成削除") {
241 BEGIN_CASE("1","ちゃんとゴミ箱から外せる") {
244 DummyGarbage * garbage = new DummyGarbage;
246 TEST_CASE("0","[前提] ゴミが入っている", std::find(mybox.garbage.begin(), mybox.garbage.end(), garbage) != mybox.garbage.end());
248 TEST_CASE("1","ゴミが消えている", std::find(mybox.garbage.begin(), mybox.garbage.end(), garbage) == mybox.garbage.end());
253 BEGIN_CASE("2","親のゴミ箱に入っているものもゴミ箱から外せる") {
255 DummyGarbage * garbage = new DummyGarbage;
256 TEST_CASE("0","[前提] ゴミが入っている", find(mybox.garbage.begin(), mybox.garbage.end(), garbage) != mybox.garbage.end());
261 TEST_CASE("1","ゴミが消えている", find(mybox.garbage.begin(), mybox.garbage.end(), garbage) == mybox.garbage.end());
266 BEGIN_CASE("5","TrashBox::cleanup") {
267 BEGIN_CASE("1","動的に作ったオブジェクトが破棄できる") {
269 DummyGarbage * garbage;
271 TestSuite::clearCheckpoints();
273 garbage = new DummyGarbage;
274 TEST_CASE("0","[前提] コンストラクタが起動されている", TestSuite::isReached("DummyGarbage::DummyGarbage"));
277 TEST_CASE("1","デストラクタが起動されている", TestSuite::isReached("DummyGarbage::~DummyGarbage"));
281 BEGIN_CASE("2","例外はもれる") {
283 DummyGarbage * garbage;
285 TestSuite::clearCheckpoints();
287 garbage = new DummyGarbage;
288 garbage->throw_exception = true;
291 try { mybox.cleanup(); }
292 catch(...) { result = true; }
298 BEGIN_CASE("3","例外を起こしたオブジェクトが破壊されている (2重破棄にならない)") {
300 DummyGarbage * garbage;
301 DummyGarbage * garbage2;
303 TestSuite::clearCheckpoints();
305 garbage = new DummyGarbage;
306 garbage->throw_exception = true;
307 garbage2 = new DummyGarbage;
308 garbage2->throw_exception = true;
310 try { mybox.cleanup(); }
312 try { mybox.cleanup(); } //ここでAccessViolationが起こらない
315 if(!mybox.garbage.empty())
320 BEGIN_CASE("4","削除の順序が正しい") {
322 DummyGarbage * garbage;
323 DummyGarbage * garbage2;
324 DummyGarbage * garbage3;
329 TestSuite::clearCheckpoints();
331 garbage = new DummyGarbage(&g);
332 garbage2 = new DummyGarbage(&g2);
333 garbage3 = new DummyGarbage(&g3);
337 TEST_CASE("1","最初に登録されたものは最後に削除",g == 3);
338 TEST_CASE("2","次に登録されたものは2番目に削除",g2 == 2);
339 TEST_CASE("3","次に登録されたものは最初に削除",g3 == 1);
342 BEGIN_CASE("5","トップレベルでないゴミ箱はcleanupできない") {
347 try { outerbox.cleanup(); }
348 catch(std::runtime_error)
357 BEGIN_CASE("6","デストラクタによる破棄") {
358 BEGIN_CASE("1","動的に作ったオブジェクトが破棄できる (TrashBox::~TrashBox)") {
361 DummyGarbage * garbage;
363 TestSuite::clearCheckpoints();
365 garbage = new DummyGarbage;
366 TEST_CASE("0","[前提] コンストラクタが起動されている", TestSuite::isReached("DummyGarbage::DummyGarbage"));
368 TEST_CASE("1","デストラクタが起動されている", TestSuite::isReached("DummyGarbage::~DummyGarbage"));
371 BEGIN_CASE("2","例外はもれない") {
375 DummyGarbage * garbage;
377 TestSuite::clearCheckpoints();
379 garbage = new DummyGarbage;
380 TEST_CASE("0","[前提] コンストラクタが起動されている", TestSuite::isReached("DummyGarbage::DummyGarbage"));
384 TEST_CASE("1","例外はもれない", result);
389 BEGIN_CASE("7","rescue") {
390 DummyGarbage * garbage;
393 garbage = new DummyGarbage;
396 TestSuite::clearCheckpoints();
398 TEST_CASE("1","rescueしたゴミは削除されない", !TestSuite::isReached("DummyGarbage::~DummyGarbage"));
402 BEGIN_CASE("8","静的なオブジェクトが多重破棄されない") {
405 DummyGarbage garbage;
407 DummyGarbage garbage2;
409 TEST_CASE("0","[前提] コンストラクタが起動されている", TestSuite::isReached("DummyGarbage::DummyGarbage"));
410 } //ここで2重破棄でMACVにならない