make sse4.2 functions in folly/Range.h build on -fb platform
[folly.git] / folly / ScopeGuard.h
1 /*
2  * Copyright 2013 Facebook, Inc.
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 #ifndef FOLLY_SCOPEGUARD_H_
18 #define FOLLY_SCOPEGUARD_H_
19
20 #include <cstddef>
21 #include <functional>
22 #include <new>
23
24 #include "folly/Preprocessor.h"
25
26 namespace folly {
27
28 /**
29  * ScopeGuard is a general implementation of the "Initialization is
30  * Resource Acquisition" idiom.  Basically, it guarantees that a function
31  * is executed upon leaving the currrent scope unless otherwise told.
32  *
33  * The makeGuard() function is used to create a new ScopeGuard object.
34  * It can be instantiated with a lambda function, a std::function<void()>,
35  * a functor, or a void(*)() function pointer.
36  *
37  *
38  * Usage example: Add a friend to memory iff it is also added to the db.
39  *
40  * void User::addFriend(User& newFriend) {
41  *   // add the friend to memory
42  *   friends_.push_back(&newFriend);
43  *
44  *   // If the db insertion that follows fails, we should
45  *   // remove it from memory.
46  *   // (You could also declare this as "auto guard = makeGuard(...)")
47  *   ScopeGuard guard = makeGuard([&] { friends_.pop_back(); });
48  *
49  *   // this will throw an exception upon error, which
50  *   // makes the ScopeGuard execute UserCont::pop_back()
51  *   // once the Guard's destructor is called.
52  *   db_->addFriend(GetName(), newFriend.GetName());
53  *
54  *   // an exception was not thrown, so don't execute
55  *   // the Guard.
56  *   guard.dismiss();
57  * }
58  *
59  * Examine ScopeGuardTest.cpp for some more sample usage.
60  *
61  * Stolen from:
62  *   Andrei's and Petru Marginean's CUJ article:
63  *     http://drdobbs.com/184403758
64  *   and the loki library:
65  *     http://loki-lib.sourceforge.net/index.php?n=Idioms.ScopeGuardPointer
66  *   and triendl.kj article:
67  *     http://www.codeproject.com/KB/cpp/scope_guard.aspx
68  */
69 class ScopeGuardImplBase {
70  public:
71   void dismiss() noexcept {
72     dismissed_ = true;
73   }
74
75  protected:
76   ScopeGuardImplBase()
77     : dismissed_(false) {}
78
79   ScopeGuardImplBase(ScopeGuardImplBase&& other)
80     : dismissed_(other.dismissed_) {
81     other.dismissed_ = true;
82   }
83
84   bool dismissed_;
85 };
86
87 template<typename FunctionType>
88 class ScopeGuardImpl : public ScopeGuardImplBase {
89  public:
90   explicit ScopeGuardImpl(const FunctionType& fn)
91     : function_(fn) {}
92
93   explicit ScopeGuardImpl(FunctionType&& fn)
94     : function_(std::move(fn)) {}
95
96   ScopeGuardImpl(ScopeGuardImpl&& other)
97     : ScopeGuardImplBase(std::move(other)),
98       function_(std::move(other.function_)) {
99   }
100
101   ~ScopeGuardImpl() noexcept {
102     if (!dismissed_) {
103       execute();
104     }
105   }
106
107 private:
108   void* operator new(size_t) = delete;
109
110   void execute() noexcept { function_(); }
111
112   FunctionType function_;
113 };
114
115 template<typename FunctionType>
116 ScopeGuardImpl<typename std::decay<FunctionType>::type>
117 makeGuard(FunctionType&& fn) {
118   return ScopeGuardImpl<typename std::decay<FunctionType>::type>(
119       std::forward<FunctionType>(fn));
120 }
121
122 /**
123  * This is largely unneeded if you just use auto for your guards.
124  */
125 typedef ScopeGuardImplBase&& ScopeGuard;
126
127 namespace detail {
128 /**
129  * Internal use for the macro SCOPE_EXIT below
130  */
131 enum class ScopeGuardOnExit {};
132
133 template <typename FunctionType>
134 ScopeGuardImpl<typename std::decay<FunctionType>::type>
135 operator+(detail::ScopeGuardOnExit, FunctionType&& fn) {
136   return ScopeGuardImpl<typename std::decay<FunctionType>::type>(
137       std::forward<FunctionType>(fn));
138 }
139 } // namespace detail
140
141 } // folly
142
143 #define SCOPE_EXIT \
144   auto FB_ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \
145   = ::folly::detail::ScopeGuardOnExit() + [&]
146
147 #endif // FOLLY_SCOPEGUARD_H_