////////////////////////////////////////////////////////////
// UNWIND.CPP
// Copyright 1994 Gregory Colvin.
// May be distributed free with this notice.
#include "unwind.h"
static Unwindable* Newbie; // stack of newbies
static Handler Top; // default handler
Handler* Handler::handler=&Top; // current handler
unsigned Unwindable::count; // count of objects
// Set size and push on stack of newbies.
void* Unwindable::operator new(size_t size) {
Unwindable* p = (Unwindable*)::operator new(size);
p->size = size;
p->link = Newbie, Newbie = p;
return p;
}
// True iff *this is a subobject of *w.
inline int Unwindable::within(Unwindable* w) {
return (char*)w <= (char*)this
&& (char*)w + w->size >= (char*)this + size;
}
// If p is under construction by new then if *p is complete
// object pop it off stack of newbies, else pop subobjects
// of *p off of and push p onto stack for current handler.
void Handler::push(Unwindable* p,size_t sz) {
p->size = sz;
if (Newbie && p->within(Newbie)) {
if (Newbie->size == p->size)
Newbie = p->link;
} else {
for (Unwindable* stack= handler->link;
stack && stack->within(p);
stack = handler->link)
handler->link = stack->link;
p->link = handler->link, handler->link = p;
}
}
// Pop and destroy all Unwindables on stack for current
// handler and restore context of handler.
void Handler::Throw(int err) {
for (Unwindable* stack= handler->link;
stack;
stack = handler->link)
handler->link = stack->link, stack->~Unwindable();
if (handler!= &Top)
longjmp(handler->buf,err);
abort();
}
#ifdef TEST
#include <iostream.h>
struct Test : Unwindable {
int n;
Unwindable sub;
Unwindable* psub;
Test(int i) : n(i) {
UNWINDABLE;
psub = new Unwindable();
cout << "Test" << n << " " << this << endl;
}
virtual ~Test() {
cout << "~Test "<< n << " " << this << endl;
n = 0;
delete psub;
}
};
int test(int n_try, int curt_try=0) {
try {
cout << "try in test" << curr_try << endl;
Test local (curr_try);
if (curr_try < n_try)
return test(n_try,++curr_try);
else {
cout << "throw in test "<< curr_try << endl;
throw(-1);
}
} catch(int x) {
cout << "catch" << x <<" and rethrow in test"
<< curr_try << endl;
throw(x);
}
return curr_try;
}
int main() {
int n_test;
cout << "enter number of test recursions: ";
cin >> n_test;
Test* pTest= new Test(-1);
try {
return test(n_test);
} catch(int thrown) {
cout << "catch" << thrown <<" in main" << endl;
}
delete pTest;
cout << "Count" << Unwindable::Count() << endl;
return 0;
}
#endif
// End of File