Created
March 11, 2017 15:53
-
-
Save metacollin/747033264bca4ca2f2d38ec2c948ee5c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- a/common/tool/tool_manager.cpp | |
+++ b/common/tool/tool_manager.cpp | |
@@ -532,11 +532,11 @@ | |
if( st->cofunc ) | |
st->Push(); | |
+ st->cofunc = new COROUTINE<int, const TOOL_EVENT&>( tr.second ); | |
+ | |
// as the state changes, the transition table has to be set up again | |
st->transitions.clear(); | |
- st->cofunc = new COROUTINE<int, const TOOL_EVENT&>( tr.second ); | |
- | |
// got match? Run the handler. | |
st->cofunc->Call( aEvent ); | |
--- a/include/tool/coroutine.h | |
+++ b/include/tool/coroutine.h | |
@@ -27,10 +28,15 @@ | |
#include <cstdlib> | |
-#include <boost/context/fcontext.hpp> | |
#include <boost/version.hpp> | |
+#include <type_traits> | |
-#include "delegate.h" | |
+#if BOOST_VERSION <= 106000 | |
+#include <boost/context/fcontext.hpp> | |
+#else | |
+#include <boost/context/execution_context.hpp> | |
+#include <boost/context/protected_fixedsize_stack.hpp> | |
+#endif | |
/** | |
* Class COROUNTINE. | |
@@ -53,13 +59,12 @@ | |
* See coroutine_example.cpp for sample code. | |
*/ | |
-template <class ReturnType, class ArgType> | |
+template <typename ReturnType, typename ArgType> | |
class COROUTINE | |
{ | |
public: | |
COROUTINE() : | |
- m_saved( NULL ), m_self( NULL ), m_stack( NULL ), m_stackSize( c_defaultStackSize ), | |
- m_running( false ) | |
+ COROUTINE( nullptr ) | |
{ | |
} | |
@@ -69,8 +74,7 @@ | |
*/ | |
template <class T> | |
COROUTINE( T* object, ReturnType(T::* ptr)( ArgType ) ) : | |
- m_func( object, ptr ), m_self( NULL ), m_saved( NULL ), m_stack( NULL ), | |
- m_stackSize( c_defaultStackSize ), m_running( false ) | |
+ COROUTINE( std::bind( ptr, object, std::placeholders::_1 ) ) | |
{ | |
} | |
@@ -78,9 +82,15 @@ | |
* Constructor | |
* Creates a coroutine from a delegate object | |
*/ | |
- COROUTINE( DELEGATE<ReturnType, ArgType> aEntry ) : | |
- m_func( aEntry ), m_saved( NULL ), m_self( NULL ), m_stack( NULL ), | |
- m_stackSize( c_defaultStackSize ), m_running( false ) | |
+ COROUTINE( std::function<ReturnType(ArgType)> aEntry ) : | |
+ m_func( std::move( aEntry ) ), | |
+ m_running( false ), | |
+#if BOOST_VERSION <= 106000 | |
+ m_stack( nullptr ), | |
+ m_stackSize( c_defaultStackSize ), | |
+#endif | |
+ m_caller( nullptr ), | |
+ m_callee( nullptr ) | |
{ | |
// Avoid not initialized members, and make static analysers quiet | |
m_args = 0; | |
@@ -89,18 +99,26 @@ | |
~COROUTINE() | |
{ | |
- if( m_saved ) | |
- delete m_saved; | |
- | |
#if BOOST_VERSION >= 105600 | |
- if( m_self ) | |
- delete m_self; | |
+ delete m_callee; | |
#endif | |
+#if BOOST_VERSION <= 106000 | |
+ delete m_caller; | |
+ | |
if( m_stack ) | |
free( m_stack ); | |
+#endif | |
} | |
+private: | |
+#if BOOST_VERSION <= 106000 | |
+ using context_type = boost::context::fcontext_t; | |
+#else | |
+ using context_type = boost::context::execution_context<COROUTINE*>; | |
+#endif | |
+ | |
+public: | |
/** | |
* Function Yield() | |
* | |
@@ -110,7 +128,12 @@ | |
*/ | |
void Yield() | |
{ | |
- jump( m_self, m_saved, 0 ); | |
+#if BOOST_VERSION <= 106000 | |
+ jump( m_callee, m_caller, false ); | |
+#else | |
+ auto result = (*m_caller)( this ); | |
+ *m_caller = std::move( std::get<0>( result ) ); | |
+#endif | |
} | |
/** | |
@@ -122,7 +145,11 @@ | |
void Yield( ReturnType& aRetVal ) | |
{ | |
m_retVal = aRetVal; | |
- jump( m_self, m_saved, 0 ); | |
+#if BOOST_VERSION <= 106000 | |
+ jump( m_callee, m_caller, false ); | |
+#else | |
+ m_caller( this ); | |
+#endif | |
} | |
/** | |
@@ -130,9 +157,9 @@ | |
* | |
* Defines the entry point for the coroutine, if not set in the constructor. | |
*/ | |
- void SetEntry( DELEGATE<ReturnType, ArgType> aEntry ) | |
+ void SetEntry( std::function<ReturnType(ArgType)> aEntry ) | |
{ | |
- m_func = aEntry; | |
+ m_func = std::move( aEntry ); | |
} | |
/* Function Call() | |
@@ -143,6 +170,10 @@ | |
*/ | |
bool Call( ArgType aArgs ) | |
{ | |
+ assert( m_callee == NULL ); | |
+ assert( m_caller == NULL ); | |
+ | |
+#if BOOST_VERSION <= 106000 | |
// fixme: Clean up stack stuff. Add a guard | |
m_stack = malloc( c_defaultStackSize ); | |
@@ -151,22 +182,32 @@ | |
// correct the stack size | |
m_stackSize -= ( (size_t) m_stack + m_stackSize - (size_t) sp ); | |
- | |
- assert( m_self == NULL ); | |
- assert( m_saved == NULL ); | |
+#endif | |
m_args = &aArgs; | |
-#if BOOST_VERSION >= 105600 | |
- m_self = new boost::context::fcontext_t(); | |
- *m_self = boost::context::make_fcontext( sp, m_stackSize, callerStub ); | |
+ | |
+#if BOOST_VERSION < 105600 | |
+ m_callee = boost::context::make_fcontext( sp, m_stackSize, callerStub ); | |
+#elif BOOST_VERSION <= 106000 | |
+ m_callee = new context_type( boost::context::make_fcontext( sp, m_stackSize, callerStub ) ); | |
#else | |
- m_self = boost::context::make_fcontext( sp, m_stackSize, callerStub ); | |
+ m_callee = new context_type( std::allocator_arg_t(), | |
+ boost::context::protected_fixedsize_stack( c_defaultStackSize ), &COROUTINE::callerStub ); | |
+#endif | |
+ | |
+#if BOOST_VERSION <= 106000 | |
+ m_caller = new context_type(); | |
#endif | |
- m_saved = new boost::context::fcontext_t(); | |
m_running = true; | |
+ | |
// off we go! | |
- jump( m_saved, m_self, reinterpret_cast<intptr_t>( this ) ); | |
+#if BOOST_VERSION <= 106000 | |
+ jump( m_caller, m_callee, reinterpret_cast<intptr_t>( this ) ); | |
+#else | |
+ auto result = (*m_callee)( this ); | |
+ *m_callee = std::move( std::get<0>( result ) ); | |
+#endif | |
return m_running; | |
} | |
@@ -179,7 +220,12 @@ | |
*/ | |
bool Resume() | |
{ | |
- jump( m_saved, m_self, 0 ); | |
+#if BOOST_VERSION <= 106000 | |
+ jump( m_caller, m_callee, false ); | |
+#else | |
+ auto result = (*m_callee)( this ); | |
+ *m_callee = std::move( std::get<0>( result ) ); | |
+#endif | |
return m_running; | |
} | |
@@ -208,61 +254,66 @@ | |
static const int c_defaultStackSize = 2000000; // fixme: make configurable | |
/* real entry point of the coroutine */ | |
+#if BOOST_VERSION <= 106000 | |
static void callerStub( intptr_t aData ) | |
+#else | |
+ static context_type callerStub( context_type caller, COROUTINE* cor ) | |
+#endif | |
{ | |
// get pointer to self | |
+#if BOOST_VERSION <= 106000 | |
COROUTINE<ReturnType, ArgType>* cor = reinterpret_cast<COROUTINE<ReturnType, ArgType>*>( aData ); | |
+#else | |
+ cor->m_caller = &caller; | |
+#endif | |
// call the coroutine method | |
- cor->m_retVal = cor->m_func( *cor->m_args ); | |
+ cor->m_retVal = cor->m_func( *( cor->m_args ) ); | |
cor->m_running = false; | |
// go back to wherever we came from. | |
- jump( cor->m_self, cor->m_saved, 0 ); // reinterpret_cast<intptr_t>( this )); | |
+#if BOOST_VERSION <= 106000 | |
+ jump( cor->m_callee, cor->m_caller, 0 ); | |
+#else | |
+ return caller; | |
+#endif | |
} | |
///> Wrapper for jump_fcontext to assure compatibility between different boost versions | |
- static inline intptr_t jump(boost::context::fcontext_t* aOld, boost::context::fcontext_t* aNew, | |
+#if BOOST_VERSION <= 106000 | |
+ static inline intptr_t jump( context_type* aOld, context_type* aNew, | |
intptr_t aP, bool aPreserveFPU = true ) | |
{ | |
-#if BOOST_VERSION >= 105600 | |
- return boost::context::jump_fcontext( aOld, *aNew, aP, aPreserveFPU ); | |
-#else | |
+#if BOOST_VERSION < 105600 | |
return boost::context::jump_fcontext( aOld, aNew, aP, aPreserveFPU ); | |
+#else | |
+ return boost::context::jump_fcontext( aOld, *aNew, aP, aPreserveFPU ); | |
#endif | |
} | |
+#endif | |
- template <typename T> | |
- struct strip_ref | |
- { | |
- typedef T result; | |
- }; | |
+ std::function<ReturnType(ArgType)> m_func; | |
- template <typename T> | |
- struct strip_ref<T&> | |
- { | |
- typedef T result; | |
- }; | |
+ bool m_running; | |
- DELEGATE<ReturnType, ArgType> m_func; | |
+#if BOOST_VERSION <= 106000 | |
+ ///< coroutine stack | |
+ void* m_stack; | |
+ | |
+ size_t m_stackSize; | |
+#endif | |
///< pointer to coroutine entry arguments. Stripped of references | |
///< to avoid compiler errors. | |
- typename strip_ref<ArgType>::result* m_args; | |
+ typename std::remove_reference<ArgType>::type* m_args; | |
+ | |
ReturnType m_retVal; | |
///< saved caller context | |
- boost::context::fcontext_t* m_saved; | |
+ context_type* m_caller; | |
///< saved coroutine context | |
- boost::context::fcontext_t* m_self; | |
- | |
- ///< coroutine stack | |
- void* m_stack; | |
- | |
- size_t m_stackSize; | |
- | |
- bool m_running; | |
+ context_type* m_callee; | |
}; | |
#endif | |
--- a/include/tool/tool_base.h | |
+++ b/include/tool/tool_base.h | |
@@ -31,7 +32,7 @@ | |
#include <tool/tool_event.h> | |
#include <tool/tool_settings.h> | |
-#include <tool/delegate.h> | |
+#include <functional> | |
class EDA_ITEM; | |
class TOOL_MANAGER; | |
@@ -53,7 +54,9 @@ | |
/// Unique identifier for tools | |
typedef int TOOL_ID; | |
-typedef DELEGATE<int, const TOOL_EVENT&> TOOL_STATE_FUNC; | |
+ | |
+using TOOL_STATE_FUNC = std::function<int(const TOOL_EVENT&)>; | |
+ | |
/** | |
* Class TOOL_BASE | |
--- a/include/tool/tool_interactive.h | |
+++ b/include/tool/tool_interactive.h | |
@@ -113,7 +114,7 @@ | |
void TOOL_INTERACTIVE::Go( int (T::* aStateFunc)( const TOOL_EVENT& ), | |
const TOOL_EVENT_LIST& aConditions ) | |
{ | |
- TOOL_STATE_FUNC sptr( static_cast<T*>( this ), aStateFunc ); | |
+ TOOL_STATE_FUNC sptr = std::bind( aStateFunc, static_cast<T*>( this ), std::placeholders::_1 ); | |
goInternal( sptr, aConditions ); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment