KiCad PCB EDA Suite
COROUTINE< ReturnType, ArgType > Class Template Reference

Class COROUNTINE. More...

#include <coroutine.h>

Classes

class  CALL_CONTEXT
 
struct  INVOCATION_ARGS
 

Public Member Functions

 COROUTINE ()
 
template<class T >
 COROUTINE (T *object, ReturnType(T::*ptr)(ArgType))
 Constructor Creates a coroutine from a member method of an object. More...
 
 COROUTINE (std::function< ReturnType(ArgType)> aEntry)
 Constructor Creates a coroutine from a delegate object. More...
 
 ~COROUTINE ()
 
void KiYield ()
 Function KiYield() More...
 
void KiYield (ReturnType &aRetVal)
 Function KiYield() More...
 
void SetEntry (std::function< ReturnType(ArgType)> aEntry)
 Function SetEntry() More...
 
void RunMainStack (std::function< void()> func)
 Function RunMainStack() More...
 
bool Call (ArgType aArg)
 Function Call() More...
 
bool Call (const COROUTINE &aCor, ArgType aArg)
 Function Call() More...
 
bool Resume ()
 Function Resume() More...
 
bool Resume (const COROUTINE &aCor)
 Function Resume() More...
 
const ReturnType & ReturnValue () const
 Function ReturnValue() More...
 
bool Running () const
 Function Running() More...
 

Private Types

using CONTEXT_T = libcontext::fcontext_t
 
using CALLEE_STORAGE = CONTEXT_T
 

Private Member Functions

INVOCATION_ARGSdoCall (INVOCATION_ARGS *aInvArgs, ArgType aArgs)
 
INVOCATION_ARGSdoResume (INVOCATION_ARGS *args)
 
INVOCATION_ARGSjumpIn (INVOCATION_ARGS *args)
 
void jumpOut ()
 

Static Private Member Functions

static void callerStub (intptr_t aData)
 

Private Attributes

std::unique_ptr< char[]> m_stack
 < coroutine stack More...
 
std::function< ReturnType(ArgType)> m_func
 
bool m_running
 pointer to coroutine entry arguments. More...
 
std::remove_reference< ArgType >::type * m_args
 saved caller context More...
 
CONTEXT_T m_caller
 main stack information More...
 
CALL_CONTEXTm_callContext
 saved coroutine context More...
 
CALLEE_STORAGE m_callee
 
ReturnType m_retVal
 

Static Private Attributes

static constexpr int c_defaultStackSize = 2000000
 

Detailed Description

template<typename ReturnType, typename ArgType>
class COROUTINE< ReturnType, ArgType >

Class COROUNTINE.

Implements a coroutine. Wikipedia has a good explanation:

"Coroutines are computer program components that generalize subroutines to allow multiple entry points for suspending and resuming execution at certain locations. Coroutines are well-suited for implementing more familiar program components such as cooperative tasks, exceptions, event loop, iterators, infinite lists and pipes."

In other words, a coroutine can be considered a lightweight thread - which can be preempted only when it deliberately yields the control to the caller. This way, we avoid concurrency problems such as locking / race conditions.

Uses libcontext library to do the actual context switching.

This particular version takes a DELEGATE as an entry point, so it can invoke methods within a given object as separate coroutines.

See coroutine_example.cpp for sample code.

Definition at line 58 of file coroutine.h.

Member Typedef Documentation

template<typename ReturnType, typename ArgType>
using COROUTINE< ReturnType, ArgType >::CALLEE_STORAGE = CONTEXT_T
private

Definition at line 80 of file coroutine.h.

template<typename ReturnType, typename ArgType>
using COROUTINE< ReturnType, ArgType >::CONTEXT_T = libcontext::fcontext_t
private

Definition at line 79 of file coroutine.h.

Constructor & Destructor Documentation

template<typename ReturnType, typename ArgType>
COROUTINE< ReturnType, ArgType >::COROUTINE ( )
inline

Definition at line 115 of file coroutine.h.

115  :
116  COROUTINE( nullptr )
117  {
118  }
template<typename ReturnType, typename ArgType>
template<class T >
COROUTINE< ReturnType, ArgType >::COROUTINE ( T *  object,
ReturnType(T::*)(ArgType)  ptr 
)
inline

Constructor Creates a coroutine from a member method of an object.

Definition at line 125 of file coroutine.h.

125  :
126  COROUTINE( std::bind( ptr, object, std::placeholders::_1 ) )
127  {
128  }
template<typename ReturnType, typename ArgType>
COROUTINE< ReturnType, ArgType >::COROUTINE ( std::function< ReturnType(ArgType)>  aEntry)
inline

Constructor Creates a coroutine from a delegate object.

Definition at line 134 of file coroutine.h.

134  :
135  m_func( std::move( aEntry ) ),
136  m_running( false ),
137  m_args( 0 ),
138  m_callee( nullptr ),
139  m_retVal( 0 )
140  {
141  }
std::function< ReturnType(ArgType)> m_func
Definition: coroutine.h:367
bool m_running
pointer to coroutine entry arguments.
Definition: coroutine.h:369
std::remove_reference< ArgType >::type * m_args
saved caller context
Definition: coroutine.h:373
CALLEE_STORAGE m_callee
Definition: coroutine.h:382
ReturnType m_retVal
Definition: coroutine.h:384
template<typename ReturnType, typename ArgType>
COROUTINE< ReturnType, ArgType >::~COROUTINE ( )
inline

Definition at line 143 of file coroutine.h.

144  {
145  }

Member Function Documentation

template<typename ReturnType, typename ArgType>
bool COROUTINE< ReturnType, ArgType >::Call ( ArgType  aArg)
inline

Function Call()

Starts execution of a coroutine, passing args as its arguments. Call this method from the application main stack only.

Returns
true, if the coroutine has yielded and false if it has finished its execution (returned).

Definition at line 204 of file coroutine.h.

Referenced by TOOL_MANAGER::dispatchInternal(), and MyClass::Run().

205  {
206  CALL_CONTEXT ctx;
207  INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROOT, this, &ctx };
208  ctx.Continue( doCall( &args, aArg ) );
209 
210  return Running();
211  }
INVOCATION_ARGS * doCall(INVOCATION_ARGS *aInvArgs, ArgType aArgs)
Definition: coroutine.h:285
bool Running() const
Function Running()
Definition: coroutine.h:279
template<typename ReturnType, typename ArgType>
bool COROUTINE< ReturnType, ArgType >::Call ( const COROUTINE< ReturnType, ArgType > &  aCor,
ArgType  aArg 
)
inline

Function Call()

Starts execution of a coroutine, passing args as its arguments. Call this method for a nested coroutine invocation.

Returns
true, if the coroutine has yielded and false if it has finished its execution (returned).

Definition at line 221 of file coroutine.h.

222  {
223  INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROUTINE, this, aCor.m_callContext };
224  doCall( &args, aArg );
225  // we will not be asked to continue
226 
227  return Running();
228  }
CALL_CONTEXT * m_callContext
saved coroutine context
Definition: coroutine.h:379
INVOCATION_ARGS * doCall(INVOCATION_ARGS *aInvArgs, ArgType aArgs)
Definition: coroutine.h:285
bool Running() const
Function Running()
Definition: coroutine.h:279
template<typename ReturnType, typename ArgType>
static void COROUTINE< ReturnType, ArgType >::callerStub ( intptr_t  aData)
inlinestaticprivate

Definition at line 317 of file coroutine.h.

Referenced by COROUTINE< int, int >::doCall().

318  {
319  INVOCATION_ARGS& args = *reinterpret_cast<INVOCATION_ARGS*>( aData );
320  // get pointer to self
321  COROUTINE* cor = args.destination;
322  cor->m_callContext = args.context;
323 
324  if( args.type == INVOCATION_ARGS::FROM_ROOT )
325  cor->m_callContext->SetMainStack( &cor->m_caller );
326 
327  // call the coroutine method
328  cor->m_retVal = cor->m_func( *(cor->m_args) );
329  cor->m_running = false;
330 
331  // go back to wherever we came from.
332  cor->jumpOut();
333  }
std::function< ReturnType(ArgType)> m_func
Definition: coroutine.h:367
bool m_running
pointer to coroutine entry arguments.
Definition: coroutine.h:369
Class COROUNTINE.
Definition: coroutine.h:58
void jumpOut()
Definition: coroutine.h:345
CALL_CONTEXT * m_callContext
saved coroutine context
Definition: coroutine.h:379
CONTEXT_T m_caller
main stack information
Definition: coroutine.h:376
std::remove_reference< ArgType >::type * m_args
saved caller context
Definition: coroutine.h:373
void SetMainStack(CONTEXT_T *aStack)
Definition: coroutine.h:85
ReturnType m_retVal
Definition: coroutine.h:384
template<typename ReturnType, typename ArgType>
INVOCATION_ARGS* COROUTINE< ReturnType, ArgType >::doCall ( INVOCATION_ARGS aInvArgs,
ArgType  aArgs 
)
inlineprivate

Definition at line 285 of file coroutine.h.

Referenced by COROUTINE< int, int >::Call().

286  {
287  assert( m_func );
288  assert( !m_callee );
289 
290  m_args = &aArgs;
291 
292  assert( m_stack == nullptr );
293 
294  // fixme: Clean up stack stuff. Add a guard
295  size_t stackSize = c_defaultStackSize;
296  m_stack.reset( new char[stackSize] );
297 
298  // align to 16 bytes
299  void* sp = (void*)((((ptrdiff_t) m_stack.get()) + stackSize - 0xf) & (~0x0f));
300 
301  // correct the stack size
302  stackSize -= size_t( ( (ptrdiff_t) m_stack.get() + stackSize ) - (ptrdiff_t) sp );
303 
304  m_callee = libcontext::make_fcontext( sp, stackSize, callerStub );
305  m_running = true;
306 
307  // off we go!
308  return jumpIn( aInvArgs );
309  }
std::function< ReturnType(ArgType)> m_func
Definition: coroutine.h:367
bool m_running
pointer to coroutine entry arguments.
Definition: coroutine.h:369
std::unique_ptr< char[]> m_stack
< coroutine stack
Definition: coroutine.h:365
static constexpr int c_defaultStackSize
Definition: coroutine.h:362
std::remove_reference< ArgType >::type * m_args
saved caller context
Definition: coroutine.h:373
CALLEE_STORAGE m_callee
Definition: coroutine.h:382
static void callerStub(intptr_t aData)
Definition: coroutine.h:317
fcontext_t LIBCONTEXT_CALL_CONVENTION make_fcontext(void *sp, size_t size, void(*fn)(intptr_t))
INVOCATION_ARGS * jumpIn(INVOCATION_ARGS *args)
Definition: coroutine.h:335
template<typename ReturnType, typename ArgType>
INVOCATION_ARGS* COROUTINE< ReturnType, ArgType >::doResume ( INVOCATION_ARGS args)
inlineprivate

Definition at line 311 of file coroutine.h.

Referenced by COROUTINE< ReturnType, ArgType >::CALL_CONTEXT::Continue(), and COROUTINE< int, int >::Resume().

312  {
313  return jumpIn( args );
314  }
INVOCATION_ARGS * jumpIn(INVOCATION_ARGS *args)
Definition: coroutine.h:335
template<typename ReturnType, typename ArgType>
INVOCATION_ARGS* COROUTINE< ReturnType, ArgType >::jumpIn ( INVOCATION_ARGS args)
inlineprivate

Definition at line 335 of file coroutine.h.

Referenced by COROUTINE< int, int >::doCall(), and COROUTINE< int, int >::doResume().

336  {
337  args = reinterpret_cast<INVOCATION_ARGS*>(
339  reinterpret_cast<intptr_t>( args ) )
340  );
341 
342  return args;
343  }
intptr_t LIBCONTEXT_CALL_CONVENTION jump_fcontext(fcontext_t *ofc, fcontext_t nfc, intptr_t vp, bool preserve_fpu=false)
CONTEXT_T m_caller
main stack information
Definition: coroutine.h:376
CALLEE_STORAGE m_callee
Definition: coroutine.h:382
template<typename ReturnType, typename ArgType>
void COROUTINE< ReturnType, ArgType >::jumpOut ( )
inlineprivate

Definition at line 345 of file coroutine.h.

Referenced by COROUTINE< int, int >::callerStub(), and COROUTINE< int, int >::KiYield().

346  {
347  INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROUTINE, nullptr, nullptr };
348  INVOCATION_ARGS* ret;
349  ret = reinterpret_cast<INVOCATION_ARGS*>(
351  reinterpret_cast<intptr_t>( &args ) )
352  );
353 
354  m_callContext = ret->context;
355 
356  if( ret->type == INVOCATION_ARGS::FROM_ROOT )
357  {
359  }
360  }
CALL_CONTEXT * m_callContext
saved coroutine context
Definition: coroutine.h:379
intptr_t LIBCONTEXT_CALL_CONVENTION jump_fcontext(fcontext_t *ofc, fcontext_t nfc, intptr_t vp, bool preserve_fpu=false)
CONTEXT_T m_caller
main stack information
Definition: coroutine.h:376
CALLEE_STORAGE m_callee
Definition: coroutine.h:382
void SetMainStack(CONTEXT_T *aStack)
Definition: coroutine.h:85
template<typename ReturnType, typename ArgType>
void COROUTINE< ReturnType, ArgType >::KiYield ( )
inline

Function KiYield()

Stops execution of the coroutine and returns control to the caller. After a yield, Call() or Resume() methods invoked by the caller will immediately return true, indicating that we are not done yet, just asleep.

Definition at line 155 of file coroutine.h.

Referenced by TOOL_MANAGER::ScheduleWait().

156  {
157  jumpOut();
158  }
void jumpOut()
Definition: coroutine.h:345
template<typename ReturnType, typename ArgType>
void COROUTINE< ReturnType, ArgType >::KiYield ( ReturnType &  aRetVal)
inline

Function KiYield()

KiYield with a value - passes a value of given type to the caller. Useful for implementing generator objects.

Definition at line 166 of file coroutine.h.

167  {
168  m_retVal = aRetVal;
169  jumpOut();
170  }
void jumpOut()
Definition: coroutine.h:345
ReturnType m_retVal
Definition: coroutine.h:384
template<typename ReturnType, typename ArgType>
bool COROUTINE< ReturnType, ArgType >::Resume ( )
inline

Function Resume()

Resumes execution of a previously yielded coroutine. Call this method only from the main application stack.

Returns
true, if the coroutine has yielded again and false if it has finished its execution (returned).

Definition at line 238 of file coroutine.h.

Referenced by TOOL_MANAGER::dispatchInternal(), and MyClass::Run().

239  {
240  CALL_CONTEXT ctx;
241  INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROOT, this, &ctx };
242  ctx.Continue( doResume( &args ) );
243 
244  return Running();
245  }
INVOCATION_ARGS * doResume(INVOCATION_ARGS *args)
Definition: coroutine.h:311
bool Running() const
Function Running()
Definition: coroutine.h:279
template<typename ReturnType, typename ArgType>
bool COROUTINE< ReturnType, ArgType >::Resume ( const COROUTINE< ReturnType, ArgType > &  aCor)
inline

Function Resume()

Resumes execution of a previously yielded coroutine. Call this method for a nested coroutine invocation.

Returns
true, if the coroutine has yielded again and false if it has finished its execution (returned).

Definition at line 255 of file coroutine.h.

256  {
257  INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROUTINE, this, aCor.m_callContext };
258  doResume( &args );
259  // we will not be asked to continue
260 
261  return Running();
262  }
CALL_CONTEXT * m_callContext
saved coroutine context
Definition: coroutine.h:379
INVOCATION_ARGS * doResume(INVOCATION_ARGS *args)
Definition: coroutine.h:311
bool Running() const
Function Running()
Definition: coroutine.h:279
template<typename ReturnType, typename ArgType>
const ReturnType& COROUTINE< ReturnType, ArgType >::ReturnValue ( ) const
inline

Function ReturnValue()

Returns the yielded value (the argument KiYield() was called with)

Definition at line 269 of file coroutine.h.

Referenced by MyClass::Run().

270  {
271  return m_retVal;
272  }
ReturnType m_retVal
Definition: coroutine.h:384
template<typename ReturnType, typename ArgType>
void COROUTINE< ReturnType, ArgType >::RunMainStack ( std::function< void()>  func)
inline

Function RunMainStack()

Run a functor inside the application main stack context Call this function for example if the operation will spawn a webkit browser instance which will walk the stack to the upper border of the address space on mac osx systems because its javascript needs garbage collection (for example if you paste text into an edit box).

Definition at line 190 of file coroutine.h.

Referenced by TOOL_MANAGER::RunMainStack().

191  {
192  assert( m_callContext );
193  m_callContext->RunMainStack( this, std::move( func ) );
194  }
void RunMainStack(COROUTINE *aCor, std::function< void()> aFunc)
Definition: coroutine.h:90
CALL_CONTEXT * m_callContext
saved coroutine context
Definition: coroutine.h:379
template<typename ReturnType, typename ArgType>
bool COROUTINE< ReturnType, ArgType >::Running ( ) const
inline

Function Running()

Returns
true, if the coroutine is active

Definition at line 279 of file coroutine.h.

Referenced by COROUTINE< int, int >::Call(), TOOL_MANAGER::dispatchInternal(), COROUTINE< int, int >::Resume(), and MyClass::Run().

280  {
281  return m_running;
282  }
bool m_running
pointer to coroutine entry arguments.
Definition: coroutine.h:369
template<typename ReturnType, typename ArgType>
void COROUTINE< ReturnType, ArgType >::SetEntry ( std::function< ReturnType(ArgType)>  aEntry)
inline

Function SetEntry()

Defines the entry point for the coroutine, if not set in the constructor.

Definition at line 177 of file coroutine.h.

178  {
179  m_func = std::move( aEntry );
180  }
std::function< ReturnType(ArgType)> m_func
Definition: coroutine.h:367

Member Data Documentation

template<typename ReturnType, typename ArgType>
constexpr int COROUTINE< ReturnType, ArgType >::c_defaultStackSize = 2000000
staticprivate

Definition at line 362 of file coroutine.h.

Referenced by COROUTINE< int, int >::doCall().

template<typename ReturnType, typename ArgType>
std::remove_reference<ArgType>::type* COROUTINE< ReturnType, ArgType >::m_args
private

saved caller context

Definition at line 373 of file coroutine.h.

Referenced by COROUTINE< int, int >::callerStub(), and COROUTINE< int, int >::doCall().

template<typename ReturnType, typename ArgType>
CALL_CONTEXT* COROUTINE< ReturnType, ArgType >::m_callContext
private
template<typename ReturnType, typename ArgType>
CALLEE_STORAGE COROUTINE< ReturnType, ArgType >::m_callee
private
template<typename ReturnType, typename ArgType>
CONTEXT_T COROUTINE< ReturnType, ArgType >::m_caller
private

main stack information

Definition at line 376 of file coroutine.h.

Referenced by COROUTINE< int, int >::callerStub(), COROUTINE< int, int >::jumpIn(), and COROUTINE< int, int >::jumpOut().

template<typename ReturnType, typename ArgType>
std::function<ReturnType( ArgType )> COROUTINE< ReturnType, ArgType >::m_func
private
template<typename ReturnType, typename ArgType>
ReturnType COROUTINE< ReturnType, ArgType >::m_retVal
private
template<typename ReturnType, typename ArgType>
bool COROUTINE< ReturnType, ArgType >::m_running
private

pointer to coroutine entry arguments.

Stripped of references to avoid compiler errors.

Definition at line 369 of file coroutine.h.

Referenced by COROUTINE< int, int >::callerStub(), COROUTINE< int, int >::doCall(), and COROUTINE< int, int >::Running().

template<typename ReturnType, typename ArgType>
std::unique_ptr<char[]> COROUTINE< ReturnType, ArgType >::m_stack
private

< coroutine stack

Definition at line 365 of file coroutine.h.

Referenced by COROUTINE< int, int >::doCall().


The documentation for this class was generated from the following file: