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_callContext( nullptr ),
139  m_callee( nullptr ),
140  m_retVal( 0 )
141  {
142  }
std::function< ReturnType(ArgType)> m_func
Definition: coroutine.h:368
bool m_running
pointer to coroutine entry arguments.
Definition: coroutine.h:370
CALL_CONTEXT * m_callContext
saved coroutine context
Definition: coroutine.h:380
std::remove_reference< ArgType >::type * m_args
saved caller context
Definition: coroutine.h:374
CALLEE_STORAGE m_callee
Definition: coroutine.h:383
ReturnType m_retVal
Definition: coroutine.h:385
template<typename ReturnType, typename ArgType>
COROUTINE< ReturnType, ArgType >::~COROUTINE ( )
inline

Definition at line 144 of file coroutine.h.

145  {
146  }

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 205 of file coroutine.h.

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

206  {
207  CALL_CONTEXT ctx;
208  INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROOT, this, &ctx };
209  ctx.Continue( doCall( &args, aArg ) );
210 
211  return Running();
212  }
INVOCATION_ARGS * doCall(INVOCATION_ARGS *aInvArgs, ArgType aArgs)
Definition: coroutine.h:286
bool Running() const
Function Running()
Definition: coroutine.h:280
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 222 of file coroutine.h.

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

Definition at line 318 of file coroutine.h.

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

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

Definition at line 286 of file coroutine.h.

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

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

Definition at line 312 of file coroutine.h.

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

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

Definition at line 336 of file coroutine.h.

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

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

Definition at line 346 of file coroutine.h.

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

347  {
348  INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROUTINE, nullptr, nullptr };
349  INVOCATION_ARGS* ret;
350  ret = reinterpret_cast<INVOCATION_ARGS*>(
352  reinterpret_cast<intptr_t>( &args ) )
353  );
354 
355  m_callContext = ret->context;
356 
357  if( ret->type == INVOCATION_ARGS::FROM_ROOT )
358  {
360  }
361  }
intptr_t LIBCONTEXT_CALL_CONVENTION jump_fcontext(fcontext_t *ofc, fcontext_t nfc, intptr_t vp, bool preserve_fpu=true)
CALL_CONTEXT * m_callContext
saved coroutine context
Definition: coroutine.h:380
CONTEXT_T m_caller
main stack information
Definition: coroutine.h:377
CALLEE_STORAGE m_callee
Definition: coroutine.h:383
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 156 of file coroutine.h.

Referenced by TOOL_MANAGER::ScheduleWait().

157  {
158  jumpOut();
159  }
void jumpOut()
Definition: coroutine.h:346
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 167 of file coroutine.h.

168  {
169  m_retVal = aRetVal;
170  jumpOut();
171  }
void jumpOut()
Definition: coroutine.h:346
ReturnType m_retVal
Definition: coroutine.h:385
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 239 of file coroutine.h.

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

240  {
241  CALL_CONTEXT ctx;
242  INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROOT, this, &ctx };
243  ctx.Continue( doResume( &args ) );
244 
245  return Running();
246  }
INVOCATION_ARGS * doResume(INVOCATION_ARGS *args)
Definition: coroutine.h:312
bool Running() const
Function Running()
Definition: coroutine.h:280
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 256 of file coroutine.h.

257  {
258  INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROUTINE, this, aCor.m_callContext };
259  doResume( &args );
260  // we will not be asked to continue
261 
262  return Running();
263  }
CALL_CONTEXT * m_callContext
saved coroutine context
Definition: coroutine.h:380
INVOCATION_ARGS * doResume(INVOCATION_ARGS *args)
Definition: coroutine.h:312
bool Running() const
Function Running()
Definition: coroutine.h:280
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 270 of file coroutine.h.

Referenced by MyClass::Run().

271  {
272  return m_retVal;
273  }
ReturnType m_retVal
Definition: coroutine.h:385
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 191 of file coroutine.h.

Referenced by TOOL_MANAGER::RunMainStack().

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

Function Running()

Returns
true, if the coroutine is active

Definition at line 280 of file coroutine.h.

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

281  {
282  return m_running;
283  }
bool m_running
pointer to coroutine entry arguments.
Definition: coroutine.h:370
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 178 of file coroutine.h.

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

Member Data Documentation

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

Definition at line 363 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 374 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 377 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 370 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 366 of file coroutine.h.

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


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