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 
28 namespace RCF {
29 
30  template<typename T1,typename T2>
31  class RecursionState
32  {
33  public:
34  RecursionState() :
35  mRecursing(),
36  mBreak(),
37  mT1(),
38  mT2()
39  {}
40 
41  void assign(const T1 &t1)
42  {
43  mT1 = t1;
44 
45  clearArg(t1);
46  }
47 
48  void assign(const T1 &t1, const T2 &t2)
49  {
50  mT1 = t1;
51  mT2 = t2;
52 
53  clearArg(t1);
54  clearArg(t2);
55  }
56 
57  void clear()
58  {
59  mRecursing = false;
60  mBreak = true;
61  mT1 = T1();
62  mT2 = T2();
63  }
64 
65  bool mRecursing;
66  bool mBreak;
67  T1 mT1;
68  T2 mT2;
69 
70  private:
71  void clearArg_(const ByteBuffer &byteBuffer, boost::mpl::true_*)
72  {
73  const_cast<ByteBuffer &>(byteBuffer).clear();
74  }
75 
76  template<typename T>
77  void clearArg_(const T &, boost::mpl::false_*)
78  {}
79 
80  template<typename T>
81  void clearArg(const T &t)
82  {
83  typedef typename boost::is_same<T, ByteBuffer>::type type;
84  clearArg_(t, (type*) 0);
85  }
86  };
87 
88  // Utility for avoiding recursive function calls on the stack, by unwinding
89  // the relevant part of the stack and then reissuing the requested function
90  // call.
91 
92  template<typename StateT, typename X, typename Pfn>
93  void applyRecursionLimiter(
94  StateT & state,
95  Pfn pfn,
96  X & x)
97  {
98  state.mBreak = false;
99 
100  //state.assign(t1);
101  if (state.mRecursing)
102  {
103  state.mRecursing = false;
104  }
105  else
106  {
107  // gcc295 seems to need the namespace qualifier for make_obj_guard anyway
108  using namespace boost::multi_index::detail;
109 
110  scope_guard guard = boost::multi_index::detail::make_obj_guard(
111  state,
112  &StateT::clear);
113 
114  RCF_UNUSED_VARIABLE(guard);
115 
116  while (!state.mRecursing && !state.mBreak)
117  {
118  state.mRecursing = true;
119  ((&x)->*pfn)();
120  }
121  }
122  }
123 
124 
125  template<typename StateT, typename X, typename Pfn, typename T1>
126  void applyRecursionLimiter(
127  StateT & state,
128  Pfn pfn,
129  X & x,
130  const T1 & t1)
131  {
132  state.mBreak = false;
133 
134  state.assign(t1);
135  if (state.mRecursing)
136  {
137  state.mRecursing = false;
138  }
139  else
140  {
141  // gcc295 seems to need the namespace qualifier for make_obj_guard anyway
142  using namespace boost::multi_index::detail;
143 
144  scope_guard guard = boost::multi_index::detail::make_obj_guard(
145  state,
146  &StateT::clear);
147 
148  RCF_UNUSED_VARIABLE(guard);
149 
150  while (!state.mRecursing && !state.mBreak)
151  {
152  state.mRecursing = true;
153  ((&x)->*pfn)(state.mT1);
154  }
155  }
156  }
157 
158  template<typename StateT, typename X, typename Pfn, typename T1, typename T2>
159  void applyRecursionLimiter(
160  StateT & state,
161  Pfn pfn,
162  X & x,
163  const T1 & t1,
164  const T2 & t2)
165  {
166  state.mBreak = false;
167 
168  state.assign(t1, t2);
169  if (state.mRecursing)
170  {
171  state.mRecursing = false;
172  }
173  else
174  {
175  // gcc295 seems to need the namespace qualifier for make_obj_guard anyway
176  using namespace boost::multi_index::detail;
177 
178  scope_guard guard = boost::multi_index::detail::make_obj_guard(
179  state,
180  &StateT::clear);
181 
182  RCF_UNUSED_VARIABLE(guard);
183 
184  while (!state.mRecursing && !state.mBreak)
185  {
186  state.mRecursing = true;
187  ((&x)->*pfn)(state.mT1, state.mT2);
188  }
189  }
190  }
191 
192 } // namespace RCF
193 
194 #endif // ! INCLUDE_RCF_RECURSIONLIMITER_HPP