1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 #ifndef __DEFER_HEADER_ 19 #define __DEFER_HEADER_ 20 21 // Macro for running a block of code before function exits. 22 // Example: 23 // DEFER { 24 // fclose(hc); 25 // hc = nullptr; 26 // }; 27 // It works by creating a new local variable struct holding the lambda, the 28 // destructor of that struct will invoke the lambda. 29 30 // ScopeGuard ensures that the specified functor is executed no matter how the 31 // current scope exits. 32 template <typename F> class ScopeGuard { 33 public: ScopeGuard(F && f)34 constexpr ScopeGuard(F &&f) : f_(static_cast<F &&>(f)) {} ScopeGuard(ScopeGuard && that)35 constexpr ScopeGuard(ScopeGuard &&that) noexcept 36 : f_(that.f_), active_(that.active_) { 37 that.active_ = false; 38 } 39 40 template <typename Functor> ScopeGuard(ScopeGuard<Functor> && that)41 constexpr ScopeGuard(ScopeGuard<Functor> &&that) 42 : f_(that.f_), active_(that.active_) { 43 that.active_ = false; 44 } 45 ~ScopeGuard()46 ~ScopeGuard() { f_(); } 47 48 ScopeGuard() = delete; 49 ScopeGuard(const ScopeGuard &) = delete; 50 void operator=(const ScopeGuard &) = delete; 51 void operator=(ScopeGuard &&that) = delete; 52 53 private: 54 template <typename Functor> friend class ScopeGuard; 55 F f_; 56 bool active_ = true; 57 }; 58 59 constexpr struct { 60 template <typename F> constexpr auto operator<<(F &&f) const noexcept { 61 return ScopeGuard<F>(static_cast<F &&>(f)); 62 } 63 } deferrer; 64 65 #define TOKENPASTE1(x, y) x##y 66 #define TOKENPASTE2(x, y) TOKENPASTE1(x, y) 67 #define DEFER \ 68 auto TOKENPASTE2(_deferred_lambda_call, __COUNTER__) = deferrer \ 69 << [&]() mutable 70 71 #endif