Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/libcfa/concurrency/coroutines

    rc84e80a raed3f54  
    1 //                              - *- Mode: CFA - *-
    2 //
    3 // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
    4 //
    5 // The contents of this file are covered under the licence agreement in the
    6 // file "LICENCE" distributed with Cforall.
    7 //
    8 // coroutines --
    9 //
    10 // Author           : Thierry Delisle
    11 // Created On       : Mon Nov 28 12:27:26 2016
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : Mon Nov 28 12:27:26 2016
    14 // Update Count     : 0
    15 //
    16 
    17 #ifndef COROUTINES_H
    18 #define COROUTINES_H
    19 
    20 #include "assert"
    21 #include "invoke.h"
    22 
    23 //-----------------------------------------------------------------------------
    24 // Coroutine trait
    25 // Anything that implements this trait can be resumed.
    26 // Anything that is resumed is a coroutine.
    27 trait is_coroutine(dtype T) {
    28       void main(T * this);
    29       coroutine * get_coroutine(T * this);
    30 };
    31 
    32 #define DECL_COROUTINE(X) static inline coroutine* get_coroutine(X* this) { return &this->c; } void main(X* this);
    33 
    34 //-----------------------------------------------------------------------------
    35 // Ctors and dtors
    36 void ?{}(coStack_t * this);
    37 void ?{}(coroutine * this);
    38 void ^?{}(coStack_t * this);
    39 void ^?{}(coroutine * this);
    40 
    41 //-----------------------------------------------------------------------------
    42 // Public coroutine API
    43 static inline void suspend();
    44 
    45 forall(dtype T | is_coroutine(T))
    46 static inline void resume(T * cor);
    47 
    48 forall(dtype T | is_coroutine(T))
    49 void prime(T * cor);
    50 
    51 //-----------------------------------------------------------------------------
    52 // PRIVATE exposed because of inline
    53 
    54 // Start coroutine routines
    55 extern "C" {
    56       forall(dtype T | is_coroutine(T))
    57       void CtxInvokeCoroutine(T * this);
    58 
    59       forall(dtype T | is_coroutine(T))
    60       void CtxStart(T * this, void ( *invoke)(T *));
    61 }
    62 
    63 // Get current coroutine
    64 extern coroutine * current_coroutine; //PRIVATE, never use directly
    65 static inline coroutine * this_coroutine(void) {
    66         return current_coroutine;
    67 }
    68 
    69 // Private wrappers for context switch and stack creation
    70 extern void corCxtSw(coroutine * src, coroutine * dst);
    71 extern void create_stack( coStack_t * this, unsigned int storageSize );
    72 
    73 // Suspend implementation inlined for performance
    74 static inline void suspend() {
    75       coroutine * src = this_coroutine();               // optimization
    76 
    77         assertf( src->last != 0,
    78                 "Attempt to suspend coroutine %.256s (%p) that has never been resumed.\n"
    79                 "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",
    80                 src->name, src );
    81         assertf( src->last->notHalted,
    82                 "Attempt by coroutine %.256s (%p) to suspend back to terminated coroutine %.256s (%p).\n"
    83                 "Possible cause is terminated coroutine's main routine has already returned.",
    84                 src->name, src, src->last->name, src->last );
    85 
    86         corCxtSw( src, src->last );
    87 }
    88 
    89 // Resume implementation inlined for performance
    90 forall(dtype T | is_coroutine(T))
    91 static inline void resume(T * cor) {
    92         coroutine * src = this_coroutine();             // optimization
    93         coroutine * dst = get_coroutine(cor);
    94 
    95       if( unlikely(!dst->stack.base) ) {
    96                 create_stack(&dst->stack, dst->stack.size);
    97                 CtxStart(cor, CtxInvokeCoroutine);
    98         }
    99 
    100       // not resuming self ?
    101         if ( src != dst ) {
    102                 assertf( dst->notHalted ,
    103                         "Attempt by coroutine %.256s (%p) to resume terminated coroutine %.256s (%p).\n"
    104                         "Possible cause is terminated coroutine's main routine has already returned.",
    105                         src->name, src, dst->name, dst );
    106 
    107             // set last resumer
    108                 dst->last = src;
    109         } // if
    110 
    111       // always done for performance testing
    112         corCxtSw( src, dst );
    113 }
    114 
    115 #endif //COROUTINES_H
    116 
    117 // Local Variables: //
    118 // mode: c //
    119 // tab-width: 4 //
    120 // End: //
Note: See TracChangeset for help on using the changeset viewer.