]>
Commit | Line | Data |
---|---|---|
c4549a7b JR |
1 | From 9a7bd89fd15be9af3b676cd1d7a28338e6c8cd15 Mon Sep 17 00:00:00 2001 |
2 | From: Michael Steinberg <michsteinb@gmail.com> | |
3 | Date: Tue, 5 Jul 2016 00:14:32 +0200 | |
4 | Subject: [PATCH 1/3] boost::context fixes to make it compatible with boost | |
5 | 1.61 | |
6 | ||
7 | (cherry picked from commit 06d4894fdbeb00727cdcc667b8899ad73d8eb1c2) | |
8 | --- | |
9 | common/tool/tool_manager.cpp | 6 +- | |
10 | include/tool/coroutine.h | 162 ++++++++++++++++++++++++++-------------- | |
11 | include/tool/tool_base.h | 7 +- | |
12 | include/tool/tool_interactive.h | 3 +- | |
13 | 4 files changed, 116 insertions(+), 62 deletions(-) | |
14 | ||
15 | diff --git a/common/tool/tool_manager.cpp b/common/tool/tool_manager.cpp | |
16 | index 447ab99..a198c69 100644 | |
17 | --- a/common/tool/tool_manager.cpp | |
18 | +++ b/common/tool/tool_manager.cpp | |
19 | @@ -528,7 +528,7 @@ void TOOL_MANAGER::dispatchInternal( const TOOL_EVENT& aEvent ) | |
20 | } | |
21 | } | |
22 | ||
23 | - BOOST_FOREACH( TOOL_STATE* st, m_toolState | boost::adaptors::map_values ) | |
24 | + for( TOOL_STATE* st : ( m_toolState | boost::adaptors::map_values ) ) | |
25 | { | |
26 | // no state handler in progress - check if there are any transitions (defined by | |
27 | // Go() method that match the event. | |
28 | @@ -542,11 +542,11 @@ void TOOL_MANAGER::dispatchInternal( const TOOL_EVENT& aEvent ) | |
29 | if( st->cofunc ) | |
30 | st->Push(); | |
31 | ||
32 | + st->cofunc = new COROUTINE<int, const TOOL_EVENT&>( tr.second ); | |
33 | + | |
34 | // as the state changes, the transition table has to be set up again | |
35 | st->transitions.clear(); | |
36 | ||
37 | - st->cofunc = new COROUTINE<int, const TOOL_EVENT&>( tr.second ); | |
38 | - | |
39 | // got match? Run the handler. | |
40 | st->cofunc->Call( aEvent ); | |
41 | ||
42 | diff --git a/include/tool/coroutine.h b/include/tool/coroutine.h | |
43 | index c7eaf5f..e21e18f 100644 | |
44 | --- a/include/tool/coroutine.h | |
45 | +++ b/include/tool/coroutine.h | |
46 | @@ -3,6 +3,7 @@ | |
47 | * | |
48 | * Copyright (C) 2013 CERN | |
49 | * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> | |
50 | + * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors. | |
51 | * | |
52 | * This program is free software; you can redistribute it and/or | |
53 | * modify it under the terms of the GNU General Public License | |
54 | @@ -27,10 +28,14 @@ | |
55 | ||
56 | #include <cstdlib> | |
57 | ||
58 | -#include <boost/context/fcontext.hpp> | |
59 | #include <boost/version.hpp> | |
60 | +#include <type_traits> | |
61 | ||
62 | -#include "delegate.h" | |
63 | +#if BOOST_VERSION <= 106000 | |
64 | +#include <boost/context/fcontext.hpp> | |
65 | +#else | |
66 | +#include <boost/context/execution_context.hpp> | |
67 | +#endif | |
68 | ||
69 | /** | |
70 | * Class COROUNTINE. | |
71 | @@ -53,13 +58,12 @@ | |
72 | * See coroutine_example.cpp for sample code. | |
73 | */ | |
74 | ||
75 | -template <class ReturnType, class ArgType> | |
76 | +template <typename ReturnType, typename ArgType> | |
77 | class COROUTINE | |
78 | { | |
79 | public: | |
80 | COROUTINE() : | |
81 | - m_saved( NULL ), m_self( NULL ), m_stack( NULL ), m_stackSize( c_defaultStackSize ), | |
82 | - m_running( false ) | |
83 | + COROUTINE( nullptr ) | |
84 | { | |
85 | } | |
86 | ||
87 | @@ -69,8 +73,7 @@ public: | |
88 | */ | |
89 | template <class T> | |
90 | COROUTINE( T* object, ReturnType(T::* ptr)( ArgType ) ) : | |
91 | - m_func( object, ptr ), m_self( NULL ), m_saved( NULL ), m_stack( NULL ), | |
92 | - m_stackSize( c_defaultStackSize ), m_running( false ) | |
93 | + COROUTINE( std::bind( ptr, object, std::placeholders::_1 ) ) | |
94 | { | |
95 | } | |
96 | ||
97 | @@ -78,9 +81,15 @@ public: | |
98 | * Constructor | |
99 | * Creates a coroutine from a delegate object | |
100 | */ | |
101 | - COROUTINE( DELEGATE<ReturnType, ArgType> aEntry ) : | |
102 | - m_func( aEntry ), m_saved( NULL ), m_self( NULL ), m_stack( NULL ), | |
103 | - m_stackSize( c_defaultStackSize ), m_running( false ) | |
104 | + COROUTINE( std::function<ReturnType(ArgType)> aEntry ) : | |
105 | + m_func( std::move( aEntry ) ), | |
106 | + m_running( false ), | |
107 | +#if BOOST_VERSION <= 106000 | |
108 | + m_stack( nullptr ), | |
109 | + m_stackSize( c_defaultStackSize ), | |
110 | +#endif | |
111 | + m_caller( nullptr ), | |
112 | + m_callee( nullptr ) | |
113 | { | |
114 | // Avoid not initialized members, and make static analysers quiet | |
115 | m_args = 0; | |
116 | @@ -89,18 +98,26 @@ public: | |
117 | ||
118 | ~COROUTINE() | |
119 | { | |
120 | - if( m_saved ) | |
121 | - delete m_saved; | |
122 | - | |
123 | #if BOOST_VERSION >= 105600 | |
124 | - if( m_self ) | |
125 | - delete m_self; | |
126 | + delete m_callee; | |
127 | #endif | |
128 | ||
129 | +#if BOOST_VERSION <= 106000 | |
130 | + delete m_caller; | |
131 | + | |
132 | if( m_stack ) | |
133 | free( m_stack ); | |
134 | +#endif | |
135 | } | |
136 | ||
137 | +private: | |
138 | +#if BOOST_VERSION <= 106000 | |
139 | + using context_type = boost::context::fcontext_t; | |
140 | +#else | |
141 | + using context_type = boost::context::execution_context<COROUTINE*>; | |
142 | +#endif | |
143 | + | |
144 | +public: | |
145 | /** | |
146 | * Function Yield() | |
147 | * | |
148 | @@ -110,7 +127,12 @@ public: | |
149 | */ | |
150 | void Yield() | |
151 | { | |
152 | - jump( m_self, m_saved, 0 ); | |
153 | +#if BOOST_VERSION <= 106000 | |
154 | + jump( m_callee, m_caller, false ); | |
155 | +#else | |
156 | + auto result = (*m_caller)( this ); | |
157 | + *m_caller = std::move( std::get<0>( result ) ); | |
158 | +#endif | |
159 | } | |
160 | ||
161 | /** | |
162 | @@ -122,7 +144,11 @@ public: | |
163 | void Yield( ReturnType& aRetVal ) | |
164 | { | |
165 | m_retVal = aRetVal; | |
166 | - jump( m_self, m_saved, 0 ); | |
167 | +#if BOOST_VERSION <= 106000 | |
168 | + jump( m_callee, m_caller, false ); | |
169 | +#else | |
170 | + m_caller( this ); | |
171 | +#endif | |
172 | } | |
173 | ||
174 | /** | |
175 | @@ -130,9 +156,9 @@ public: | |
176 | * | |
177 | * Defines the entry point for the coroutine, if not set in the constructor. | |
178 | */ | |
179 | - void SetEntry( DELEGATE<ReturnType, ArgType> aEntry ) | |
180 | + void SetEntry( std::function<ReturnType(ArgType)> aEntry ) | |
181 | { | |
182 | - m_func = aEntry; | |
183 | + m_func = std::move( aEntry ); | |
184 | } | |
185 | ||
186 | /* Function Call() | |
187 | @@ -143,6 +169,10 @@ public: | |
188 | */ | |
189 | bool Call( ArgType aArgs ) | |
190 | { | |
191 | + assert( m_callee == NULL ); | |
192 | + assert( m_caller == NULL ); | |
193 | + | |
194 | +#if BOOST_VERSION <= 106000 | |
195 | // fixme: Clean up stack stuff. Add a guard | |
196 | m_stack = malloc( c_defaultStackSize ); | |
197 | ||
198 | @@ -151,22 +181,32 @@ public: | |
199 | ||
200 | // correct the stack size | |
201 | m_stackSize -= ( (size_t) m_stack + m_stackSize - (size_t) sp ); | |
202 | - | |
203 | - assert( m_self == NULL ); | |
204 | - assert( m_saved == NULL ); | |
205 | +#endif | |
206 | ||
207 | m_args = &aArgs; | |
208 | -#if BOOST_VERSION >= 105600 | |
209 | - m_self = new boost::context::fcontext_t(); | |
210 | - *m_self = boost::context::make_fcontext( sp, m_stackSize, callerStub ); | |
211 | + | |
212 | +#if BOOST_VERSION < 105600 | |
213 | + m_callee = boost::context::make_fcontext( sp, m_stackSize, callerStub ); | |
214 | +#elif BOOST_VERSION <= 106000 | |
215 | + m_callee = new context_type( boost::context::make_fcontext( sp, m_stackSize, callerStub ) ); | |
216 | #else | |
217 | - m_self = boost::context::make_fcontext( sp, m_stackSize, callerStub ); | |
218 | + m_callee = new context_type( std::allocator_arg_t(), | |
219 | + boost::context::fixedsize_stack( c_defaultStackSize ), &COROUTINE::callerStub ); | |
220 | +#endif | |
221 | + | |
222 | +#if BOOST_VERSION <= 106000 | |
223 | + m_caller = new context_type(); | |
224 | #endif | |
225 | - m_saved = new boost::context::fcontext_t(); | |
226 | ||
227 | m_running = true; | |
228 | + | |
229 | // off we go! | |
230 | - jump( m_saved, m_self, reinterpret_cast<intptr_t>( this ) ); | |
231 | +#if BOOST_VERSION <= 106000 | |
232 | + jump( m_caller, m_callee, reinterpret_cast<intptr_t>( this ) ); | |
233 | +#else | |
234 | + auto result = (*m_callee)( this ); | |
235 | + *m_callee = std::move( std::get<0>( result ) ); | |
236 | +#endif | |
237 | return m_running; | |
238 | } | |
239 | ||
240 | @@ -179,7 +219,12 @@ public: | |
241 | */ | |
242 | bool Resume() | |
243 | { | |
244 | - jump( m_saved, m_self, 0 ); | |
245 | +#if BOOST_VERSION <= 106000 | |
246 | + jump( m_caller, m_callee, false ); | |
247 | +#else | |
248 | + auto result = (*m_callee)( this ); | |
249 | + *m_callee = std::move( std::get<0>( result ) ); | |
250 | +#endif | |
251 | ||
252 | return m_running; | |
253 | } | |
254 | @@ -208,61 +253,66 @@ private: | |
255 | static const int c_defaultStackSize = 2000000; // fixme: make configurable | |
256 | ||
257 | /* real entry point of the coroutine */ | |
258 | +#if BOOST_VERSION <= 106000 | |
259 | static void callerStub( intptr_t aData ) | |
260 | +#else | |
261 | + static context_type callerStub( context_type caller, COROUTINE* cor ) | |
262 | +#endif | |
263 | { | |
264 | // get pointer to self | |
265 | +#if BOOST_VERSION <= 106000 | |
266 | COROUTINE<ReturnType, ArgType>* cor = reinterpret_cast<COROUTINE<ReturnType, ArgType>*>( aData ); | |
267 | +#else | |
268 | + cor->m_caller = &caller; | |
269 | +#endif | |
270 | ||
271 | // call the coroutine method | |
272 | - cor->m_retVal = cor->m_func( *cor->m_args ); | |
273 | + cor->m_retVal = cor->m_func( *( cor->m_args ) ); | |
274 | cor->m_running = false; | |
275 | ||
276 | // go back to wherever we came from. | |
277 | - jump( cor->m_self, cor->m_saved, 0 ); // reinterpret_cast<intptr_t>( this )); | |
278 | +#if BOOST_VERSION <= 106000 | |
279 | + jump( cor->m_callee, cor->m_caller, 0 ); | |
280 | +#else | |
281 | + return caller; | |
282 | +#endif | |
283 | } | |
284 | ||
285 | ///> Wrapper for jump_fcontext to assure compatibility between different boost versions | |
286 | - static inline intptr_t jump(boost::context::fcontext_t* aOld, boost::context::fcontext_t* aNew, | |
287 | +#if BOOST_VERSION <= 106000 | |
288 | + static inline intptr_t jump( context_type* aOld, context_type* aNew, | |
289 | intptr_t aP, bool aPreserveFPU = true ) | |
290 | { | |
291 | -#if BOOST_VERSION >= 105600 | |
292 | - return boost::context::jump_fcontext( aOld, *aNew, aP, aPreserveFPU ); | |
293 | -#else | |
294 | +#if BOOST_VERSION < 105600 | |
295 | return boost::context::jump_fcontext( aOld, aNew, aP, aPreserveFPU ); | |
296 | +#else | |
297 | + return boost::context::jump_fcontext( aOld, *aNew, aP, aPreserveFPU ); | |
298 | #endif | |
299 | } | |
300 | +#endif | |
301 | ||
302 | - template <typename T> | |
303 | - struct strip_ref | |
304 | - { | |
305 | - typedef T result; | |
306 | - }; | |
307 | + std::function<ReturnType(ArgType)> m_func; | |
308 | ||
309 | - template <typename T> | |
310 | - struct strip_ref<T&> | |
311 | - { | |
312 | - typedef T result; | |
313 | - }; | |
314 | + bool m_running; | |
315 | ||
316 | - DELEGATE<ReturnType, ArgType> m_func; | |
317 | +#if BOOST_VERSION <= 106000 | |
318 | + ///< coroutine stack | |
319 | + void* m_stack; | |
320 | + | |
321 | + size_t m_stackSize; | |
322 | +#endif | |
323 | ||
324 | ///< pointer to coroutine entry arguments. Stripped of references | |
325 | ///< to avoid compiler errors. | |
326 | - typename strip_ref<ArgType>::result* m_args; | |
327 | + typename std::remove_reference<ArgType>::type* m_args; | |
328 | + | |
329 | ReturnType m_retVal; | |
330 | ||
331 | ///< saved caller context | |
332 | - boost::context::fcontext_t* m_saved; | |
333 | + context_type* m_caller; | |
334 | ||
335 | ///< saved coroutine context | |
336 | - boost::context::fcontext_t* m_self; | |
337 | - | |
338 | - ///< coroutine stack | |
339 | - void* m_stack; | |
340 | - | |
341 | - size_t m_stackSize; | |
342 | - | |
343 | - bool m_running; | |
344 | + context_type* m_callee; | |
345 | }; | |
346 | ||
347 | #endif | |
348 | diff --git a/include/tool/tool_base.h b/include/tool/tool_base.h | |
349 | index 584a979..3bef987 100644 | |
350 | --- a/include/tool/tool_base.h | |
351 | +++ b/include/tool/tool_base.h | |
352 | @@ -3,6 +3,7 @@ | |
353 | * | |
354 | * Copyright (C) 2013 CERN | |
355 | * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> | |
356 | + * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors. | |
357 | * | |
358 | * This program is free software; you can redistribute it and/or | |
359 | * modify it under the terms of the GNU General Public License | |
360 | @@ -31,7 +32,7 @@ | |
361 | #include <tool/tool_event.h> | |
362 | #include <tool/tool_settings.h> | |
363 | ||
364 | -#include <tool/delegate.h> | |
365 | +#include <functional> | |
366 | ||
367 | class EDA_ITEM; | |
368 | class TOOL_MANAGER; | |
369 | @@ -53,7 +54,9 @@ enum TOOL_TYPE | |
370 | ||
371 | /// Unique identifier for tools | |
372 | typedef int TOOL_ID; | |
373 | -typedef DELEGATE<int, const TOOL_EVENT&> TOOL_STATE_FUNC; | |
374 | + | |
375 | +using TOOL_STATE_FUNC = std::function<int(const TOOL_EVENT&)>; | |
376 | + | |
377 | ||
378 | /** | |
379 | * Class TOOL_BASE | |
380 | diff --git a/include/tool/tool_interactive.h b/include/tool/tool_interactive.h | |
381 | index 17d2de7..240eb58 100644 | |
382 | --- a/include/tool/tool_interactive.h | |
383 | +++ b/include/tool/tool_interactive.h | |
384 | @@ -3,6 +3,7 @@ | |
385 | * | |
386 | * Copyright (C) 2013 CERN | |
387 | * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> | |
388 | + * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors. | |
389 | * | |
390 | * This program is free software; you can redistribute it and/or | |
391 | * modify it under the terms of the GNU General Public License | |
392 | @@ -113,7 +114,7 @@ template <class T> | |
393 | void TOOL_INTERACTIVE::Go( int (T::* aStateFunc)( const TOOL_EVENT& ), | |
394 | const TOOL_EVENT_LIST& aConditions ) | |
395 | { | |
396 | - TOOL_STATE_FUNC sptr( static_cast<T*>( this ), aStateFunc ); | |
397 | + TOOL_STATE_FUNC sptr = std::bind( aStateFunc, static_cast<T*>( this ), std::placeholders::_1 ); | |
398 | ||
399 | goInternal( sptr, aConditions ); | |
400 | } | |
401 | -- | |
402 | 2.9.3 | |
403 | ||
404 | From 157c499b031659b895c1a7fef056d02a94bce0b3 Mon Sep 17 00:00:00 2001 | |
405 | From: decimad <michsteinb@gmail.com> | |
406 | Date: Tue, 5 Jul 2016 18:02:50 +0200 | |
407 | Subject: [PATCH 2/3] use a guarded stack for coroutines in boost version 1.61 | |
408 | ||
409 | (cherry picked from commit 78bc3c65de6c03d19be9902327d08cd4d87c229c) | |
410 | --- | |
411 | include/tool/coroutine.h | 3 ++- | |
412 | 1 file changed, 2 insertions(+), 1 deletion(-) | |
413 | ||
414 | diff --git a/include/tool/coroutine.h b/include/tool/coroutine.h | |
415 | index e21e18f..8e472ca 100644 | |
416 | --- a/include/tool/coroutine.h | |
417 | +++ b/include/tool/coroutine.h | |
418 | @@ -35,6 +35,7 @@ | |
419 | #include <boost/context/fcontext.hpp> | |
420 | #else | |
421 | #include <boost/context/execution_context.hpp> | |
422 | +#include <boost/context/protected_fixedsize_stack.hpp> | |
423 | #endif | |
424 | ||
425 | /** | |
426 | @@ -191,7 +192,7 @@ public: | |
427 | m_callee = new context_type( boost::context::make_fcontext( sp, m_stackSize, callerStub ) ); | |
428 | #else | |
429 | m_callee = new context_type( std::allocator_arg_t(), | |
430 | - boost::context::fixedsize_stack( c_defaultStackSize ), &COROUTINE::callerStub ); | |
431 | + boost::context::protected_fixedsize_stack( c_defaultStackSize ), &COROUTINE::callerStub ); | |
432 | #endif | |
433 | ||
434 | #if BOOST_VERSION <= 106000 | |
435 | -- | |
436 | 2.9.3 | |
437 | ||
438 | From 418c62f03d9bd81881a17c9cca9c30f839d23e3a Mon Sep 17 00:00:00 2001 | |
439 | From: decimad <michsteinb@gmail.com> | |
440 | Date: Tue, 2 Aug 2016 11:39:39 +0200 | |
441 | Subject: [PATCH 3/3] Refactor coroutine to improve readability and removed | |
442 | unnecessary heap allocations. Added documentation/links to various boost doc | |
443 | revisions. | |
444 | ||
445 | (cherry picked from commit 18b7dbf4d166fcb7da10ced72268a77f02448188) | |
446 | --- | |
447 | include/tool/coroutine.h | 221 +++++++++++++++++++++++++---------------------- | |
448 | include/tool/delegate.h | 100 --------------------- | |
449 | 2 files changed, 120 insertions(+), 201 deletions(-) | |
450 | delete mode 100644 include/tool/delegate.h | |
451 | ||
452 | diff --git a/include/tool/coroutine.h b/include/tool/coroutine.h | |
453 | index 8e472ca..70ef6cb 100644 | |
454 | --- a/include/tool/coroutine.h | |
455 | +++ b/include/tool/coroutine.h | |
456 | @@ -31,7 +31,7 @@ | |
457 | #include <boost/version.hpp> | |
458 | #include <type_traits> | |
459 | ||
460 | -#if BOOST_VERSION <= 106000 | |
461 | +#if BOOST_VERSION < 106100 | |
462 | #include <boost/context/fcontext.hpp> | |
463 | #else | |
464 | #include <boost/context/execution_context.hpp> | |
465 | @@ -39,6 +39,44 @@ | |
466 | #endif | |
467 | ||
468 | /** | |
469 | + * Note: in the history of boost, two changes to the context interface happened. | |
470 | + * [1.54, 1.56) | |
471 | + * http://www.boost.org/doc/libs/1_55_0/libs/context/doc/html/context/context/boost_fcontext.html | |
472 | + * intptr_t jump_fcontext( | |
473 | + * fcontext_t* ofc, | |
474 | + * fcontext_t const* nfc, | |
475 | + * intptr_t vp, | |
476 | + * bool preserve_fpu = true | |
477 | + * ); | |
478 | + * | |
479 | + * fcontext_t* make_fcontext( | |
480 | + * void* sp, | |
481 | + * std::size_t size, | |
482 | + * void (*fn)(intptr_t) | |
483 | + * ); | |
484 | + * | |
485 | + * [1.56, 1.61) | |
486 | + * http://www.boost.org/doc/libs/1_56_0/libs/context/doc/html/context/context/boost_fcontext.html | |
487 | + * intptr_t jump_fcontext( | |
488 | + * fcontext_t* ofc, | |
489 | + * fcontext_t nfc, <----- | |
490 | + * intptr_t vp, | |
491 | + * bool preserve_fpu = true | |
492 | + * ); | |
493 | + * | |
494 | + * fcontext_t make_fcontext( <----- | |
495 | + * void* sp, | |
496 | + * std::size_t size, | |
497 | + * void(*fn)(intptr_t) | |
498 | + * ); | |
499 | + * | |
500 | + * [1.61, oo) | |
501 | + * http://www.boost.org/doc/libs/1_61_0/libs/context/doc/html/context/ecv2.html | |
502 | + * fcontext_t is hidden away behind the boost::execution_context(_v2) and the stack is created on behalf of | |
503 | + * the user. | |
504 | + */ | |
505 | + | |
506 | +/** | |
507 | * Class COROUNTINE. | |
508 | * Implements a coroutine. Wikipedia has a good explanation: | |
509 | * | |
510 | @@ -73,7 +111,7 @@ public: | |
511 | * Creates a coroutine from a member method of an object | |
512 | */ | |
513 | template <class T> | |
514 | - COROUTINE( T* object, ReturnType(T::* ptr)( ArgType ) ) : | |
515 | + COROUTINE( T* object, ReturnType(T::*ptr)( ArgType ) ) : | |
516 | COROUTINE( std::bind( ptr, object, std::placeholders::_1 ) ) | |
517 | { | |
518 | } | |
519 | @@ -85,34 +123,20 @@ public: | |
520 | COROUTINE( std::function<ReturnType(ArgType)> aEntry ) : | |
521 | m_func( std::move( aEntry ) ), | |
522 | m_running( false ), | |
523 | -#if BOOST_VERSION <= 106000 | |
524 | - m_stack( nullptr ), | |
525 | - m_stackSize( c_defaultStackSize ), | |
526 | + m_args( 0 ), | |
527 | +#if BOOST_VERSION < 106100 // -> m_callee = void* or void** | |
528 | + m_callee( nullptr ), | |
529 | #endif | |
530 | - m_caller( nullptr ), | |
531 | - m_callee( nullptr ) | |
532 | + m_retVal( 0 ) | |
533 | { | |
534 | - // Avoid not initialized members, and make static analysers quiet | |
535 | - m_args = 0; | |
536 | - m_retVal = 0; | |
537 | } | |
538 | ||
539 | ~COROUTINE() | |
540 | { | |
541 | -#if BOOST_VERSION >= 105600 | |
542 | - delete m_callee; | |
543 | -#endif | |
544 | - | |
545 | -#if BOOST_VERSION <= 106000 | |
546 | - delete m_caller; | |
547 | - | |
548 | - if( m_stack ) | |
549 | - free( m_stack ); | |
550 | -#endif | |
551 | } | |
552 | ||
553 | private: | |
554 | -#if BOOST_VERSION <= 106000 | |
555 | +#if BOOST_VERSION < 106100 | |
556 | using context_type = boost::context::fcontext_t; | |
557 | #else | |
558 | using context_type = boost::context::execution_context<COROUTINE*>; | |
559 | @@ -128,12 +152,7 @@ public: | |
560 | */ | |
561 | void Yield() | |
562 | { | |
563 | -#if BOOST_VERSION <= 106000 | |
564 | - jump( m_callee, m_caller, false ); | |
565 | -#else | |
566 | - auto result = (*m_caller)( this ); | |
567 | - *m_caller = std::move( std::get<0>( result ) ); | |
568 | -#endif | |
569 | + jumpOut(); | |
570 | } | |
571 | ||
572 | /** | |
573 | @@ -145,11 +164,20 @@ public: | |
574 | void Yield( ReturnType& aRetVal ) | |
575 | { | |
576 | m_retVal = aRetVal; | |
577 | -#if BOOST_VERSION <= 106000 | |
578 | - jump( m_callee, m_caller, false ); | |
579 | -#else | |
580 | - m_caller( this ); | |
581 | -#endif | |
582 | + jumpOut(); | |
583 | + } | |
584 | + | |
585 | + /** | |
586 | + * Function Resume() | |
587 | + * | |
588 | + * Resumes execution of a previously yielded coroutine. | |
589 | + * @return true, if the coroutine has yielded again and false if it has finished its | |
590 | + * execution (returned). | |
591 | + */ | |
592 | + bool Resume() | |
593 | + { | |
594 | + jumpIn(); | |
595 | + return m_running; | |
596 | } | |
597 | ||
598 | /** | |
599 | @@ -170,62 +198,37 @@ public: | |
600 | */ | |
601 | bool Call( ArgType aArgs ) | |
602 | { | |
603 | - assert( m_callee == NULL ); | |
604 | - assert( m_caller == NULL ); | |
605 | + assert( m_func ); | |
606 | + assert( !m_callee ); | |
607 | + | |
608 | + m_args = &aArgs; | |
609 | + | |
610 | +#if BOOST_VERSION < 106100 | |
611 | + assert( m_stack == nullptr ); | |
612 | ||
613 | -#if BOOST_VERSION <= 106000 | |
614 | // fixme: Clean up stack stuff. Add a guard | |
615 | - m_stack = malloc( c_defaultStackSize ); | |
616 | + size_t stackSize = c_defaultStackSize; | |
617 | + m_stack.reset( new char[stackSize] ); | |
618 | ||
619 | // align to 16 bytes | |
620 | - void* sp = (void*) ( ( ( (ptrdiff_t) m_stack ) + m_stackSize - 0xf ) & ( ~0x0f ) ); | |
621 | + void* sp = (void*) ( ( ( (ptrdiff_t) m_stack.get() ) + stackSize - 0xf ) & ( ~0x0f ) ); | |
622 | ||
623 | // correct the stack size | |
624 | - m_stackSize -= ( (size_t) m_stack + m_stackSize - (size_t) sp ); | |
625 | -#endif | |
626 | - | |
627 | - m_args = &aArgs; | |
628 | + stackSize -= size_t( ( (ptrdiff_t) m_stack.get() + stackSize) - (ptrdiff_t) sp ); | |
629 | ||
630 | -#if BOOST_VERSION < 105600 | |
631 | - m_callee = boost::context::make_fcontext( sp, m_stackSize, callerStub ); | |
632 | -#elif BOOST_VERSION <= 106000 | |
633 | - m_callee = new context_type( boost::context::make_fcontext( sp, m_stackSize, callerStub ) ); | |
634 | + m_callee = boost::context::make_fcontext( sp, stackSize, callerStub ); | |
635 | #else | |
636 | - m_callee = new context_type( std::allocator_arg_t(), | |
637 | - boost::context::protected_fixedsize_stack( c_defaultStackSize ), &COROUTINE::callerStub ); | |
638 | -#endif | |
639 | - | |
640 | -#if BOOST_VERSION <= 106000 | |
641 | - m_caller = new context_type(); | |
642 | + m_callee = context_type( | |
643 | + std::allocator_arg_t(), | |
644 | + boost::context::protected_fixedsize_stack( c_defaultStackSize ), | |
645 | + &COROUTINE::callerStub | |
646 | + ); | |
647 | #endif | |
648 | ||
649 | m_running = true; | |
650 | ||
651 | // off we go! | |
652 | -#if BOOST_VERSION <= 106000 | |
653 | - jump( m_caller, m_callee, reinterpret_cast<intptr_t>( this ) ); | |
654 | -#else | |
655 | - auto result = (*m_callee)( this ); | |
656 | - *m_callee = std::move( std::get<0>( result ) ); | |
657 | -#endif | |
658 | - return m_running; | |
659 | - } | |
660 | - | |
661 | - /** | |
662 | - * Function Resume() | |
663 | - * | |
664 | - * Resumes execution of a previously yielded coroutine. | |
665 | - * @return true, if the coroutine has yielded again and false if it has finished its | |
666 | - * execution (returned). | |
667 | - */ | |
668 | - bool Resume() | |
669 | - { | |
670 | -#if BOOST_VERSION <= 106000 | |
671 | - jump( m_caller, m_callee, false ); | |
672 | -#else | |
673 | - auto result = (*m_callee)( this ); | |
674 | - *m_callee = std::move( std::get<0>( result ) ); | |
675 | -#endif | |
676 | + jumpIn(); | |
677 | ||
678 | return m_running; | |
679 | } | |
680 | @@ -254,66 +257,82 @@ private: | |
681 | static const int c_defaultStackSize = 2000000; // fixme: make configurable | |
682 | ||
683 | /* real entry point of the coroutine */ | |
684 | -#if BOOST_VERSION <= 106000 | |
685 | +#if BOOST_VERSION < 106100 | |
686 | static void callerStub( intptr_t aData ) | |
687 | -#else | |
688 | - static context_type callerStub( context_type caller, COROUTINE* cor ) | |
689 | -#endif | |
690 | { | |
691 | // get pointer to self | |
692 | -#if BOOST_VERSION <= 106000 | |
693 | - COROUTINE<ReturnType, ArgType>* cor = reinterpret_cast<COROUTINE<ReturnType, ArgType>*>( aData ); | |
694 | + COROUTINE* cor = reinterpret_cast<COROUTINE*>( aData ); | |
695 | + | |
696 | + // call the coroutine method | |
697 | + cor->m_retVal = cor->m_func( *(cor->m_args) ); | |
698 | + cor->m_running = false; | |
699 | + | |
700 | + // go back to wherever we came from. | |
701 | + cor->jumpOut(); | |
702 | + } | |
703 | #else | |
704 | - cor->m_caller = &caller; | |
705 | -#endif | |
706 | + /* real entry point of the coroutine */ | |
707 | + static context_type callerStub( context_type caller, COROUTINE* cor ) | |
708 | + { | |
709 | + cor->m_caller = std::move( caller ); | |
710 | ||
711 | // call the coroutine method | |
712 | - cor->m_retVal = cor->m_func( *( cor->m_args ) ); | |
713 | + cor->m_retVal = cor->m_func( *(cor->m_args) ); | |
714 | cor->m_running = false; | |
715 | ||
716 | // go back to wherever we came from. | |
717 | -#if BOOST_VERSION <= 106000 | |
718 | - jump( cor->m_callee, cor->m_caller, 0 ); | |
719 | + return std::move( cor->m_caller ); | |
720 | + } | |
721 | +#endif | |
722 | + | |
723 | + void jumpIn() | |
724 | + { | |
725 | +#if BOOST_VERSION < 105600 | |
726 | + boost::context::jump_fcontext( &m_caller, m_callee, reinterpret_cast<intptr_t>(this) ); | |
727 | +#elif BOOST_VERSION < 106100 | |
728 | + boost::context::jump_fcontext( &m_caller, m_callee, reinterpret_cast<intptr_t>(this) ); | |
729 | #else | |
730 | - return caller; | |
731 | + auto result = m_callee( this ); | |
732 | + m_callee = std::move( std::get<0>( result ) ); | |
733 | #endif | |
734 | } | |
735 | ||
736 | - ///> Wrapper for jump_fcontext to assure compatibility between different boost versions | |
737 | -#if BOOST_VERSION <= 106000 | |
738 | - static inline intptr_t jump( context_type* aOld, context_type* aNew, | |
739 | - intptr_t aP, bool aPreserveFPU = true ) | |
740 | + void jumpOut() | |
741 | { | |
742 | #if BOOST_VERSION < 105600 | |
743 | - return boost::context::jump_fcontext( aOld, aNew, aP, aPreserveFPU ); | |
744 | + boost::context::jump_fcontext( m_callee, &m_caller, 0 ); | |
745 | +#elif BOOST_VERSION < 106100 | |
746 | + boost::context::jump_fcontext( &m_callee, m_caller, 0 ); | |
747 | #else | |
748 | - return boost::context::jump_fcontext( aOld, *aNew, aP, aPreserveFPU ); | |
749 | + auto result = m_caller( nullptr ); | |
750 | + m_caller = std::move( std::get<0>( result ) ); | |
751 | #endif | |
752 | } | |
753 | -#endif | |
754 | ||
755 | std::function<ReturnType(ArgType)> m_func; | |
756 | ||
757 | bool m_running; | |
758 | ||
759 | -#if BOOST_VERSION <= 106000 | |
760 | +#if BOOST_VERSION < 106100 | |
761 | ///< coroutine stack | |
762 | - void* m_stack; | |
763 | - | |
764 | - size_t m_stackSize; | |
765 | + std::unique_ptr<char[]> m_stack; | |
766 | #endif | |
767 | ||
768 | ///< pointer to coroutine entry arguments. Stripped of references | |
769 | ///< to avoid compiler errors. | |
770 | typename std::remove_reference<ArgType>::type* m_args; | |
771 | ||
772 | - ReturnType m_retVal; | |
773 | - | |
774 | ///< saved caller context | |
775 | - context_type* m_caller; | |
776 | + context_type m_caller; | |
777 | ||
778 | ///< saved coroutine context | |
779 | +#if BOOST_VERSION < 105600 | |
780 | context_type* m_callee; | |
781 | +#else | |
782 | + context_type m_callee; | |
783 | +#endif | |
784 | + | |
785 | + ReturnType m_retVal; | |
786 | }; | |
787 | ||
788 | #endif | |
789 | diff --git a/include/tool/delegate.h b/include/tool/delegate.h | |
790 | deleted file mode 100644 | |
791 | index a350dec..0000000 | |
792 | --- a/include/tool/delegate.h | |
793 | +++ /dev/null | |
794 | @@ -1,100 +0,0 @@ | |
795 | -/* | |
796 | - * This program source code file is part of KiCad, a free EDA CAD application. | |
797 | - * | |
798 | - * Copyright (C) 2013 CERN | |
799 | - * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> | |
800 | - * | |
801 | - * This program is free software; you can redistribute it and/or | |
802 | - * modify it under the terms of the GNU General Public License | |
803 | - * as published by the Free Software Foundation; either version 2 | |
804 | - * of the License, or (at your option) any later version. | |
805 | - * | |
806 | - * This program is distributed in the hope that it will be useful, | |
807 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
808 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
809 | - * GNU General Public License for more details. | |
810 | - * | |
811 | - * You should have received a copy of the GNU General Public License | |
812 | - * along with this program; if not, you may find one here: | |
813 | - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html | |
814 | - * or you may search the http://www.gnu.org website for the version 2 license, | |
815 | - * or you may write to the Free Software Foundation, Inc., | |
816 | - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA | |
817 | - */ | |
818 | - | |
819 | -#ifndef __DELEGATE_H | |
820 | -#define __DELEGATE_H | |
821 | - | |
822 | - | |
823 | -/** | |
824 | - * class DELEGATE | |
825 | - * A trivial delegate (pointer to member method of an object) pattern implementation. | |
826 | - * Check delegate_example.cpp for a coding sample. | |
827 | - */ | |
828 | - | |
829 | -template <class ReturnType, class Arg> | |
830 | -class DELEGATE | |
831 | -{ | |
832 | -public: | |
833 | - typedef ReturnType (DELEGATE<ReturnType, Arg>::* MemberPointer)( Arg ); | |
834 | - typedef ReturnType _ReturnType; | |
835 | - typedef Arg _ArgType; | |
836 | - | |
837 | - DELEGATE() | |
838 | - { | |
839 | - } | |
840 | - | |
841 | - template <class T> | |
842 | - DELEGATE( T* aObject, ReturnType(T::* aPtr)( Arg ) ) | |
843 | - { | |
844 | - m_ptr = reinterpret_cast<MemberPointer>( aPtr ); | |
845 | - m_object = reinterpret_cast<void*>( aObject ); | |
846 | - }; | |
847 | - | |
848 | - | |
849 | - ReturnType operator()( Arg aA ) const | |
850 | - { | |
851 | - DELEGATE<ReturnType, Arg>* casted = reinterpret_cast<DELEGATE<ReturnType, Arg>*>( m_object ); | |
852 | - return (casted->*m_ptr)( aA ); | |
853 | - } | |
854 | - | |
855 | -private: | |
856 | - MemberPointer m_ptr; | |
857 | - void* m_object; | |
858 | -}; | |
859 | - | |
860 | -/** | |
861 | - * Class DELEGATE0 | |
862 | - * Same as DELEGATE, but with no arguments. | |
863 | - */ | |
864 | -template <class ReturnType> | |
865 | -class DELEGATE0 | |
866 | -{ | |
867 | -public: | |
868 | - typedef ReturnType ( DELEGATE0<ReturnType>::* MemberPointer )(); | |
869 | - typedef ReturnType _ReturnType; | |
870 | - | |
871 | - DELEGATE0() | |
872 | - { | |
873 | - } | |
874 | - | |
875 | - template <class T> | |
876 | - DELEGATE0( T* aObject, ReturnType(T::* aPtr)() ) | |
877 | - { | |
878 | - m_ptr = reinterpret_cast<MemberPointer>( aPtr ); | |
879 | - m_object = reinterpret_cast<void*>( aObject ); | |
880 | - }; | |
881 | - | |
882 | - | |
883 | - ReturnType operator()() const | |
884 | - { | |
885 | - DELEGATE0<ReturnType>* casted = reinterpret_cast<DELEGATE0<ReturnType>*>( m_object ); | |
886 | - return ( casted->*m_ptr )(); | |
887 | - } | |
888 | - | |
889 | -private: | |
890 | - MemberPointer m_ptr; | |
891 | - void* m_object; | |
892 | -}; | |
893 | - | |
894 | -#endif | |
895 | -- | |
896 | 2.9.3 | |
897 |