Remote Call Framework 3.1
RecursionLimiter.hpp
1 
2 //******************************************************************************
3 // RCF - Remote Call Framework
4 //
5 // Copyright (c) 2005 - 2019, Delta V Software. All rights reserved.
6 // http://www.deltavsoft.com
7 //
8 // RCF is distributed under dual licenses - closed source or GPL.
9 // Consult your particular license for conditions of use.
10 //
11 // If you have not purchased a commercial license, you are using RCF
12 // under GPL terms.
13 //
14 // Version: 3.1
15 // Contact: support <at> deltavsoft.com
16 //
17 //******************************************************************************
18 
19 #ifndef INCLUDE_RCF_RECURSIONLIMITER_HPP
20 #define INCLUDE_RCF_RECURSIONLIMITER_HPP
21 
22 #include <type_traits>
23 
24 #include <RCF/TypeTraits.hpp>
25 #include <RCF/Tools.hpp>
26 
27 namespace RCF {
28 
29  class ByteBuffer;
30 
31  template<typename T1,typename T2>
32  class RecursionState
33  {
34  public:
35  RecursionState() :
36  mRecursing(),
37  mBreak(),
38  mT1(),
39  mT2()
40  {}
41 
42  void assign(const T1 &t1)
43  {
44  mT1 = t1;
45 
46  clearArg(t1);
47  }
48 
49  void assign(const T1 &t1, const T2 &t2)
50  {
51  mT1 = t1;
52  mT2 = t2;
53 
54  clearArg(t1);
55  clearArg(t2);
56  }
57 
58  void clear()
59  {
60  mRecursing = false;
61  mBreak = true;
62  mT1 = T1();
63  mT2 = T2();
64  }
65 
66  bool mRecursing;
67  bool mBreak;
68  T1 mT1;
69  T2 mT2;
70 
71  private:
72  void clearArg_(const ByteBuffer &byteBuffer, std::true_type *)
73  {
74  const_cast<ByteBuffer &>(byteBuffer).clear();
75  }
76 
77  template<typename T>
78  void clearArg_(const T &, std::false_type *)
79  {}
80 
81  template<typename T>
82  void clearArg(const T &t)
83  {
84  typedef typename std::is_same<T, ByteBuffer>::type type;
85  clearArg_(t, (type*) 0);
86  }
87  };
88 
89  // Utility for avoiding recursive function calls on the stack, by unwinding
90  // the relevant part of the stack and then reissuing the requested function
91  // call.
92 
93  template<typename StateT, typename X, typename Pfn>
94  void applyRecursionLimiter(
95  StateT & state,
96  Pfn pfn,
97  X & x)
98  {
99  state.mBreak = false;
100 
101  if (state.mRecursing)
102  {
103  state.mRecursing = false;
104  }
105  else
106  {
107  ScopeGuard guard([&]() { state.clear(); });
108 
109  while (!state.mRecursing && !state.mBreak)
110  {
111  state.mRecursing = true;
112  ((&x)->*pfn)();
113  }
114  }
115  }
116 
117 
118  template<typename StateT, typename X, typename Pfn, typename T1>
119  void applyRecursionLimiter(
120  StateT & state,
121  Pfn pfn,
122  X & x,
123  const T1 & t1)
124  {
125  state.mBreak = false;
126 
127  state.assign(t1);
128  if (state.mRecursing)
129  {
130  state.mRecursing = false;
131  }
132  else
133  {
134  ScopeGuard guard([&]() { state.clear(); });
135 
136  while (!state.mRecursing && !state.mBreak)
137  {
138  state.mRecursing = true;
139  ((&x)->*pfn)(state.mT1);
140  }
141  }
142  }
143 
144  template<typename StateT, typename X, typename Pfn, typename T1, typename T2>
145  void applyRecursionLimiter(
146  StateT & state,
147  Pfn pfn,
148  X & x,
149  const T1 & t1,
150  const T2 & t2)
151  {
152  state.mBreak = false;
153 
154  state.assign(t1, t2);
155  if (state.mRecursing)
156  {
157  state.mRecursing = false;
158  }
159  else
160  {
161  ScopeGuard guard([&]() { state.clear(); });
162 
163  while (!state.mRecursing && !state.mBreak)
164  {
165  state.mRecursing = true;
166  ((&x)->*pfn)(state.mT1, state.mT2);
167  }
168  }
169  }
170 
171 } // namespace RCF
172 
173 #endif // ! INCLUDE_RCF_RECURSIONLIMITER_HPP
Definition: AmiIoHandler.hpp:24