1 #pragma once
2 
3 namespace unwinder { namespace detail {
4 
5         template<typename Function>
6         class unwinder
7         {
8         public:
~unwinder()9             ~unwinder() noexcept
10             {
11                 if (!!function)
12                 {
13                     (*function)();
14                 }
15             }
16 
unwinder(Function * functionArg)17             explicit unwinder(Function* functionArg)
18                 : function(functionArg)
19             {
20             }
21 
dismiss()22             void dismiss()
23             {
24                 function = nullptr;
25             }
26 
27             unwinder& operator=(nullptr_t) {
28                 dismiss();
29                 return *this;
30             }
31 
32         private:
33             unwinder();
34             unwinder(const unwinder&);
35             unwinder& operator=(const unwinder&);
36 
37             Function* function;
38         };
39 } }
40 
41 #define UNWIND_MAKE_IDENTIFIER_EXPLICIT_PASTER(Prefix, Suffix) Prefix ## Suffix
42 #define UNWIND_MAKE_IDENTIFIER_EXPLICIT(Prefix, Suffix) UNWIND_MAKE_IDENTIFIER_EXPLICIT_PASTER(Prefix, Suffix)
43 
44 #define UNWIND_MAKE_IDENTIFIER(Prefix) UNWIND_MAKE_IDENTIFIER_EXPLICIT(Prefix, __LINE__)
45 
46 #define ON_UNWIND(Name, Function) \
47 	ON_UNWIND_EXPLICIT(uwfunc_ ## Name, Name, Function)
48 
49 #define ON_UNWIND_AUTO(Function) \
50 	ON_UNWIND_EXPLICIT(UNWIND_MAKE_IDENTIFIER(uwfunc_), UNWIND_MAKE_IDENTIFIER(unwind_), Function)
51 
52 #define ON_UNWIND_EXPLICIT(FunctionName, UnwinderName, Function) \
53 	auto FunctionName = (Function); \
54 	::unwinder::detail::unwinder<decltype(FunctionName)> UnwinderName(std::addressof(FunctionName))
55