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