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 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 ()
 coroutine stack More...
 

Static Private Member Functions

static void callerStub (intptr_t aData)
 

Private Attributes

std::unique_ptr< char[]> m_stack
 
int m_stacksize
 
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
 

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

Member Typedef Documentation

◆ CALLEE_STORAGE

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

Definition at line 85 of file coroutine.h.

◆ CONTEXT_T

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

Definition at line 84 of file coroutine.h.

Constructor & Destructor Documentation

◆ COROUTINE() [1/3]

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

Definition at line 125 of file coroutine.h.

125  :
126  COROUTINE( nullptr )
127  {
128  }

◆ COROUTINE() [2/3]

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

135  :
136  COROUTINE( std::bind( ptr, object, std::placeholders::_1 ) )
137  {
138  }

◆ COROUTINE() [3/3]

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

144  :
145  m_func( std::move( aEntry ) ),
146  m_running( false ),
147  m_args( 0 ),
148  m_caller( nullptr ),
149  m_callContext( nullptr ),
150  m_callee( nullptr ),
151  m_retVal( 0 )
152 #ifdef KICAD_USE_VALGRIND
153  ,valgrind_stack( 0 )
154 #endif
155  {
157  }
std::function< ReturnType(ArgType)> m_func
Definition: coroutine.h:384
bool m_running
pointer to coroutine entry arguments.
Definition: coroutine.h:386
CALL_CONTEXT * m_callContext
saved coroutine context
Definition: coroutine.h:396
int m_stacksize
Definition: coroutine.h:382
CONTEXT_T m_caller
main stack information
Definition: coroutine.h:393
std::remove_reference< ArgType >::type * m_args
saved caller context
Definition: coroutine.h:390
CALLEE_STORAGE m_callee
Definition: coroutine.h:399
int m_coroutineStackSize
Set the stack size for coroutines.
ReturnType m_retVal
Definition: coroutine.h:401
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers of advanced config.

◆ ~COROUTINE()

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

Definition at line 159 of file coroutine.h.

160  {
161 #ifdef KICAD_USE_VALGRIND
162  VALGRIND_STACK_DEREGISTER( valgrind_stack );
163 #endif
164  }

Member Function Documentation

◆ Call() [1/2]

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

214  {
215  CALL_CONTEXT ctx;
216  INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROOT, this, &ctx };
217  ctx.Continue( doCall( &args, aArg ) );
218 
219  return Running();
220  }
INVOCATION_ARGS * doCall(INVOCATION_ARGS *aInvArgs, ArgType aArgs)
Definition: coroutine.h:294
bool Running() const
Function Running()
Definition: coroutine.h:288

Referenced by TOOL_MANAGER::dispatchInternal().

◆ Call() [2/2]

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

231  {
232  INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROUTINE, this, aCor.m_callContext };
233  doCall( &args, aArg );
234  // we will not be asked to continue
235 
236  return Running();
237  }
CALL_CONTEXT * m_callContext
saved coroutine context
Definition: coroutine.h:396
INVOCATION_ARGS * doCall(INVOCATION_ARGS *aInvArgs, ArgType aArgs)
Definition: coroutine.h:294
bool Running() const
Function Running()
Definition: coroutine.h:288

◆ callerStub()

template<typename ReturnType, typename ArgType>
static void COROUTINE< ReturnType, ArgType >::callerStub ( intptr_t  aData)
inlinestaticprivate

Definition at line 334 of file coroutine.h.

335  {
336  INVOCATION_ARGS& args = *reinterpret_cast<INVOCATION_ARGS*>( aData );
337  // get pointer to self
338  COROUTINE* cor = args.destination;
339  cor->m_callContext = args.context;
340 
341  if( args.type == INVOCATION_ARGS::FROM_ROOT )
342  cor->m_callContext->SetMainStack( &cor->m_caller );
343 
344  // call the coroutine method
345  cor->m_retVal = cor->m_func( *(cor->m_args) );
346  cor->m_running = false;
347 
348  // go back to wherever we came from.
349  cor->jumpOut();
350  }
std::function< ReturnType(ArgType)> m_func
Definition: coroutine.h:384
bool m_running
pointer to coroutine entry arguments.
Definition: coroutine.h:386
Class COROUNTINE.
Definition: coroutine.h:63
void jumpOut()
coroutine stack
Definition: coroutine.h:362
CALL_CONTEXT * m_callContext
saved coroutine context
Definition: coroutine.h:396
CONTEXT_T m_caller
main stack information
Definition: coroutine.h:393
std::remove_reference< ArgType >::type * m_args
saved caller context
Definition: coroutine.h:390
void SetMainStack(CONTEXT_T *aStack)
Definition: coroutine.h:95
ReturnType m_retVal
Definition: coroutine.h:401

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

◆ doCall()

template<typename ReturnType, typename ArgType>
INVOCATION_ARGS* COROUTINE< ReturnType, ArgType >::doCall ( INVOCATION_ARGS aInvArgs,
ArgType  aArgs 
)
inlineprivate

Definition at line 294 of file coroutine.h.

295  {
296  assert( m_func );
297  assert( !m_callee );
298 
299  m_args = &aArgs;
300 
301  assert( m_stack == nullptr );
302 
303  size_t stackSize = m_stacksize;
304  void* sp = nullptr;
305 
306  #ifndef LIBCONTEXT_HAS_OWN_STACK
307  // fixme: Clean up stack stuff. Add a guard
308  m_stack.reset( new char[stackSize] );
309 
310  // align to 16 bytes
311  sp = (void*)((((ptrdiff_t) m_stack.get()) + stackSize - 0xf) & (~0x0f));
312 
313  // correct the stack size
314  stackSize -= size_t( ( (ptrdiff_t) m_stack.get() + stackSize ) - (ptrdiff_t) sp );
315 
316 #ifdef KICAD_USE_VALGRIND
317  valgrind_stack = VALGRIND_STACK_REGISTER( sp, m_stack.get() );
318 #endif
319  #endif
320 
321  m_callee = libcontext::make_fcontext( sp, stackSize, callerStub );
322  m_running = true;
323 
324  // off we go!
325  return jumpIn( aInvArgs );
326  }
std::function< ReturnType(ArgType)> m_func
Definition: coroutine.h:384
bool m_running
pointer to coroutine entry arguments.
Definition: coroutine.h:386
std::unique_ptr< char[]> m_stack
Definition: coroutine.h:380
int m_stacksize
Definition: coroutine.h:382
std::remove_reference< ArgType >::type * m_args
saved caller context
Definition: coroutine.h:390
CALLEE_STORAGE m_callee
Definition: coroutine.h:399
static void callerStub(intptr_t aData)
Definition: coroutine.h:334
INVOCATION_ARGS * jumpIn(INVOCATION_ARGS *args)
Definition: coroutine.h:352

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

◆ doResume()

template<typename ReturnType, typename ArgType>
INVOCATION_ARGS* COROUTINE< ReturnType, ArgType >::doResume ( INVOCATION_ARGS args)
inlineprivate

Definition at line 328 of file coroutine.h.

329  {
330  return jumpIn( args );
331  }
INVOCATION_ARGS * jumpIn(INVOCATION_ARGS *args)
Definition: coroutine.h:352

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

◆ jumpIn()

template<typename ReturnType, typename ArgType>
INVOCATION_ARGS* COROUTINE< ReturnType, ArgType >::jumpIn ( INVOCATION_ARGS args)
inlineprivate

Definition at line 352 of file coroutine.h.

353  {
354  args = reinterpret_cast<INVOCATION_ARGS*>(
355  libcontext::jump_fcontext( &m_caller, m_callee,
356  reinterpret_cast<intptr_t>( args ) )
357  );
358 
359  return args;
360  }
CONTEXT_T m_caller
main stack information
Definition: coroutine.h:393
CALLEE_STORAGE m_callee
Definition: coroutine.h:399

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

◆ jumpOut()

template<typename ReturnType, typename ArgType>
void COROUTINE< ReturnType, ArgType >::jumpOut ( )
inlineprivate

◆ KiYield() [1/2]

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

175  {
176  jumpOut();
177  }
void jumpOut()
coroutine stack
Definition: coroutine.h:362

Referenced by TOOL_MANAGER::ScheduleWait().

◆ KiYield() [2/2]

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

186  {
187  m_retVal = aRetVal;
188  jumpOut();
189  }
void jumpOut()
coroutine stack
Definition: coroutine.h:362
ReturnType m_retVal
Definition: coroutine.h:401

◆ Resume() [1/2]

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

248  {
249  CALL_CONTEXT ctx;
250  INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROOT, this, &ctx };
251  ctx.Continue( doResume( &args ) );
252 
253  return Running();
254  }
INVOCATION_ARGS * doResume(INVOCATION_ARGS *args)
Definition: coroutine.h:328
bool Running() const
Function Running()
Definition: coroutine.h:288

Referenced by TOOL_MANAGER::dispatchInternal().

◆ Resume() [2/2]

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

265  {
266  INVOCATION_ARGS args{ INVOCATION_ARGS::FROM_ROUTINE, this, aCor.m_callContext };
267  doResume( &args );
268  // we will not be asked to continue
269 
270  return Running();
271  }
CALL_CONTEXT * m_callContext
saved coroutine context
Definition: coroutine.h:396
INVOCATION_ARGS * doResume(INVOCATION_ARGS *args)
Definition: coroutine.h:328
bool Running() const
Function Running()
Definition: coroutine.h:288

◆ ReturnValue()

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

279  {
280  return m_retVal;
281  }
ReturnType m_retVal
Definition: coroutine.h:401

◆ RunMainStack()

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

200  {
201  assert( m_callContext );
202  m_callContext->RunMainStack( this, std::move( func ) );
203  }
void RunMainStack(COROUTINE *aCor, std::function< void()> aFunc)
Definition: coroutine.h:100
CALL_CONTEXT * m_callContext
saved coroutine context
Definition: coroutine.h:396

Referenced by TOOL_MANAGER::RunMainStack().

◆ Running()

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

Function Running()

Returns
true, if the coroutine is active

Definition at line 288 of file coroutine.h.

289  {
290  return m_running;
291  }
bool m_running
pointer to coroutine entry arguments.
Definition: coroutine.h:386

Referenced by COROUTINE< int, const TOOL_EVENT & >::Call(), TOOL_MANAGER::dispatchInternal(), and COROUTINE< int, const TOOL_EVENT & >::Resume().

Member Data Documentation

◆ m_args

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

saved caller context

Definition at line 390 of file coroutine.h.

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

◆ m_callContext

◆ m_callee

◆ m_caller

template<typename ReturnType, typename ArgType>
CONTEXT_T COROUTINE< ReturnType, ArgType >::m_caller
private

◆ m_func

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

◆ m_retVal

template<typename ReturnType, typename ArgType>
ReturnType COROUTINE< ReturnType, ArgType >::m_retVal
private

◆ m_running

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

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

◆ m_stack

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

Definition at line 380 of file coroutine.h.

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

◆ m_stacksize

template<typename ReturnType, typename ArgType>
int COROUTINE< ReturnType, ArgType >::m_stacksize
private

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