RCFProto

- Main Page
- Classes
- Files

- File List

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