// examples/scoped_resource // BEGIN mycpp output #include "gc_heap.h" using gc_heap::Alloc; using gc_heap::kZeroMask; using gc_heap::StackRoots; #include "my_runtime.h" #include "mylib2.h" using gc_heap::NewStr; using gc_heap::NewList; using gc_heap::NewDict; GLOBAL_STR(str0, "CWD"); GLOBAL_STR(str1, "foo"); GLOBAL_STR(str2, " in context stack %d"); GLOBAL_STR(str3, ""); GLOBAL_STR(str4, "-> dir stack %d"); GLOBAL_STR(str5, "exited with exception"); GLOBAL_STR(str6, "<- dir stack %d"); GLOBAL_STR(str7, "foo"); GLOBAL_STR(str8, "exception"); namespace scoped_resource { // forward declare class MyError; class ctx_DirStack; class DirStack; } // forward declare namespace scoped_resource namespace scoped_resource { // declare class MyError : public gc_heap::Obj { public: MyError(); DISALLOW_COPY_AND_ASSIGN(MyError) }; void Error(bool error); class ctx_DirStack : public gc_heap::Obj { public: ctx_DirStack(scoped_resource::DirStack* state, Str* entry); ~ctx_DirStack(); scoped_resource::DirStack* state; DISALLOW_COPY_AND_ASSIGN(ctx_DirStack) }; class DirStack : public gc_heap::Obj { public: DirStack(); void Reset(); void Push(Str* entry); Str* Pop(); List* Iter(); List* stack; DISALLOW_COPY_AND_ASSIGN(DirStack) }; void DoWork(scoped_resource::DirStack* d, bool do_raise); void run_tests(); void run_benchmarks(); inline Str* fmt0(int a0) { gBuf.reset(); gBuf.write_const(" in context stack ", 19); gBuf.format_d(a0); return gBuf.getvalue(); } inline Str* fmt1(int a0) { gBuf.reset(); gBuf.write_const("-> dir stack ", 13); gBuf.format_d(a0); return gBuf.getvalue(); } inline Str* fmt2(int a0) { gBuf.reset(); gBuf.write_const("<- dir stack ", 13); gBuf.format_d(a0); return gBuf.getvalue(); } } // declare namespace scoped_resource namespace scoped_resource { // define MyError::MyError() : gc_heap::Obj(Tag::FixedSize, kZeroMask, sizeof(MyError)) { ; // pass } void Error(bool error) { if (error) { throw Alloc(); } } ctx_DirStack::ctx_DirStack(scoped_resource::DirStack* state, Str* entry) : gc_heap::Obj(Tag::FixedSize, kZeroMask, sizeof(ctx_DirStack)) { this->state = state; state->Push(entry); } ctx_DirStack::~ctx_DirStack(){ this->state->Pop(); } DirStack::DirStack() : gc_heap::Obj(Tag::FixedSize, kZeroMask, sizeof(DirStack)) { this->stack = Alloc>(); this->Reset(); } void DirStack::Reset() { this->stack->clear(); this->stack->append(str0); } void DirStack::Push(Str* entry) { StackRoots _roots({&entry}); this->stack->append(entry); } Str* DirStack::Pop() { if (len(this->stack) <= 1) { return nullptr; } this->stack->pop(); return this->stack->index(-1); } List* DirStack::Iter() { List* ret = nullptr; StackRoots _roots({&ret}); ret = Alloc>(); ret->extend(this->stack); ret->reverse(); return ret; } void DoWork(scoped_resource::DirStack* d, bool do_raise) { StackRoots _roots({&d}); { // with ctx_DirStack ctx(d, str1); println_stderr(fmt0(len(d->stack))); if (do_raise) { Error(do_raise); } } } void run_tests() { scoped_resource::DirStack* d = nullptr; StackRoots _roots({&d}); d = Alloc(); for (ListIter it(NewList(std::initializer_list{false, true})); !it.Done(); it.Next()) { bool do_raise = it.Value(); StackRoots _for({&do_raise }); println_stderr(str3); println_stderr(fmt1(len(d->stack))); try { DoWork(d, do_raise); } catch (MyError*) { println_stderr(str5); } println_stderr(fmt2(len(d->stack))); } } void run_benchmarks() { scoped_resource::DirStack* d = nullptr; StackRoots _roots({&d}); d = Alloc(); for (int i = 0; i < 1000000; ++i) { try { { // with ctx_DirStack ctx(d, str7); if ((i % 10000) == 0) { throw Alloc(); } } } catch (MyError*) { println_stderr(str8); } } } } // define namespace scoped_resource int main(int argc, char **argv) { // gc_heap::gHeap.Init(512); gc_heap::gHeap.Init(128 << 10); // 128 KiB; doubling in size // gc_heap::gHeap.Init(400 << 20); // 400 MiB to avoid garbage collection if (getenv("BENCHMARK")) { fprintf(stderr, "Benchmarking...\n"); scoped_resource::run_benchmarks(); } else { scoped_resource::run_tests(); } }