2 * Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
8 #ifndef LTTNG_SCOPE_EXIT_H
9 #define LTTNG_SCOPE_EXIT_H
16 /* Is operator() of InvocableType is marked as noexcept? */
17 template <typename InvocableType>
18 struct is_invocation_noexcept
19 : std::integral_constant<bool, noexcept((std::declval<InvocableType>())())> {
21 } /* namespace details. */
24 * Generic utility to run a lambda (or any other invocable object) when leaving
27 * Notably, this makes it easy to specify an action (e.g. restore a context)
28 * that must occur at the end of a function or roll-back operations in an
31 template <typename ScopeExitInvocableType>
35 * Since ScopeExitInvocableType will be invoked in the destructor, it
36 * must be `noexcept` lest we anger the undefined behaviour gods.
38 static_assert(details::is_invocation_noexcept<ScopeExitInvocableType>::value,
39 "scope_exit requires a noexcept invocable type");
41 explicit scope_exit(ScopeExitInvocableType&& scope_exit_callable) :
42 _on_scope_exit{std::forward<ScopeExitInvocableType>(scope_exit_callable)}
46 scope_exit(scope_exit&& rhs) :
47 _on_scope_exit{std::move(rhs._on_scope_exit)}, _armed{rhs._armed}
49 /* Don't invoke ScopeExitInvocableType for the moved-from copy. */
54 * The copy constructor is disabled to prevent the action from being
55 * executed twice should a copy be performed accidentaly.
57 * The move-constructor is present to enable make_scope_exit() but to
58 * also propagate the scope_exit to another scope, should it be needed.
60 scope_exit(const scope_exit&) = delete;
61 scope_exit() = delete;
63 void disarm() noexcept
76 ScopeExitInvocableType _on_scope_exit;
80 template <typename ScopeExitInvocableType>
81 scope_exit<ScopeExitInvocableType> make_scope_exit(ScopeExitInvocableType&& scope_exit_callable)
83 return scope_exit<ScopeExitInvocableType>(
84 std::forward<ScopeExitInvocableType>(scope_exit_callable));
87 } /* namespace lttng */
89 #endif /* LTTNG_SCOPE_EXIT_H */