1 #pragma once 2 3 namespace unwinder { namespace detail { 4 5 template<typename Function> 6 class unwinder 7 { 8 public: 9 ~unwinder() noexcept 10 { 11 if (!!function) 12 { 13 (*function)(); 14 } 15 } 16 17 explicit unwinder(Function* functionArg) 18 : function(functionArg) 19 { 20 } 21 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