forked from Kistler-Group/sdbus-cpp
feat: extend ScopeGuard with success and failure overloads (#384)
This commit is contained in:
committed by
GitHub
parent
934d51fa8a
commit
d80483cdc0
118
src/ScopeGuard.h
118
src/ScopeGuard.h
@ -55,62 +55,104 @@
|
|||||||
// return; // exiting scope normally
|
// return; // exiting scope normally
|
||||||
// }
|
// }
|
||||||
|
|
||||||
#define SCOPE_EXIT \
|
#define SCOPE_EXIT \
|
||||||
auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \
|
auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \
|
||||||
= ::sdbus::internal::detail::ScopeGuardOnExit() + [&]() \
|
= ::sdbus::internal::ScopeGuardOnExitTag{} + [&]() \
|
||||||
/**/
|
/**/
|
||||||
|
#define SCOPE_EXIT_NAMED(NAME) \
|
||||||
#define SCOPE_EXIT_NAMED(NAME) \
|
auto NAME \
|
||||||
auto NAME \
|
= ::sdbus::internal::ScopeGuardOnExitTag{} + [&]() \
|
||||||
= ::sdbus::internal::detail::ScopeGuardOnExit() + [&]() \
|
/**/
|
||||||
|
#define SCOPE_EXIT_SUCCESS \
|
||||||
|
auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \
|
||||||
|
= ::sdbus::internal::ScopeGuardOnExitSuccessTag{} + [&]() \
|
||||||
|
/**/
|
||||||
|
#define SCOPE_EXIT_SUCCESS_NAMED(NAME) \
|
||||||
|
auto NAME \
|
||||||
|
= ::sdbus::internal::ScopeGuardOnExitSuccessTag{} + [&]() \
|
||||||
|
/**/
|
||||||
|
#define SCOPE_EXIT_FAILURE \
|
||||||
|
auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \
|
||||||
|
= ::sdbus::internal::ScopeGuardOnExitFailureTag{} + [&]() \
|
||||||
|
/**/
|
||||||
|
#define SCOPE_EXIT_FAILURE_NAMED(NAME) \
|
||||||
|
auto NAME \
|
||||||
|
= ::sdbus::internal::ScopeGuardOnExitFailureTag{} + [&]() \
|
||||||
/**/
|
/**/
|
||||||
|
|
||||||
namespace sdbus::internal {
|
namespace sdbus::internal {
|
||||||
|
|
||||||
template <class _Fun>
|
struct ScopeGuardOnExitTag
|
||||||
|
{
|
||||||
|
static bool holds(int /*originalExceptions*/)
|
||||||
|
{
|
||||||
|
return true; // Always holds
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct ScopeGuardOnExitSuccessTag
|
||||||
|
{
|
||||||
|
static bool holds(int originalExceptions)
|
||||||
|
{
|
||||||
|
return originalExceptions == std::uncaught_exceptions(); // Only holds when no exception occurred within the scope
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct ScopeGuardOnExitFailureTag
|
||||||
|
{
|
||||||
|
static bool holds(int originalExceptions)
|
||||||
|
{
|
||||||
|
return originalExceptions != std::uncaught_exceptions(); // Only holds when an exception occurred within the scope
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class _Fun, typename _Tag>
|
||||||
class ScopeGuard
|
class ScopeGuard
|
||||||
{
|
{
|
||||||
_Fun fnc_;
|
|
||||||
bool active_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ScopeGuard(_Fun f)
|
ScopeGuard(_Fun f) : fnc_(std::move(f))
|
||||||
: fnc_(std::move(f))
|
|
||||||
, active_(true)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
~ScopeGuard()
|
|
||||||
|
ScopeGuard() = delete;
|
||||||
|
ScopeGuard(const ScopeGuard&) = delete;
|
||||||
|
ScopeGuard& operator=(const ScopeGuard&) = delete;
|
||||||
|
ScopeGuard(ScopeGuard&& rhs) : fnc_(std::move(rhs.fnc_)), active_(rhs.active_), exceptions_(rhs.exceptions_)
|
||||||
{
|
{
|
||||||
if (active_)
|
rhs.dismiss();
|
||||||
fnc_();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dismiss()
|
void dismiss()
|
||||||
{
|
{
|
||||||
active_ = false;
|
active_ = false;
|
||||||
}
|
}
|
||||||
ScopeGuard() = delete;
|
|
||||||
ScopeGuard(const ScopeGuard&) = delete;
|
~ScopeGuard()
|
||||||
ScopeGuard& operator=(const ScopeGuard&) = delete;
|
|
||||||
ScopeGuard(ScopeGuard&& rhs)
|
|
||||||
: fnc_(std::move(rhs.fnc_))
|
|
||||||
, active_(rhs.active_)
|
|
||||||
{
|
{
|
||||||
rhs.dismiss();
|
if (active_ && _Tag::holds(exceptions_))
|
||||||
|
fnc_();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
_Fun fnc_;
|
||||||
|
int exceptions_{std::uncaught_exceptions()};
|
||||||
|
bool active_{true};
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail
|
template <typename _Fun>
|
||||||
|
ScopeGuard<_Fun, ScopeGuardOnExitTag> operator+(ScopeGuardOnExitTag, _Fun&& fnc)
|
||||||
{
|
{
|
||||||
enum class ScopeGuardOnExit
|
return ScopeGuard<_Fun, ScopeGuardOnExitTag>(std::forward<_Fun>(fnc));
|
||||||
{
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// Helper function to auto-deduce type of the callable entity
|
template <typename _Fun>
|
||||||
template <typename _Fun>
|
ScopeGuard<_Fun, ScopeGuardOnExitSuccessTag> operator+(ScopeGuardOnExitSuccessTag, _Fun&& fnc)
|
||||||
ScopeGuard<_Fun> operator+(ScopeGuardOnExit, _Fun&& fnc)
|
{
|
||||||
{
|
return ScopeGuard<_Fun, ScopeGuardOnExitSuccessTag>(std::forward<_Fun>(fnc));
|
||||||
return ScopeGuard<_Fun>(std::forward<_Fun>(fnc));
|
}
|
||||||
}
|
|
||||||
|
template <typename _Fun>
|
||||||
|
ScopeGuard<_Fun, ScopeGuardOnExitFailureTag> operator+(ScopeGuardOnExitFailureTag, _Fun&& fnc)
|
||||||
|
{
|
||||||
|
return ScopeGuard<_Fun, ScopeGuardOnExitFailureTag>(std::forward<_Fun>(fnc));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -119,13 +161,9 @@ namespace sdbus::internal {
|
|||||||
#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2)
|
#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2)
|
||||||
|
|
||||||
#ifdef __COUNTER__
|
#ifdef __COUNTER__
|
||||||
#define ANONYMOUS_VARIABLE(str) \
|
#define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __COUNTER__)
|
||||||
CONCATENATE(str, __COUNTER__) \
|
|
||||||
/**/
|
|
||||||
#else
|
#else
|
||||||
#define ANONYMOUS_VARIABLE(str) \
|
#define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __LINE__)
|
||||||
CONCATENATE(str, __LINE__) \
|
|
||||||
/**/
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* SDBUS_CPP_INTERNAL_SCOPEGUARD_H_ */
|
#endif /* SDBUS_CPP_INTERNAL_SCOPEGUARD_H_ */
|
||||||
|
Reference in New Issue
Block a user