RCFProto
 All Classes Functions Typedefs
RecursionLimiter.hpp
1 
2 //******************************************************************************
3 // RCF - Remote Call Framework
4 //
5 // Copyright (c) 2005 - 2013, 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: 2.0
15 // Contact: support <at> deltavsoft.com
16 //
17 //******************************************************************************
18 
19 #ifndef INCLUDE_RCF_RECURSIONLIMITER_HPP
20 #define INCLUDE_RCF_RECURSIONLIMITER_HPP
21 
22 #include <boost/type_traits/is_same.hpp>
23 #include <boost/mpl/bool.hpp>
24 
25 #include <RCF/ByteBuffer.hpp>
26 #include <RCF/Tools.hpp>
27 #include <RCF/TypeTraits.hpp>
28 
29 namespace RCF {
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, TrueType *)
73  {
74  const_cast<ByteBuffer &>(byteBuffer).clear();
75  }
76 
77  template<typename T>
78  void clearArg_(const T &, FalseType *)
79  {}
80 
81  template<typename T>
82  void clearArg(const T &t)
83  {
84  typedef typename boost::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  //state.assign(t1);
102  if (state.mRecursing)
103  {
104  state.mRecursing = false;
105  }
106  else
107  {
108  // gcc295 seems to need the namespace qualifier for make_obj_guard anyway
109  using namespace boost::multi_index::detail;
110 
111  scope_guard guard = boost::multi_index::detail::make_obj_guard(
112  state,
113  &StateT::clear);
114 
115  RCF_UNUSED_VARIABLE(guard);
116 
117  while (!state.mRecursing && !state.mBreak)
118  {
119  state.mRecursing = true;
120  ((&x)->*pfn)();
121  }
122  }
123  }
124 
125 
126  template<typename StateT, typename X, typename Pfn, typename T1>
127  void applyRecursionLimiter(
128  StateT & state,
129  Pfn pfn,
130  X & x,
131  const T1 & t1)
132  {
133  state.mBreak = false;
134 
135  state.assign(t1);
136  if (state.mRecursing)
137  {
138  state.mRecursing = false;
139  }
140  else
141  {
142  // gcc295 seems to need the namespace qualifier for make_obj_guard anyway
143  using namespace boost::multi_index::detail;
144 
145  scope_guard guard = boost::multi_index::detail::make_obj_guard(
146  state,
147  &StateT::clear);
148 
149  RCF_UNUSED_VARIABLE(guard);
150 
151  while (!state.mRecursing && !state.mBreak)
152  {
153  state.mRecursing = true;
154  ((&x)->*pfn)(state.mT1);
155  }
156  }
157  }
158 
159  template<typename StateT, typename X, typename Pfn, typename T1, typename T2>
160  void applyRecursionLimiter(
161  StateT & state,
162  Pfn pfn,
163  X & x,
164  const T1 & t1,
165  const T2 & t2)
166  {
167  state.mBreak = false;
168 
169  state.assign(t1, t2);
170  if (state.mRecursing)
171  {
172  state.mRecursing = false;
173  }
174  else
175  {
176  // gcc295 seems to need the namespace qualifier for make_obj_guard anyway
177  using namespace boost::multi_index::detail;
178 
179  scope_guard guard = boost::multi_index::detail::make_obj_guard(
180  state,
181  &StateT::clear);
182 
183  RCF_UNUSED_VARIABLE(guard);
184 
185  while (!state.mRecursing && !state.mBreak)
186  {
187  state.mRecursing = true;
188  ((&x)->*pfn)(state.mT1, state.mT2);
189  }
190  }
191  }
192 
193 } // namespace RCF
194 
195 #endif // ! INCLUDE_RCF_RECURSIONLIMITER_HPP