NetBurner 3.1
defer.h
1 #ifndef __DEFER_H
2 #define __DEFER_H
3 /* As posted by Oded Lazar, modified from StackOverflow user R. Martinho Fernandes, */
4 /* and originally published by Andrei Alexandrescu and Petru Marginean in Dr. Dobbs
5  * December 2000 */
6 /* https://oded.blog/2017/10/05/go-defer-in-cpp/ */
7 /* https://stackoverflow.com/questions/10270328/the-simplest-and-neatest-c11-scopeguard/ */
8 /* http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758 */
9 /*NB_REVISION*/
10 
11 /*NB_COPYRIGHT*/
12 
13 #include <functional>
14 #include <utility>
15 
16 #define DEFER_CONCAT_(a, b) a ## b
17 #define DEFER_CONCAT(a, b) DEFER_CONCAT_(a,b)
18 
19 
20 #define DEFER_CALL(fn) _ScopeGuard DEFER_CONCAT(__defer__, __LINE__) = [&] ( ) { fn ; };
21 
22 class _ScopeGuard {
23  public:
24  template<class Callable>
25  _ScopeGuard(Callable &&fn) : fn_(std::forward<Callable>(fn)) {}
26 
27  _ScopeGuard(_ScopeGuard &&other) : fn_(std::move(other.fn_)) {
28  other.fn_ = nullptr;
29  }
30 
31  ~_ScopeGuard()
32  {
33  // must not throw
34  if (fn_) fn_();
35  }
36 
37  _ScopeGuard(const _ScopeGuard &) = delete;
38  void operator=(const _ScopeGuard &) = delete;
39 
40  private:
41  std::function<void()> fn_;
42 };
43 
44 #define IF_REENTERED(fn) \
45  static int DEFER_CONCAT(__reenter_guard_depth__, __LINE__) = 0; \
46  _ReentrancyGuard DEFER_CONCAT(__reenter_guard__, __LINE__)(DEFER_CONCAT(__reenter_guard_depth__, __LINE__), [&] ( ) { fn ; });
47 
48 class _ReentrancyGuard {
49  public:
50  template<class Callable>
51  _ReentrancyGuard(int &entered, Callable &&fn) : depth(entered)
52  {
53  if (depth) { fn(); }
54  depth++;
55  }
56 
57  _ReentrancyGuard(_ReentrancyGuard &&other) : depth(other.depth) { }
58 
59  ~_ReentrancyGuard()
60  {
61  depth--;
62  }
63 
64  _ReentrancyGuard(const _ReentrancyGuard &) = delete;
65  void operator=(const _ReentrancyGuard &) = delete;
66 
67  private:
68  int &depth;
69 };
70 
71 #endif /* ----- #ifndef __DEFER_H ----- */