source: anotherchoice/tags/jsp-1.4.4-full-UTF8/cfg/base/garbage.cpp@ 26

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

initial

File size: 14.2 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) 2000-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: garbage.cpp,v 1.6 2003/12/15 07:32:13 takayuki Exp $
51 */
52
53// $Header: /home/CVS/configurator/base/garbage.cpp,v 1.6 2003/12/15 07:32:13 takayuki Exp $
54
55#include "base/garbage.h"
56
57#include <stdexcept>
58#include <algorithm>
59
60using namespace std;
61
62TrashBox * TrashBox::current_box = 0;
63
64//----------------------------------------------------------------
65// Garbage : ゴミ
66
67 //コンストラクタ
68Garbage::Garbage(void) throw()
69{
70 //ゴミ箱に関連付ける
71 assigned_box = TrashBox::getCurrentTrashBox();
72 if(assigned_box->isValid())
73 cookie = assigned_box->addGarbage(this);
74}
75
76 //デストラクタ
77Garbage::~Garbage(void) throw()
78{
79 rescue();
80}
81
82 //ゴミ救出
83void Garbage::rescue(void) throw()
84{
85 if(assigned_box->isValid()) {
86 assigned_box->recoverGarbage(cookie);
87 assigned_box = 0;
88 }
89}
90
91
92//----------------------------------------------------------------
93// TrashBox : ゴミをå…
94¥ã‚Œã‚‹ç®±
95
96TrashBox::TrashBox(void) throw()
97{
98 //ゴミ箱の差し替え
99 previous_box = current_box;
100 current_box = this;
101}
102
103TrashBox::~TrashBox(void) throw()
104{
105 //ゴミがなくなるまで削除
106 while(!garbage.empty()) {
107 //ふた
108 try{ cleanup(); }
109 catch(...) {}
110 }
111
112 //ゴミ箱の差し替え
113 current_box = previous_box;
114}
115
116/*
117 //ゴミ箱にå…
118¥ã‚ŒãŸã‚´ãƒŸã‚’取り除く
119void TrashBox::recoverGarbage(Garbage * _garbage, TrashBox::Cookie cookie) throw()
120{
121 if(isValid() && _garbage != 0) {
122 bool forward = true;
123 list<Garbage *>::iterator scope;
124
125 if(!garbage.empty()) {
126 scope = garbage.erase(cookie);
127
128 //自分が始末した
129 if(scope != garbage.end() || garbage.empty())
130 forward = false;
131 }
132
133 //親ゴミ箱に回送
134 if(forward && previous_box->isValid())
135 previous_box->recoverGarbage(_garbage, cookie);
136 }
137}
138*/
139 /* 修正時のメモ
140 関連付けられたゴミ箱が消えることは無い(生成期間はゴミ箱のほうが長いはず)ので、親に回送する必
141要は無い。よってif(forward...節は不要。
142 自分が始末できないゴミは無いので(cleanupはrecoverGargabeを呼ばない)、eraseの返却値のチェックは不要。
143 個別削除要求はゴミから出されるので、実行された時点でゴミは1つ以上存在するはずなので、emptyチェックは不要.
144 この時点でeraseだけになり、第一引数は不要。
145 */
146
147 //ゴミ箱にå…
148¥ã‚ŒãŸã‚´ãƒŸã‚’取り除く
149void TrashBox::recoverGarbage(TrashBox::Cookie cookie) throw()
150{ garbage.erase(cookie); }
151
152 //ゴミ箱を空にする
153void TrashBox::cleanup(void)
154{
155 //自分がトップレベルゴミ箱でなかったら失敗
156 if(current_box != this)
157 throw std::runtime_error("TrashBox::cleanup can be performed from the top level trash box only.");
158
159 try {
160 while(!garbage.empty())
161 delete *garbage.begin(); //ゴミリストから要素を外すのは子の役目
162 }
163 catch(...) {
164 garbage.erase(garbage.begin()); //例外を起こした最初の要素を削除
165 throw; //再送
166 }
167}
168
169
170
171/****************************************** テストスィート ******************************************/
172
173#ifdef TESTSUITE
174#include "coverage_undefs.h"
175
176namespace { int counter = 0; }
177
178#ifdef _MSC_VER
179 class DummyGarbage : public Garbage
180 {
181 public:
182 int * count;
183 bool throw_exception;
184
185 DummyGarbage(int * _count = 0) : count(_count), throw_exception(false)
186 { TestSuite::check("DummyGarbage::DummyGarbage"); }
187
188 ~DummyGarbage(void) throw(int)
189 {
190 if(count != 0) *count = ++counter;
191 if(throw_exception) throw 0;
192 TestSuite::check("DummyGarbage::~DummyGarbage");
193 }
194
195 };
196#elif __GNUC__
197 class DummyGarbage : public Garbage
198 {
199 public:
200 int * count;
201
202 DummyGarbage(int * _count = 0) : count(_count)
203 { TestSuite::check("DummyGarbage::DummyGarbage"); }
204
205 ~DummyGarbage(void) throw()
206 {
207 if(count != 0) *count = ++counter;
208 TestSuite::check("DummyGarbage::~DummyGarbage");
209 }
210 };
211#endif
212
213TESTSUITE(main, TrashBox)
214{
215 BEGIN_CASE("1","ゴミ箱を作ると登録される") {
216 TrashBox mybox;
217 TEST_CASE("1", "作ったゴミ箱が現在のゴミ箱になっている", TrashBox::current_box == &mybox);
218
219 {
220 TrashBox mybox2;
221 TEST_CASE("2", "作ったゴミ箱が現在のゴミ箱になっている (2)", TrashBox::current_box == &mybox2);
222 TEST_CASE("3", "もともとのゴミ箱が保存されている", mybox2.previous_box == &mybox);
223 }
224
225 TEST_CASE("4", "もとのゴミ箱に戻る", TrashBox::current_box == &mybox);
226 } END_CASE;
227
228 BEGIN_CASE("2","isValid") {
229 TrashBox mybox;
230
231 TEST_CASE("1","作ったゴミ箱は正常", mybox.isValid());
232 TEST_CASE("2","NULL箱は異常", !((TrashBox *)0)->isValid());
233 } END_CASE;
234
235 BEGIN_CASE("3","operator new") {
236 BEGIN_CASE("1","new TrashBoxはbad_alloc例外を返す") {
237 bool result = false;
238
239 try { TrashBox * box = new TrashBox; }
240 catch(bad_alloc) { result = true; }
241
242 if(!result)
243 TEST_FAIL;
244 } END_CASE;
245
246 BEGIN_CASE("2","new(nothrow) TrashBoxはNULLを返す") {
247 bool result = true;
248 TrashBox * box;
249
250 try { box = new(nothrow) TrashBox; }
251 catch(...) { result = false; }
252
253 TEST_CASE("1", "new(nothrow)は例外を返さない", result);
254 TEST_CASE("2", "new(nothrow)はNULLを返す", box == 0);
255 } END_CASE;
256 } END_CASE;
257
258 BEGIN_CASE("4","基本的な生成削除") {
259 BEGIN_CASE("1","ちゃんとゴミ箱から外せる") {
260 TrashBox mybox;
261
262 DummyGarbage * garbage = new DummyGarbage;
263
264 TEST_CASE("0","[前提] ゴミがå…
265¥ã£ã¦ã„ã‚‹", std::find(mybox.garbage.begin(), mybox.garbage.end(), garbage) != mybox.garbage.end());
266 delete garbage;
267 TEST_CASE("1","ゴミが消えている", std::find(mybox.garbage.begin(), mybox.garbage.end(), garbage) == mybox.garbage.end());
268
269
270 } END_CASE;
271
272 BEGIN_CASE("2","親のゴミ箱にå…
273¥ã£ã¦ã„るものもゴミ箱から外せる") {
274 TrashBox mybox;
275 DummyGarbage * garbage = new DummyGarbage;
276 TEST_CASE("0","[前提] ゴミがå…
277¥ã£ã¦ã„ã‚‹", find(mybox.garbage.begin(), mybox.garbage.end(), garbage) != mybox.garbage.end());
278
279 TrashBox secondbox;
280 delete garbage;
281
282 TEST_CASE("1","ゴミが消えている", find(mybox.garbage.begin(), mybox.garbage.end(), garbage) == mybox.garbage.end());
283
284 } END_CASE;
285 } END_CASE;
286
287 BEGIN_CASE("5","TrashBox::cleanup") {
288 BEGIN_CASE("1","動的に作ったオブジェクトが破棄できる") {
289 TrashBox mybox;
290 DummyGarbage * garbage;
291
292 TestSuite::clearCheckpoints();
293
294 garbage = new DummyGarbage;
295 TEST_CASE("0","[前提] コンストラクタが起動されている", TestSuite::isReached("DummyGarbage::DummyGarbage"));
296
297 mybox.cleanup();
298 TEST_CASE("1","デストラクタが起動されている", TestSuite::isReached("DummyGarbage::~DummyGarbage"));
299 } END_CASE;
300
301#ifdef _MSC_VER
302 BEGIN_CASE("2","例外はもれる") {
303 TrashBox mybox;
304 DummyGarbage * garbage;
305
306 TestSuite::clearCheckpoints();
307
308 garbage = new DummyGarbage;
309 garbage->throw_exception = true;
310
311 bool result = false;
312 try { mybox.cleanup(); }
313 catch(...) { result = true; }
314
315 if(!result)
316 TEST_FAIL;
317 } END_CASE;
318
319 BEGIN_CASE("3","例外を起こしたオブジェクトが破壊されている (2重破棄にならない)") {
320 TrashBox mybox;
321 DummyGarbage * garbage;
322 DummyGarbage * garbage2;
323
324 TestSuite::clearCheckpoints();
325
326 garbage = new DummyGarbage;
327 garbage->throw_exception = true;
328 garbage2 = new DummyGarbage;
329 garbage2->throw_exception = true;
330
331 try { mybox.cleanup(); }
332 catch(...) {}
333 try { mybox.cleanup(); } //ここでAccessViolationが起こらない
334 catch(...) {}
335
336 if(!mybox.garbage.empty())
337 TEST_FAIL;
338 } END_CASE;
339#endif
340
341 BEGIN_CASE("4","削除の順序が正しい") {
342 TrashBox mybox;
343 DummyGarbage * garbage;
344 DummyGarbage * garbage2;
345 DummyGarbage * garbage3;
346 int g = 0;
347 int g2 = 0;
348 int g3 = 0;
349
350 TestSuite::clearCheckpoints();
351
352 garbage = new DummyGarbage(&g);
353 garbage2 = new DummyGarbage(&g2);
354 garbage3 = new DummyGarbage(&g3);
355
356 mybox.cleanup();
357
358 TEST_CASE("1","最初に登録されたものは最後に削除",g == 3);
359 TEST_CASE("2","次に登録されたものは2番目に削除",g2 == 2);
360 TEST_CASE("3","次に登録されたものは最初に削除",g3 == 1);
361 } END_CASE;
362
363 BEGIN_CASE("5","トップレベルでないゴミ箱はcleanupできない") {
364 TrashBox outerbox;
365 TrashBox innerbox;
366
367 bool result = false;
368 try { outerbox.cleanup(); }
369 catch(std::runtime_error)
370 { result = true; }
371
372 if(!result)
373 TEST_FAIL;
374 } END_CASE;
375
376 } END_CASE;
377
378 BEGIN_CASE("6","デストラクタによる破棄") {
379 BEGIN_CASE("1","動的に作ったオブジェクトが破棄できる (TrashBox::~TrashBox)") {
380 {
381 TrashBox mybox;
382 DummyGarbage * garbage;
383
384 TestSuite::clearCheckpoints();
385
386 garbage = new DummyGarbage;
387 TEST_CASE("0","[前提] コンストラクタが起動されている", TestSuite::isReached("DummyGarbage::DummyGarbage"));
388 }
389 TEST_CASE("1","デストラクタが起動されている", TestSuite::isReached("DummyGarbage::~DummyGarbage"));
390 } END_CASE;
391
392 BEGIN_CASE("2","例外はもれない") {
393 bool result = true;
394 try{
395 TrashBox mybox;
396 DummyGarbage * garbage;
397
398 TestSuite::clearCheckpoints();
399
400 garbage = new DummyGarbage;
401 TEST_CASE("0","[前提] コンストラクタが起動されている", TestSuite::isReached("DummyGarbage::DummyGarbage"));
402 }
403 catch(...)
404 { result = false; }
405 TEST_CASE("1","例外はもれない", result);
406 } END_CASE;
407
408 } END_CASE;
409
410 BEGIN_CASE("7","rescue") {
411 DummyGarbage * garbage;
412 {
413 TrashBox mybox;
414 garbage = new DummyGarbage;
415 garbage->rescue();
416
417 TestSuite::clearCheckpoints();
418 }
419 TEST_CASE("1","rescueしたゴミは削除されない", !TestSuite::isReached("DummyGarbage::~DummyGarbage"));
420 delete garbage;
421 } END_CASE;
422
423 BEGIN_CASE("8","静的なオブジェクトが多重破棄されない") {
424 TrashBox outerbox;
425 {
426 DummyGarbage garbage;
427 TrashBox innerbox;
428 DummyGarbage garbage2;
429
430 TEST_CASE("0","[前提] コンストラクタが起動されている", TestSuite::isReached("DummyGarbage::DummyGarbage"));
431 } //ここで2重破棄でMACVにならない
432 } END_CASE;
433}
434
435#endif
436
437
438
Note: See TracBrowser for help on using the repository browser.