HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
UT_ScopeExit.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_ScopeExit.h (UT Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __UT_SCOPEEXIT_H_INCLUDED__
12 #define __UT_SCOPEEXIT_H_INCLUDED__
13 
14 /// @file
15 ///
16 /// UT_SCOPE_EXIT/UT_AT_SCOPE_EXIT provides convenient mechanisms to do RAII
17 /// without writing a special struct does cleans up upon destruction. The code
18 /// within the scope exit block is executed in reverse order of declaration as
19 /// the innermost enclosing scope ends. If execution never passes through a
20 /// scope exit block in the first place, then it won't be executed.
21 ///
22 
23 #include "UT_API.h"
24 #include <utility> // for std::move()
25 
26 /// UT_ScopeExit which runs the given lambda on destruction
27 template <typename F>
29 {
30 public:
31  explicit UT_ScopeExit(F& action)
32  : myAction(action) { }
33  explicit UT_ScopeExit(const F&& action)
34  : myAction(action) { }
35  explicit UT_ScopeExit(F&& action)
36  : myAction(std::move(action)) { }
38  : myAction(std::move(other.myAction)) { }
39 
41  { myAction(); }
42 private:
43  F myAction;
44 };
45 
46 // Taken from the CppCon 2015 presentation, "Declarative Control Flow", by
47 // Andrei Alexandrescu.
48 // https://github.com/CppCon/CppCon2015/tree/master/Presentations/Declarative%20Control%20Flow
49 namespace UT_ScopeGuard
50 {
51 
52 // Helper type for the operator+() below
53 enum class OnExit { };
54 
55 // The operator+() is used to allow type deduction while leaving the function
56 // body at end of the statement.
57 // NB: To support a wider class of functors F, we can use
58 // UT_ScopeExit<typename std::decay<F>::type> but that would need to pull
59 // in <type_traits> which do not want to do.
60 template <typename F>
62 operator+(OnExit, F&& fn)
63 {
64  return UT_ScopeExit<F>(std::forward<F>(fn));
65 }
66 
67 } // namespace UT_ScopeGuard
68 
69 // UT_SCOPE_EXIT_VAR(name) creates a unique variable name<X> where <X> is
70 // different everytime the macro is used.
71 // TODO: Move this somewhere more generic for use
72 #define UT_SCOPE_EXIT_CONCAT_IMPL(x, y) x ## y
73 #define UT_SCOPE_EXIT_CONCAT(x, y) UT_SCOPE_EXIT_CONCAT_IMPL(x, y)
74 #define UT_SCOPE_EXIT_VAR(name) UT_SCOPE_EXIT_CONCAT(name, __COUNTER__)
75 
76 // Taken from the CppCon 2014 presentation,
77 // "C++11 in the Wild - Techniques from a Real Codebase", by Arthur O'Dwyer.
78 // https://github.com/CppCon/CppCon2014/tree/master/Presentations/C%2B%2B11%20in%20the%20Wild%20-%20Techniques%20from%20a%20Real%20Codebase
79 #define UT_SCOPE_EXIT_RUN_IMPL(func_name, scope_name, ...) \
80  auto func_name = [&]() { __VA_ARGS__; }; \
81  UT_ScopeExit<decltype(func_name)> scope_name(func_name) \
82  /**/
83 
84 /// Runs given statement within the parentheses when the scope exits.
85 /// @note Put the semi-colon outside the parentheses.
86 /// Example
87 /// @code
88 /// FILE *fp = ::fopen("foo", "r");
89 /// if (fp)
90 /// {
91 /// UT_AT_SCOPE_EXIT(::fclose(fp)); // <= NOTE: SEMI-COLON OUTSIDE
92 /// ...
93 /// }
94 /// @endcode
95 #define UT_AT_SCOPE_EXIT(...) \
96  UT_SCOPE_EXIT_RUN_IMPL(UT_SCOPE_EXIT_VAR(scope_exit_lambda), \
97  UT_SCOPE_EXIT_VAR(scope_exit_scope), \
98  __VA_ARGS__) \
99  /**/
100 
101 /// Runs given statement block after it when the current scope exits.
102 /// @note Put a semi-colon after the statement block!
103 /// Example
104 /// @code
105 /// FILE *fp = ::fopen("foo", "r");
106 /// UT_SCOPE_EXIT
107 /// {
108 /// if (fp)
109 /// ::fclose(fp);
110 /// }; // <= NOTE: SEMI-COLON ENDS THE BLOCK
111 /// @endcode
112 #define UT_SCOPE_EXIT \
113  auto UT_SCOPE_EXIT_VAR(scope_exit_scope) \
114  = UT_ScopeGuard::OnExit() + [&]() noexcept \
115  /**/
116 
117 #endif // __UT_SCOPEEXIT_H_INCLUDED__
UT_ScopeExit(F &action)
Definition: UT_ScopeExit.h:31
UT_ScopeExit which runs the given lambda on destruction.
Definition: UT_ScopeExit.h:28
UT_ScopeExit< F > operator+(OnExit, F &&fn)
Definition: UT_ScopeExit.h:62
UT_ScopeExit(F &&action)
Definition: UT_ScopeExit.h:35
UT_ScopeExit(UT_ScopeExit &&other)
Definition: UT_ScopeExit.h:37
UT_ScopeExit(const F &&action)
Definition: UT_ScopeExit.h:33