Lua: Don't lua_error() out of context with pending dtors
[lsnes.git] / src / library / exrethrow.cpp
blob8a47cf066c00b4d3e7c5bda07d1f3a2c2d43a463
1 #include "exrethrow.hpp"
2 #include <list>
3 #include <iostream>
4 #include <future>
6 namespace exrethrow
8 ex_spec<std::exception, 0> std_exception;
9 ex_spec<std::logic_error, 1> std_logic_error;
10 ex_spec<std::domain_error, 2> std_domain_error;
11 ex_spec<std::invalid_argument, 2> std_invalid_argument;
12 ex_spec<std::length_error, 2> std_length_error;
13 ex_spec<std::out_of_range, 2> std_out_of_range;
14 ex_spec<std::future_error, 2> std_future_error;
15 ex_spec<std::runtime_error, 1> std_runtime_error;
16 ex_spec<std::range_error, 2> std_range_error;
17 ex_spec<std::overflow_error, 2> std_overflow_error;
18 ex_spec<std::underflow_error, 2> std_underflow_error;
19 ex_spec<std::system_error, 2> std_system_error;
20 ex_spec<std::bad_cast, 1> std_bad_cast;
21 ex_spec<std::bad_exception, 1> std_bad_exception;
22 ex_spec<std::bad_function_call, 1> std_bad_function_call;
23 ex_spec<std::bad_typeid, 1> std_bad_typeid;
24 ex_spec<std::bad_weak_ptr, 1> std_bad_weak_ptr;
25 ex_spec<std::ios_base::failure, 1> std_ios_base_failure;
27 struct exspec_item {
28 unsigned prio;
29 std::function<bool(std::exception& e)> identify;
30 std::function<void()> (*throwfn)(std::exception& e);
32 std::list<exspec_item>* exspecs;
34 void add_ex_spec(unsigned prio, std::function<bool(std::exception& e)> identify,
35 std::function<void()> (*throwfn)(std::exception& e))
37 exspec_item i;
38 i.prio = prio;
39 i.identify = identify;
40 i.throwfn = throwfn;
41 if(!exspecs)
42 exspecs = new std::list<exspec_item>;
43 for(auto j = exspecs->begin(); j != exspecs->end(); j++) {
44 if(j->prio <= prio) {
45 exspecs->insert(j, i);
46 return;
49 exspecs->push_back(i);
52 std::function<void()> get_throw_fn(std::exception& e)
54 for(auto& i : *exspecs) {
55 if(i.identify(e))
56 return i.throwfn(e);
58 return []() -> void { throw std::runtime_error("Unknown exception"); };
61 storage::storage()
63 null = true;
66 storage::storage(std::exception& e)
68 null = false;
69 oom = false;
70 if(dynamic_cast<std::bad_alloc*>(&e)) {
71 oom = true;
72 return;
74 try {
75 do_rethrow = get_throw_fn(e);
76 } catch(...) {
77 oom = true;
81 void storage::rethrow()
83 if(null) return;
84 if(oom)
85 throw std::bad_alloc();
86 do_rethrow();
89 storage::operator bool()
91 return !null;