File indexing completed on 2025-01-18 09:54:52
0001
0002
0003
0004
0005 #ifndef CPPCORO_ON_SCOPE_EXIT_HPP_INCLUDED
0006 #define CPPCORO_ON_SCOPE_EXIT_HPP_INCLUDED
0007
0008 #include <type_traits>
0009 #include <exception>
0010
0011 namespace cppcoro
0012 {
0013 template<typename FUNC>
0014 class scoped_lambda
0015 {
0016 public:
0017
0018 scoped_lambda(FUNC&& func)
0019 : m_func(std::forward<FUNC>(func))
0020 , m_cancelled(false)
0021 {}
0022
0023 scoped_lambda(const scoped_lambda& other) = delete;
0024
0025 scoped_lambda(scoped_lambda&& other)
0026 : m_func(std::forward<FUNC>(other.m_func))
0027 , m_cancelled(other.m_cancelled)
0028 {
0029 other.cancel();
0030 }
0031
0032 ~scoped_lambda()
0033 {
0034 if (!m_cancelled)
0035 {
0036 m_func();
0037 }
0038 }
0039
0040 void cancel()
0041 {
0042 m_cancelled = true;
0043 }
0044
0045 void call_now()
0046 {
0047 m_cancelled = true;
0048 m_func();
0049 }
0050
0051 private:
0052
0053 FUNC m_func;
0054 bool m_cancelled;
0055
0056 };
0057
0058
0059
0060
0061 template<typename FUNC, bool CALL_ON_FAILURE>
0062 class conditional_scoped_lambda
0063 {
0064 public:
0065
0066 conditional_scoped_lambda(FUNC&& func)
0067 : m_func(std::forward<FUNC>(func))
0068 , m_uncaughtExceptionCount(std::uncaught_exceptions())
0069 , m_cancelled(false)
0070 {}
0071
0072 conditional_scoped_lambda(const conditional_scoped_lambda& other) = delete;
0073
0074 conditional_scoped_lambda(conditional_scoped_lambda&& other)
0075 noexcept(std::is_nothrow_move_constructible<FUNC>::value)
0076 : m_func(std::forward<FUNC>(other.m_func))
0077 , m_uncaughtExceptionCount(other.m_uncaughtExceptionCount)
0078 , m_cancelled(other.m_cancelled)
0079 {
0080 other.cancel();
0081 }
0082
0083 ~conditional_scoped_lambda() noexcept(CALL_ON_FAILURE || noexcept(std::declval<FUNC>()()))
0084 {
0085 if (!m_cancelled && (is_unwinding_due_to_exception() == CALL_ON_FAILURE))
0086 {
0087 m_func();
0088 }
0089 }
0090
0091 void cancel() noexcept
0092 {
0093 m_cancelled = true;
0094 }
0095
0096 private:
0097
0098 bool is_unwinding_due_to_exception() const noexcept
0099 {
0100 return std::uncaught_exceptions() > m_uncaughtExceptionCount;
0101 }
0102
0103 FUNC m_func;
0104 int m_uncaughtExceptionCount;
0105 bool m_cancelled;
0106
0107 };
0108
0109
0110
0111
0112
0113
0114
0115
0116 template<typename FUNC>
0117 auto on_scope_exit(FUNC&& func)
0118 {
0119 return scoped_lambda<FUNC>{ std::forward<FUNC>(func) };
0120 }
0121
0122
0123
0124
0125
0126
0127
0128 template<typename FUNC>
0129 auto on_scope_failure(FUNC&& func)
0130 {
0131 return conditional_scoped_lambda<FUNC, true>{ std::forward<FUNC>(func) };
0132 }
0133
0134
0135
0136
0137
0138
0139
0140 template<typename FUNC>
0141 auto on_scope_success(FUNC&& func)
0142 {
0143 return conditional_scoped_lambda<FUNC, false>{ std::forward<FUNC>(func) };
0144 }
0145 }
0146
0147 #endif