1 // 2 // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 #pragma once 8 9 #include "td/utils/common.h" 10 11 #include <cstdlib> 12 #include <memory> 13 #include <type_traits> 14 #include <utility> 15 16 namespace td { 17 18 class Guard { 19 public: 20 Guard() = default; 21 Guard(const Guard &other) = delete; 22 Guard &operator=(const Guard &other) = delete; 23 Guard(Guard &&other) = default; 24 Guard &operator=(Guard &&other) = default; 25 virtual ~Guard() = default; dismiss()26 virtual void dismiss() { 27 std::abort(); 28 } 29 }; 30 31 template <class FunctionT> 32 class LambdaGuard final : public Guard { 33 public: LambdaGuard(const FunctionT & func)34 explicit LambdaGuard(const FunctionT &func) : func_(func) { 35 } LambdaGuard(FunctionT && func)36 explicit LambdaGuard(FunctionT &&func) : func_(std::move(func)) { 37 } 38 LambdaGuard(const LambdaGuard &other) = delete; 39 LambdaGuard &operator=(const LambdaGuard &other) = delete; LambdaGuard(LambdaGuard && other)40 LambdaGuard(LambdaGuard &&other) : func_(std::move(other.func_)), dismissed_(other.dismissed_) { 41 other.dismissed_ = true; 42 } 43 LambdaGuard &operator=(LambdaGuard &&other) = delete; 44 dismiss()45 void dismiss() final { 46 dismissed_ = true; 47 } 48 ~LambdaGuard()49 ~LambdaGuard() final { 50 if (!dismissed_) { 51 func_(); 52 } 53 } 54 55 private: 56 FunctionT func_; 57 bool dismissed_ = false; 58 }; 59 60 template <class F> create_lambda_guard(F && f)61unique_ptr<Guard> create_lambda_guard(F &&f) { 62 return make_unique<LambdaGuard<F>>(std::forward<F>(f)); 63 } 64 template <class F> create_shared_lambda_guard(F && f)65std::shared_ptr<Guard> create_shared_lambda_guard(F &&f) { 66 return std::make_shared<LambdaGuard<F>>(std::forward<F>(f)); 67 } 68 69 enum class ScopeExit {}; 70 template <class FunctionT> 71 auto operator+(ScopeExit, FunctionT &&func) { 72 return LambdaGuard<std::decay_t<FunctionT>>(std::forward<FunctionT>(func)); 73 } 74 75 } // namespace td 76 77 #define SCOPE_EXIT auto TD_CONCAT(SCOPE_EXIT_VAR_, __LINE__) = ::td::ScopeExit() + [&] 78