#pragma once #include // std::forward, std::move #include // std::swap #include // std::decay namespace ipc { //////////////////////////////////////////////////////////////// /// Execute guard function when the enclosing scope exits //////////////////////////////////////////////////////////////// template class scope_guard { F destructor_; mutable bool dismiss_; public: template scope_guard(D && destructor) : destructor_(std::forward(destructor)) , dismiss_(false) { } scope_guard(scope_guard&& rhs) : destructor_(std::move(rhs.destructor_)) , dismiss_(true) /* dismiss rhs */ { std::swap(dismiss_, rhs.dismiss_); } ~scope_guard() { try { do_exit(); } /** * In the realm of exceptions, it is fundamental that you can do nothing * if your "undo/recover" action fails. */ catch (...) { /* Do nothing */ } } void swap(scope_guard & rhs) { std::swap(destructor_, rhs.destructor_); std::swap(dismiss_ , rhs.dismiss_); } void dismiss() const noexcept { dismiss_ = true; } void do_exit() { if (!dismiss_) { dismiss_ = true; destructor_(); } } }; template constexpr auto guard(D && destructor) noexcept { return scope_guard> { std::forward(destructor) }; } } // namespace ipc