NetBurner 3.5.6
PDF Version
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#define DEFER_CALL(fn) _ScopeGuard DEFER_CONCAT(__defer__, __LINE__) = [&]() { fn; };
20
21class _ScopeGuard
22{
23 public:
24 template<class Callable>
25 _ScopeGuard(Callable &&fn) : fn_(std::forward<Callable>(fn))
26 {
27 }
28
29 _ScopeGuard(_ScopeGuard &&other) : fn_(std::move(other.fn_)) { other.fn_ = nullptr; }
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
48class _ReentrancyGuard
49{
50 public:
51 template<class Callable>
52 _ReentrancyGuard(int &entered, Callable &&fn) : depth(entered)
53 {
54 if (depth) { fn(); }
55 depth++;
56 }
57
58 _ReentrancyGuard(_ReentrancyGuard &&other) : depth(other.depth) {}
59
60 ~_ReentrancyGuard() { depth--; }
61
62 _ReentrancyGuard(const _ReentrancyGuard &) = delete;
63 void operator=(const _ReentrancyGuard &) = delete;
64
65 private:
66 int &depth;
67};
68
69#endif /* ----- #ifndef __DEFER_H ----- */