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
7 (cherry picked from commit 06d4894fdbeb00727cdcc667b8899ad73d8eb1c2)
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(-)
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 )
23 - BOOST_FOREACH( TOOL_STATE* st, m_toolState | boost::adaptors::map_values )
24 + for( TOOL_STATE* st : ( m_toolState | boost::adaptors::map_values ) )
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 )
32 + st->cofunc = new COROUTINE<int, const TOOL_EVENT&>( tr.second );
34 // as the state changes, the transition table has to be set up again
35 st->transitions.clear();
37 - st->cofunc = new COROUTINE<int, const TOOL_EVENT&>( tr.second );
39 // got match? Run the handler.
40 st->cofunc->Call( aEvent );
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
48 * Copyright (C) 2013 CERN
49 * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
50 + * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
52 * This program is free software; you can redistribute it and/or
53 * modify it under the terms of the GNU General Public License
58 -#include <boost/context/fcontext.hpp>
59 #include <boost/version.hpp>
60 +#include <type_traits>
62 -#include "delegate.h"
63 +#if BOOST_VERSION <= 106000
64 +#include <boost/context/fcontext.hpp>
66 +#include <boost/context/execution_context.hpp>
72 * See coroutine_example.cpp for sample code.
75 -template <class ReturnType, class ArgType>
76 +template <typename ReturnType, typename ArgType>
81 - m_saved( NULL ), m_self( NULL ), m_stack( NULL ), m_stackSize( c_defaultStackSize ),
83 + COROUTINE( nullptr )
87 @@ -69,8 +73,7 @@ public:
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 ) )
97 @@ -78,9 +81,15 @@ public:
99 * Creates a coroutine from a delegate object
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 ),
111 + m_caller( nullptr ),
112 + m_callee( nullptr )
114 // Avoid not initialized members, and make static analysers quiet
116 @@ -89,18 +98,26 @@ public:
123 #if BOOST_VERSION >= 105600
129 +#if BOOST_VERSION <= 106000
138 +#if BOOST_VERSION <= 106000
139 + using context_type = boost::context::fcontext_t;
141 + using context_type = boost::context::execution_context<COROUTINE*>;
148 @@ -110,7 +127,12 @@ public:
152 - jump( m_self, m_saved, 0 );
153 +#if BOOST_VERSION <= 106000
154 + jump( m_callee, m_caller, false );
156 + auto result = (*m_caller)( this );
157 + *m_caller = std::move( std::get<0>( result ) );
162 @@ -122,7 +144,11 @@ public:
163 void Yield( ReturnType& aRetVal )
166 - jump( m_self, m_saved, 0 );
167 +#if BOOST_VERSION <= 106000
168 + jump( m_callee, m_caller, false );
175 @@ -130,9 +156,9 @@ public:
177 * Defines the entry point for the coroutine, if not set in the constructor.
179 - void SetEntry( DELEGATE<ReturnType, ArgType> aEntry )
180 + void SetEntry( std::function<ReturnType(ArgType)> aEntry )
183 + m_func = std::move( aEntry );
187 @@ -143,6 +169,10 @@ public:
189 bool Call( ArgType aArgs )
191 + assert( m_callee == NULL );
192 + assert( m_caller == NULL );
194 +#if BOOST_VERSION <= 106000
195 // fixme: Clean up stack stuff. Add a guard
196 m_stack = malloc( c_defaultStackSize );
198 @@ -151,22 +181,32 @@ public:
200 // correct the stack size
201 m_stackSize -= ( (size_t) m_stack + m_stackSize - (size_t) sp );
203 - assert( m_self == NULL );
204 - assert( m_saved == NULL );
208 -#if BOOST_VERSION >= 105600
209 - m_self = new boost::context::fcontext_t();
210 - *m_self = boost::context::make_fcontext( sp, m_stackSize, callerStub );
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 ) );
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 );
222 +#if BOOST_VERSION <= 106000
223 + m_caller = new context_type();
225 - m_saved = new boost::context::fcontext_t();
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 ) );
234 + auto result = (*m_callee)( this );
235 + *m_callee = std::move( std::get<0>( result ) );
240 @@ -179,7 +219,12 @@ public:
244 - jump( m_saved, m_self, 0 );
245 +#if BOOST_VERSION <= 106000
246 + jump( m_caller, m_callee, false );
248 + auto result = (*m_callee)( this );
249 + *m_callee = std::move( std::get<0>( result ) );
254 @@ -208,61 +253,66 @@ private:
255 static const int c_defaultStackSize = 2000000; // fixme: make configurable
257 /* real entry point of the coroutine */
258 +#if BOOST_VERSION <= 106000
259 static void callerStub( intptr_t aData )
261 + static context_type callerStub( context_type caller, COROUTINE* cor )
264 // get pointer to self
265 +#if BOOST_VERSION <= 106000
266 COROUTINE<ReturnType, ArgType>* cor = reinterpret_cast<COROUTINE<ReturnType, ArgType>*>( aData );
268 + cor->m_caller = &caller;
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;
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 );
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 )
291 -#if BOOST_VERSION >= 105600
292 - return boost::context::jump_fcontext( aOld, *aNew, aP, aPreserveFPU );
294 +#if BOOST_VERSION < 105600
295 return boost::context::jump_fcontext( aOld, aNew, aP, aPreserveFPU );
297 + return boost::context::jump_fcontext( aOld, *aNew, aP, aPreserveFPU );
302 - template <typename T>
307 + std::function<ReturnType(ArgType)> m_func;
309 - template <typename T>
310 - struct strip_ref<T&>
316 - DELEGATE<ReturnType, ArgType> m_func;
317 +#if BOOST_VERSION <= 106000
318 + ///< coroutine stack
321 + size_t m_stackSize;
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;
331 ///< saved caller context
332 - boost::context::fcontext_t* m_saved;
333 + context_type* m_caller;
335 ///< saved coroutine context
336 - boost::context::fcontext_t* m_self;
338 - ///< coroutine stack
341 - size_t m_stackSize;
344 + context_type* m_callee;
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
354 * Copyright (C) 2013 CERN
355 * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
356 + * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
358 * This program is free software; you can redistribute it and/or
359 * modify it under the terms of the GNU General Public License
361 #include <tool/tool_event.h>
362 #include <tool/tool_settings.h>
364 -#include <tool/delegate.h>
365 +#include <functional>
369 @@ -53,7 +54,9 @@ enum TOOL_TYPE
371 /// Unique identifier for tools
373 -typedef DELEGATE<int, const TOOL_EVENT&> TOOL_STATE_FUNC;
375 +using TOOL_STATE_FUNC = std::function<int(const TOOL_EVENT&)>;
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
386 * Copyright (C) 2013 CERN
387 * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
388 + * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
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 )
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 );
399 goInternal( sptr, aConditions );
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
409 (cherry picked from commit 78bc3c65de6c03d19be9902327d08cd4d87c229c)
411 include/tool/coroutine.h | 3 ++-
412 1 file changed, 2 insertions(+), 1 deletion(-)
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
419 #include <boost/context/fcontext.hpp>
421 #include <boost/context/execution_context.hpp>
422 +#include <boost/context/protected_fixedsize_stack.hpp>
426 @@ -191,7 +192,7 @@ public:
427 m_callee = new context_type( boost::context::make_fcontext( sp, m_stackSize, callerStub ) );
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 );
434 #if BOOST_VERSION <= 106000
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
445 (cherry picked from commit 18b7dbf4d166fcb7da10ced72268a77f02448188)
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
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
457 #include <boost/version.hpp>
458 #include <type_traits>
460 -#if BOOST_VERSION <= 106000
461 +#if BOOST_VERSION < 106100
462 #include <boost/context/fcontext.hpp>
464 #include <boost/context/execution_context.hpp>
469 + * Note: in the history of boost, two changes to the context interface happened.
471 + * http://www.boost.org/doc/libs/1_55_0/libs/context/doc/html/context/context/boost_fcontext.html
472 + * intptr_t jump_fcontext(
474 + * fcontext_t const* nfc,
476 + * bool preserve_fpu = true
479 + * fcontext_t* make_fcontext(
481 + * std::size_t size,
482 + * void (*fn)(intptr_t)
486 + * http://www.boost.org/doc/libs/1_56_0/libs/context/doc/html/context/context/boost_fcontext.html
487 + * intptr_t jump_fcontext(
489 + * fcontext_t nfc, <-----
491 + * bool preserve_fpu = true
494 + * fcontext_t make_fcontext( <-----
496 + * std::size_t size,
497 + * void(*fn)(intptr_t)
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
508 * Implements a coroutine. Wikipedia has a good explanation:
510 @@ -73,7 +111,7 @@ public:
511 * Creates a coroutine from a member method of an object
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 ) )
519 @@ -85,34 +123,20 @@ public:
520 COROUTINE( std::function<ReturnType(ArgType)> aEntry ) :
521 m_func( std::move( aEntry ) ),
523 -#if BOOST_VERSION <= 106000
524 - m_stack( nullptr ),
525 - m_stackSize( c_defaultStackSize ),
527 +#if BOOST_VERSION < 106100 // -> m_callee = void* or void**
528 + m_callee( nullptr ),
530 - m_caller( nullptr ),
531 - m_callee( nullptr )
534 - // Avoid not initialized members, and make static analysers quiet
541 -#if BOOST_VERSION >= 105600
545 -#if BOOST_VERSION <= 106000
554 -#if BOOST_VERSION <= 106000
555 +#if BOOST_VERSION < 106100
556 using context_type = boost::context::fcontext_t;
558 using context_type = boost::context::execution_context<COROUTINE*>;
559 @@ -128,12 +152,7 @@ public:
563 -#if BOOST_VERSION <= 106000
564 - jump( m_callee, m_caller, false );
566 - auto result = (*m_caller)( this );
567 - *m_caller = std::move( std::get<0>( result ) );
573 @@ -145,11 +164,20 @@ public:
574 void Yield( ReturnType& aRetVal )
577 -#if BOOST_VERSION <= 106000
578 - jump( m_callee, m_caller, false );
586 + * Function Resume()
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).
599 @@ -170,62 +198,37 @@ public:
601 bool Call( ArgType aArgs )
603 - assert( m_callee == NULL );
604 - assert( m_caller == NULL );
606 + assert( !m_callee );
610 +#if BOOST_VERSION < 106100
611 + assert( m_stack == nullptr );
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] );
620 - void* sp = (void*) ( ( ( (ptrdiff_t) m_stack ) + m_stackSize - 0xf ) & ( ~0x0f ) );
621 + void* sp = (void*) ( ( ( (ptrdiff_t) m_stack.get() ) + stackSize - 0xf ) & ( ~0x0f ) );
623 // correct the stack size
624 - m_stackSize -= ( (size_t) m_stack + m_stackSize - (size_t) sp );
628 + stackSize -= size_t( ( (ptrdiff_t) m_stack.get() + stackSize) - (ptrdiff_t) sp );
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 );
636 - m_callee = new context_type( std::allocator_arg_t(),
637 - boost::context::protected_fixedsize_stack( c_defaultStackSize ), &COROUTINE::callerStub );
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
652 -#if BOOST_VERSION <= 106000
653 - jump( m_caller, m_callee, reinterpret_cast<intptr_t>( this ) );
655 - auto result = (*m_callee)( this );
656 - *m_callee = std::move( std::get<0>( result ) );
662 - * Function Resume()
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).
670 -#if BOOST_VERSION <= 106000
671 - jump( m_caller, m_callee, false );
673 - auto result = (*m_callee)( this );
674 - *m_callee = std::move( std::get<0>( result ) );
680 @@ -254,66 +257,82 @@ private:
681 static const int c_defaultStackSize = 2000000; // fixme: make configurable
683 /* real entry point of the coroutine */
684 -#if BOOST_VERSION <= 106000
685 +#if BOOST_VERSION < 106100
686 static void callerStub( intptr_t aData )
688 - static context_type callerStub( context_type caller, COROUTINE* cor )
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 );
696 + // call the coroutine method
697 + cor->m_retVal = cor->m_func( *(cor->m_args) );
698 + cor->m_running = false;
700 + // go back to wherever we came from.
704 - cor->m_caller = &caller;
706 + /* real entry point of the coroutine */
707 + static context_type callerStub( context_type caller, COROUTINE* cor )
709 + cor->m_caller = std::move( caller );
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;
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 );
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) );
731 + auto result = m_callee( this );
732 + m_callee = std::move( std::get<0>( result ) );
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 )
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 );
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 ) );
755 std::function<ReturnType(ArgType)> m_func;
759 -#if BOOST_VERSION <= 106000
760 +#if BOOST_VERSION < 106100
764 - size_t m_stackSize;
765 + std::unique_ptr<char[]> m_stack;
768 ///< pointer to coroutine entry arguments. Stripped of references
769 ///< to avoid compiler errors.
770 typename std::remove_reference<ArgType>::type* m_args;
772 - ReturnType m_retVal;
774 ///< saved caller context
775 - context_type* m_caller;
776 + context_type m_caller;
778 ///< saved coroutine context
779 +#if BOOST_VERSION < 105600
780 context_type* m_callee;
782 + context_type m_callee;
785 + ReturnType m_retVal;
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
796 - * This program source code file is part of KiCad, a free EDA CAD application.
798 - * Copyright (C) 2013 CERN
799 - * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
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.
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.
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
819 -#ifndef __DELEGATE_H
820 -#define __DELEGATE_H
825 - * A trivial delegate (pointer to member method of an object) pattern implementation.
826 - * Check delegate_example.cpp for a coding sample.
829 -template <class ReturnType, class Arg>
833 - typedef ReturnType (DELEGATE<ReturnType, Arg>::* MemberPointer)( Arg );
834 - typedef ReturnType _ReturnType;
835 - typedef Arg _ArgType;
842 - DELEGATE( T* aObject, ReturnType(T::* aPtr)( Arg ) )
844 - m_ptr = reinterpret_cast<MemberPointer>( aPtr );
845 - m_object = reinterpret_cast<void*>( aObject );
849 - ReturnType operator()( Arg aA ) const
851 - DELEGATE<ReturnType, Arg>* casted = reinterpret_cast<DELEGATE<ReturnType, Arg>*>( m_object );
852 - return (casted->*m_ptr)( aA );
856 - MemberPointer m_ptr;
862 - * Same as DELEGATE, but with no arguments.
864 -template <class ReturnType>
868 - typedef ReturnType ( DELEGATE0<ReturnType>::* MemberPointer )();
869 - typedef ReturnType _ReturnType;
876 - DELEGATE0( T* aObject, ReturnType(T::* aPtr)() )
878 - m_ptr = reinterpret_cast<MemberPointer>( aPtr );
879 - m_object = reinterpret_cast<void*>( aObject );
883 - ReturnType operator()() const
885 - DELEGATE0<ReturnType>* casted = reinterpret_cast<DELEGATE0<ReturnType>*>( m_object );
886 - return ( casted->*m_ptr )();
890 - MemberPointer m_ptr;