Changeset 427854b


Ignore:
Timestamp:
Mar 2, 2020, 4:59:27 PM (4 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
dfa4360
Parents:
37cdd97
Message:

First draft implementation of generators, still missing error checking, testing and clean-up

Files:
2 added
24 edited

Legend:

Unmodified
Added
Removed
  • benchmark/ctxswitch/cfa_cor.cfa

    r37cdd97 r427854b  
    77void main( __attribute__((unused)) C & ) {
    88        while () {
    9                 suspend();
     9                suspend;
    1010        }
    1111}
  • libcfa/prelude/builtins.c

    r37cdd97 r427854b  
    4848void exit( int status, const char fmt[], ... ) __attribute__ (( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
    4949void abort( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
     50
     51forall(dtype T)
     52static inline T & identity(T & i) {
     53        return i;
     54}
     55
     56// generator support
     57struct $generator {
     58        inline int;
     59};
     60
     61static inline void  ?{}($generator & this) { ((int&)this) = 0; }
     62static inline void ^?{}($generator &) {}
     63
     64trait is_generator(dtype T) {
     65      void main(T & this);
     66      $generator * get_generator(T & this);
     67};
     68
     69forall(dtype T | is_generator(T))
     70static inline T & resume(T & gen) {
     71        main(gen);
     72        return gen;
     73}
    5074
    5175// implicit increment, decrement if += defined, and implicit not if != defined
  • libcfa/src/concurrency/coroutine.cfa

    r37cdd97 r427854b  
    208208
    209209                if(cor->state == Primed) {
    210                         suspend();
     210                        __cfactx_suspend();
    211211                }
    212212
  • libcfa/src/concurrency/coroutine.hfa

    r37cdd97 r427854b  
    4646//-----------------------------------------------------------------------------
    4747// Public coroutine API
    48 static inline void suspend(void);
    49 
    50 forall(dtype T | is_coroutine(T))
    51 static inline T & resume(T & cor);
    52 
    5348forall(dtype T | is_coroutine(T))
    5449void prime(T & cor);
     
    9691
    9792// Suspend implementation inlined for performance
    98 static inline void suspend(void) {
    99         // optimization : read TLS once and reuse it
    100         // Safety note: this is preemption safe since if
    101         // preemption occurs after this line, the pointer
    102         // will also migrate which means this value will
    103         // stay in syn with the TLS
    104         $coroutine * src = TL_GET( this_thread )->curr_cor;
     93extern "C" {
     94        static inline void __cfactx_suspend(void) {
     95                // optimization : read TLS once and reuse it
     96                // Safety note: this is preemption safe since if
     97                // preemption occurs after this line, the pointer
     98                // will also migrate which means this value will
     99                // stay in syn with the TLS
     100                $coroutine * src = TL_GET( this_thread )->curr_cor;
    105101
    106         assertf( src->last != 0,
    107                 "Attempt to suspend coroutine \"%.256s\" (%p) that has never been resumed.\n"
    108                 "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",
    109                 src->name, src );
    110         assertf( src->last->state != Halted,
    111                 "Attempt by coroutine \"%.256s\" (%p) to suspend back to terminated coroutine \"%.256s\" (%p).\n"
    112                 "Possible cause is terminated coroutine's main routine has already returned.",
    113                 src->name, src, src->last->name, src->last );
     102                assertf( src->last != 0,
     103                        "Attempt to suspend coroutine \"%.256s\" (%p) that has never been resumed.\n"
     104                        "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",
     105                        src->name, src );
     106                assertf( src->last->state != Halted,
     107                        "Attempt by coroutine \"%.256s\" (%p) to suspend back to terminated coroutine \"%.256s\" (%p).\n"
     108                        "Possible cause is terminated coroutine's main routine has already returned.",
     109                        src->name, src, src->last->name, src->last );
    114110
    115         $ctx_switch( src, src->last );
     111                $ctx_switch( src, src->last );
     112        }
    116113}
    117114
  • src/AST/Decl.hpp

    r37cdd97 r427854b  
    259259
    260260        bool is_coroutine() { return kind == Coroutine; }
    261         bool is_monitor() { return kind == Monitor; }
    262         bool is_thread() { return kind == Thread; }
     261        bool is_generator() { return kind == Generator; }
     262        bool is_monitor  () { return kind == Monitor  ; }
     263        bool is_thread   () { return kind == Thread   ; }
    263264
    264265        const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/Concurrency/Keywords.cc

    r37cdd97 r427854b  
    1616#include "Concurrency/Keywords.h"
    1717
    18 #include <cassert>                 // for assert
    19 #include <string>                  // for string, operator==
    20 
    21 #include "Common/PassVisitor.h"    // for PassVisitor
    22 #include "Common/SemanticError.h"  // for SemanticError
    23 #include "Common/utility.h"        // for deleteAll, map_range
    24 #include "CodeGen/OperatorTable.h" // for isConstructor
    25 #include "InitTweak/InitTweak.h"   // for getPointerBase
    26 #include "SynTree/LinkageSpec.h"   // for Cforall
    27 #include "SynTree/Constant.h"      // for Constant
    28 #include "SynTree/Declaration.h"   // for StructDecl, FunctionDecl, ObjectDecl
    29 #include "SynTree/Expression.h"    // for VariableExpr, ConstantExpr, Untype...
    30 #include "SynTree/Initializer.h"   // for SingleInit, ListInit, Initializer ...
    31 #include "SynTree/Label.h"         // for Label
    32 #include "SynTree/Statement.h"     // for CompoundStmt, DeclStmt, ExprStmt
    33 #include "SynTree/Type.h"          // for StructInstType, Type, PointerType
    34 #include "SynTree/Visitor.h"       // for Visitor, acceptAll
     18#include <cassert>                        // for assert
     19#include <string>                         // for string, operator==
     20
     21#include "Common/PassVisitor.h"           // for PassVisitor
     22#include "Common/SemanticError.h"         // for SemanticError
     23#include "Common/utility.h"               // for deleteAll, map_range
     24#include "CodeGen/OperatorTable.h"        // for isConstructor
     25#include "ControlStruct/LabelGenerator.h" // for LebelGenerator
     26#include "InitTweak/InitTweak.h"          // for getPointerBase
     27#include "SynTree/LinkageSpec.h"          // for Cforall
     28#include "SynTree/Constant.h"             // for Constant
     29#include "SynTree/Declaration.h"          // for StructDecl, FunctionDecl, ObjectDecl
     30#include "SynTree/Expression.h"           // for VariableExpr, ConstantExpr, Untype...
     31#include "SynTree/Initializer.h"          // for SingleInit, ListInit, Initializer ...
     32#include "SynTree/Label.h"                // for Label
     33#include "SynTree/Statement.h"            // for CompoundStmt, DeclStmt, ExprStmt
     34#include "SynTree/Type.h"                 // for StructInstType, Type, PointerType
     35#include "SynTree/Visitor.h"              // for Visitor, acceptAll
    3536
    3637class Attribute;
     
    147148        };
    148149
     150
     151
    149152        //-----------------------------------------------------------------------------
    150153        //Handles monitor type declarations :
     
    180183
    181184        //-----------------------------------------------------------------------------
     185        //Handles generator type declarations :
     186        // generator MyGenerator {                   struct MyGenerator {
     187        //      int data;                                  int data;
     188        //      a_struct_t more_data;                      a_struct_t more_data;
     189        //                                =>             int __gen_next;
     190        // };                                        };
     191        //
     192        class GeneratorKeyword final : public ConcurrentSueKeyword {
     193          public:
     194
     195                GeneratorKeyword() : ConcurrentSueKeyword(
     196                        "$generator",
     197                        "__generator_state",
     198                        "get_generator",
     199                        "Unable to find builtin type $generator\n",
     200                        true,
     201                        AggregateDecl::Generator
     202                )
     203                {}
     204
     205                virtual ~GeneratorKeyword() {}
     206
     207                virtual bool is_target( StructDecl * decl ) override final { return decl->is_generator(); }
     208
     209                static void implement( std::list< Declaration * > & translationUnit ) {
     210                        PassVisitor< GeneratorKeyword > impl;
     211                        mutateAll( translationUnit, impl );
     212                }
     213        };
     214
     215
     216        //-----------------------------------------------------------------------------
     217        class SuspendKeyword final : public WithStmtsToAdd, public WithGuards {
     218        public:
     219                SuspendKeyword() = default;
     220                virtual ~SuspendKeyword() = default;
     221
     222                void  premutate( FunctionDecl * );
     223                DeclarationWithType * postmutate( FunctionDecl * );
     224
     225                Statement * postmutate( SuspendStmt * );
     226
     227                static void implement( std::list< Declaration * > & translationUnit ) {
     228                        PassVisitor< SuspendKeyword > impl;
     229                        mutateAll( translationUnit, impl );
     230                }
     231
     232        private:
     233                DeclarationWithType * is_main( FunctionDecl * );
     234                bool is_real_suspend( FunctionDecl * );
     235
     236                Statement * make_generator_suspend( SuspendStmt * );
     237                Statement * make_coroutine_suspend( SuspendStmt * );
     238
     239                struct LabelPair {
     240                        Label obj;
     241                        int   idx;
     242                };
     243
     244                LabelPair make_label() {
     245                        labels.push_back( gen.newLabel("generator") );
     246                        return { labels.back(), int(labels.size()) };
     247                }
     248
     249                DeclarationWithType * in_generator = nullptr;
     250                FunctionDecl * decl_suspend = nullptr;
     251                std::vector<Label> labels;
     252                ControlStruct::LabelGenerator & gen = *ControlStruct::LabelGenerator::getGenerator();
     253        };
     254
     255        //-----------------------------------------------------------------------------
    182256        //Handles mutex routines definitions :
    183257        // void foo( A * mutex a, B * mutex b,  int i ) {                  void foo( A * a, B * b,  int i ) {
     
    251325                CoroutineKeyword        ::implement( translationUnit );
    252326                MonitorKeyword  ::implement( translationUnit );
     327                GeneratorKeyword  ::implement( translationUnit );
     328                SuspendKeyword    ::implement( translationUnit );
    253329        }
    254330
     
    446522
    447523                declsToAddAfter.push_back( get_decl );
    448 
    449                 // get_decl->fixUniqueId();
    450         }
     524        }
     525
     526        //=============================================================================================
     527        // Suspend keyword implementation
     528        //=============================================================================================
     529        DeclarationWithType * SuspendKeyword::is_main( FunctionDecl * func) {
     530                if(func->name != "main") return nullptr;
     531                if(func->type->parameters.size() != 1) return nullptr;
     532
     533                auto param = func->type->parameters.front();
     534
     535                auto type  = dynamic_cast<ReferenceType * >(param->get_type());
     536                if(!type) return nullptr;
     537
     538                auto obj   = dynamic_cast<StructInstType *>(type->base);
     539                if(!obj) return nullptr;
     540
     541                if(!obj->baseStruct->is_generator()) return nullptr;
     542
     543                return param;
     544        }
     545
     546        bool SuspendKeyword::is_real_suspend( FunctionDecl * func ) {
     547                if(isMangled(func->linkage)) return false; // the real suspend isn't mangled
     548                if(func->name != "__cfactx_suspend") return false; // the real suspend has a specific name
     549                if(func->type->parameters.size() != 0) return false; // Too many parameters
     550                if(func->type->returnVals.size() != 0) return false; // Too many return values
     551
     552                return true;
     553        }
     554
     555        void SuspendKeyword::premutate( FunctionDecl * func ) {
     556                GuardValue(in_generator);
     557                in_generator = nullptr;
     558
     559                // Is this the real suspend?
     560                if(is_real_suspend(func)) {
     561                        decl_suspend = decl_suspend ? decl_suspend : func;
     562                        return;
     563                }
     564
     565                // Is this the main of a generator?
     566                auto param = is_main( func );
     567                if(!param) return;
     568
     569                if(func->type->returnVals.size() != 0) SemanticError(func->location, "Generator main must return void");
     570
     571                in_generator = param;
     572                GuardValue(labels);
     573                labels.clear();
     574        }
     575
     576        DeclarationWithType * SuspendKeyword::postmutate( FunctionDecl * func ) {
     577                if( !func->statements ) return func; // Not the actual definition, don't do anything
     578                if( !in_generator     ) return func; // Not in a generator, don't do anything
     579                if( labels.empty()    ) return func; // Generator has no states, nothing to do, could throw a warning
     580
     581                // This is a generator main, we need to add the following code to the top
     582                // static void * __generator_labels[] = {&&s0, &&s1, ...};
     583                // goto * __generator_labels[gen.__generator_state];
     584                const auto & loc = func->location;
     585
     586                const auto first_label = gen.newLabel("generator");
     587
     588                // for each label add to declaration
     589                std::list<Initializer*> inits = { new SingleInit( new LabelAddressExpr( first_label ) ) };
     590                for(const auto & label : labels) {
     591                        inits.push_back(
     592                                new SingleInit(
     593                                        new LabelAddressExpr( label )
     594                                )
     595                        );
     596                }
     597                auto init = new ListInit(std::move(inits), noDesignators, true);
     598                labels.clear();
     599
     600                // create decl
     601                auto decl = new ObjectDecl(
     602                        "__generator_labels",
     603                        Type::StorageClasses( Type::Static ),
     604                        LinkageSpec::AutoGen,
     605                        nullptr,
     606                        new ArrayType(
     607                                Type::Qualifiers(),
     608                                new PointerType(
     609                                        Type::Qualifiers(),
     610                                        new VoidType( Type::Qualifiers() )
     611                                ),
     612                                nullptr,
     613                                false, false
     614                        ),
     615                        init
     616                );
     617
     618                // create the goto
     619                assert(in_generator);
     620
     621                auto go_decl = new ObjectDecl(
     622                        "__generator_label",
     623                        noStorageClasses,
     624                        LinkageSpec::AutoGen,
     625                        nullptr,
     626                        new PointerType(
     627                                Type::Qualifiers(),
     628                                new VoidType( Type::Qualifiers() )
     629                        ),
     630                        new SingleInit(
     631                                new UntypedExpr(
     632                                        new NameExpr("?[?]"),
     633                                        {
     634                                                new NameExpr("__generator_labels"),
     635                                                new UntypedMemberExpr(
     636                                                        new NameExpr("__generator_state"),
     637                                                        new VariableExpr( in_generator )
     638                                                )
     639                                        }
     640                                )
     641                        )
     642                );
     643                go_decl->location = loc;
     644
     645                auto go = new BranchStmt(
     646                        new VariableExpr( go_decl ),
     647                        BranchStmt::Goto
     648                );
     649                go->location = loc;
     650                go->computedTarget->location = loc;
     651
     652                auto noop = new NullStmt({ first_label });
     653                noop->location = loc;
     654
     655                // wrap everything in a nice compound
     656                auto body = new CompoundStmt({
     657                        new DeclStmt( decl ),
     658                        new DeclStmt( go_decl ),
     659                        go,
     660                        noop,
     661                        func->statements
     662                });
     663                body->location   = loc;
     664                func->statements = body;
     665
     666                return func;
     667        }
     668
     669        Statement * SuspendKeyword::postmutate( SuspendStmt * stmt ) {
     670                SuspendStmt::Type type = stmt->type;
     671                if(type == SuspendStmt::None) {
     672                        // This suspend has a implicit target, find it
     673                        type = in_generator ? SuspendStmt::Generator : SuspendStmt::Coroutine;
     674                }
     675
     676                // Check that the target makes sense
     677                if(!in_generator && type == SuspendStmt::Generator) SemanticError( stmt->location, "'suspend generator' must be used inside main of generator type.");
     678
     679                // Act appropriately
     680                switch(type) {
     681                        case SuspendStmt::Generator: return make_generator_suspend(stmt);
     682                        case SuspendStmt::Coroutine: return make_coroutine_suspend(stmt);
     683                        default: abort();
     684                }
     685        }
     686
     687        Statement * SuspendKeyword::make_generator_suspend( SuspendStmt * stmt ) {
     688                assert(in_generator);
     689                // Target code is :
     690                //   gen.__generator_state = X;
     691                //   { THEN }
     692                //   return;
     693                //   __gen_X:;
     694
     695                // Save the location and delete the old statement, we only need the location from this point on
     696                auto loc = stmt->location;
     697
     698                // Build the label and get its index
     699                auto label = make_label();
     700
     701                // Create the context saving statement
     702                auto save = new ExprStmt( new UntypedExpr(
     703                        new NameExpr( "?=?" ),
     704                        {
     705                                new UntypedMemberExpr(
     706                                        new NameExpr("__generator_state"),
     707                                        new VariableExpr( in_generator )
     708                                ),
     709                                new ConstantExpr(
     710                                        Constant::from_int( label.idx )
     711                                )
     712                        }
     713                ));
     714                assert(save->expr);
     715                save->location = loc;
     716                stmtsToAddBefore.push_back( save );
     717
     718                // if we have a then add it here
     719                auto then = stmt->then;
     720                stmt->then = nullptr;
     721                delete stmt;
     722                if(then) stmtsToAddBefore.push_back( then );
     723
     724                // Create the return statement
     725                auto ret = new ReturnStmt( nullptr );
     726                ret->location = loc;
     727                stmtsToAddBefore.push_back( ret );
     728
     729                // Create the null statement with the created label
     730                auto noop = new NullStmt({ label.obj });
     731                noop->location = loc;
     732
     733                // Return the null statement to take the place of the previous statement
     734                return noop;
     735        }
     736
     737        Statement * SuspendKeyword::make_coroutine_suspend( SuspendStmt * stmt ) {
     738                if(stmt->then) SemanticError( stmt->location, "Compound statement following coroutines is not implemented.");
     739
     740                // Save the location and delete the old statement, we only need the location from this point on
     741                auto loc = stmt->location;
     742                delete stmt;
     743
     744                // Create the call expression
     745                if(!decl_suspend) SemanticError( loc, "suspend keyword applied to coroutines requires coroutines to be in scope, add #include <coroutine.hfa>\n");
     746                auto expr = new UntypedExpr( VariableExpr::functionPointer( decl_suspend ) );
     747                expr->location = stmt->location;
     748
     749                // Change this statement into a regular expr
     750                assert(expr);
     751                auto nstmt = new ExprStmt( expr );
     752                nstmt->location = stmt->location;
     753                return nstmt;
     754        }
     755
    451756
    452757        //=============================================================================================
  • src/GenPoly/Lvalue.cc

    r37cdd97 r427854b  
    140140                PassVisitor<FixIntrinsicResult> intrinsicResults;
    141141                mutateAll( translationUnit, intrinsicResults );
     142                translationUnit.back()->print( std::cout );
    142143                mutateAll( translationUnit, addrRef );
     144                translationUnit.back()->print( std::cout );
    143145                mutateAll( translationUnit, refCvt );
     146                translationUnit.back()->print( std::cout );
    144147                mutateAll( translationUnit, fixer );
     148                translationUnit.back()->print( std::cout );
    145149                mutateAll( translationUnit, collapser );
     150                translationUnit.back()->print( std::cout );
    146151                mutateAll( translationUnit, genLval );
     152                translationUnit.back()->print( std::cout );
    147153                mutateAll( translationUnit, elim );  // last because other passes need reference types to work
    148154
  • src/Parser/ParseNode.h

    r37cdd97 r427854b  
    428428Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output = nullptr, ExpressionNode * input = nullptr, ExpressionNode * clobber = nullptr, LabelNode * gotolabels = nullptr );
    429429Statement * build_directive( std::string * directive );
     430SuspendStmt * build_suspend( StatementNode *, SuspendStmt::Type = SuspendStmt::None);
    430431WaitForStmt * build_waitfor( ExpressionNode * target, StatementNode * stmt, ExpressionNode * when );
    431432WaitForStmt * build_waitfor( ExpressionNode * target, StatementNode * stmt, ExpressionNode * when, WaitForStmt * existing );
  • src/Parser/StatementNode.cc

    r37cdd97 r427854b  
    249249} // build_finally
    250250
     251SuspendStmt * build_suspend( StatementNode * then, SuspendStmt::Type type ) {
     252        auto node = new SuspendStmt();
     253
     254        node->type = type;
     255
     256        std::list< Statement * > stmts;
     257        buildMoveList< Statement, StatementNode >( then, stmts );
     258        if(!stmts.empty()) {
     259                assert( stmts.size() == 1 );
     260                node->then = dynamic_cast< CompoundStmt * >( stmts.front() );
     261        }
     262
     263        return node;
     264}
     265
    251266WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when ) {
    252267        auto node = new WaitForStmt();
  • src/Parser/TypeData.cc

    r37cdd97 r427854b  
    769769          case AggregateDecl::Struct:
    770770          case AggregateDecl::Coroutine:
     771          case AggregateDecl::Generator:
    771772          case AggregateDecl::Monitor:
    772773          case AggregateDecl::Thread:
  • src/Parser/parser.yy

    r37cdd97 r427854b  
    12611261                { SemanticError( yylloc, "Initializer return is currently unimplemented." ); $$ = nullptr; }
    12621262        | SUSPEND ';'
    1263                 { SemanticError( yylloc, "Suspend expression is currently unimplemented." ); $$ = nullptr; }
     1263                { $$ = new StatementNode( build_suspend( nullptr ) ); }
    12641264        | SUSPEND compound_statement ';'
    1265                 { SemanticError( yylloc, "Suspend expression is currently unimplemented." ); $$ = nullptr; }
     1265                { $$ = new StatementNode( build_suspend( $2 ) ); }
    12661266        | SUSPEND COROUTINE ';'
    1267                 { SemanticError( yylloc, "Suspend expression is currently unimplemented." ); $$ = nullptr; }
     1267                { $$ = new StatementNode( build_suspend( nullptr, SuspendStmt::Coroutine ) ); }
    12681268        | SUSPEND COROUTINE compound_statement
    1269                 { SemanticError( yylloc, "Suspend expression is currently unimplemented." ); $$ = nullptr; }
     1269                { $$ = new StatementNode( build_suspend( $3, SuspendStmt::Coroutine ) ); }
    12701270        | SUSPEND GENERATOR ';'
    1271                 { SemanticError( yylloc, "Suspend expression is currently unimplemented." ); $$ = nullptr; }
     1271                { $$ = new StatementNode( build_suspend( nullptr, SuspendStmt::Generator ) ); }
    12721272        | SUSPEND GENERATOR compound_statement
    1273                 { SemanticError( yylloc, "Suspend expression is currently unimplemented." ); $$ = nullptr; }
     1273                { $$ = new StatementNode( build_suspend( $3, SuspendStmt::Generator ) ); }
    12741274        | THROW assignment_expression_opt ';'                           // handles rethrow
    12751275                { $$ = new StatementNode( build_throw( $2 ) ); }
     
    20862086aggregate_control:                                                                              // CFA
    20872087        GENERATOR
    2088                 { SemanticError( yylloc, "generator is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
     2088                { yyy = true; $$ = AggregateDecl::Generator; }
    20892089        | MONITOR GENERATOR
    20902090                { SemanticError( yylloc, "monitor generator is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
  • src/SynTree/Declaration.h

    r37cdd97 r427854b  
    302302
    303303        bool is_coroutine() { return kind == Coroutine; }
    304         bool is_monitor() { return kind == Monitor; }
    305         bool is_thread() { return kind == Thread; }
     304        bool is_generator() { return kind == Generator; }
     305        bool is_monitor  () { return kind == Monitor  ; }
     306        bool is_thread   () { return kind == Thread   ; }
    306307
    307308        virtual StructDecl * clone() const override { return new StructDecl( *this ); }
  • src/SynTree/Statement.h

    r37cdd97 r427854b  
    425425  public:
    426426        CompoundStmt * then = nullptr;
    427         enum { None, Coroutine, Generator } type = None;
     427        enum Type { None, Coroutine, Generator } type = None;
    428428
    429429        SuspendStmt() = default;
  • tests/concurrent/coroutineThen.cfa

    r37cdd97 r427854b  
    4949
    5050void main(Coroutine& this) {
    51         suspend();
     51        suspend;
    5252        for(int i = 0; TEST(i < N); i++) {
    5353
    5454                print("C - Suspending");
    55                 void publish() {
     55                suspend{
    5656                        print("C - Publishing");
    5757                        assert(!the_cor);
    5858                        store( this );
    5959                }
    60                 suspend_then(publish);
    6160                assert(!the_cor);
    6261                print("Coroutine 2");
     
    6564        }
    6665        done = true;
    67         suspend();
     66        suspend;
    6867}
    6968
  • tests/concurrent/coroutineYield.cfa

    r37cdd97 r427854b  
    3333                        sout | "Coroutine 2";
    3434                #endif
    35                 suspend();
     35                suspend;
    3636        }
    3737}
  • tests/coroutine/.in/fmtLines.txt

    r37cdd97 r427854b  
    3535                        for ( fmt.b = 0; fmt.b < 4; fmt.b += 1 ) {      // blocks of 4 characters
    3636                                for ( ;; ) {                                                    // for newline characters
    37                                         suspend();
     37                                        suspend;
    3838                                        if ( fmt.ch != '\n' ) break;            // ignore newline
    3939                                } // for
  • tests/coroutine/cntparens.cfa

    r37cdd97 r427854b  
    1 // 
     1//
    22// Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo
    33//
    44// The contents of this file are covered under the licence agreement in the
    55// file "LICENCE" distributed with Cforall.
    6 // 
     6//
    77// cntparens.cfa -- match left/right parenthesis
    8 // 
     8//
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat Apr 20 11:04:45 2019
     
    1212// Last Modified On : Sat Apr 20 11:06:21 2019
    1313// Update Count     : 1
    14 // 
     14//
    1515
    1616#include <fstream.hfa>
     
    2626void main( CntParens & cpns ) with( cpns ) {
    2727        for ( ; ch == '('; cnt += 1 ) {                                         // left parenthesis
    28                 suspend();
     28                suspend;
    2929        }
    3030        for ( ; ch == ')' && cnt > 1; cnt -= 1 ) {                      // right parenthesis
    31                 suspend();
     31                suspend;
    3232        }
    3333        status = ch == ')' ? Match : Error;
    3434} // main
    35        
     35
    3636void ?{}( CntParens & cpns ) with( cpns ) { status = Cont; cnt = 0; }
    3737
  • tests/coroutine/devicedriver.cfa

    r37cdd97 r427854b  
    1 // 
     1//
    22// Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo
    33//
    44// The contents of this file are covered under the licence agreement in the
    55// file "LICENCE" distributed with Cforall.
    6 // 
    7 // devicedriver.cfa -- 
    8 // 
     6//
     7// devicedriver.cfa --
     8//
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat Mar 16 15:30:34 2019
     
    1212// Last Modified On : Sat Apr 20 09:07:19 2019
    1313// Update Count     : 90
    14 // 
     14//
    1515
    1616#include <fstream.hfa>
     
    2929
    3030void checkCRC( Driver & d, unsigned int sum ) with( d ) {
    31         suspend();
     31        suspend;
    3232        unsigned short int crc = byte << 8;                                     // sign extension over written
    33         suspend();
     33        suspend;
    3434        // prevent sign extension for signed char
    3535        status = (crc | (unsigned char)byte) == sum ? MSG : ECRC;
     
    4141                status = CONT;
    4242                unsigned int lnth = 0, sum = 0;
    43                 while ( byte != STX ) suspend();
     43                while ( byte != STX ) suspend;
    4444          emsg: for () {
    45                         suspend();
     45                        suspend;
    4646                        choose ( byte ) {                                                       // process byte
    4747                          case STX:
    48                                 status = ESTX; suspend(); continue msg;
     48                                status = ESTX; suspend; continue msg;
    4949                          case ETX:
    5050                                break emsg;
    5151                          case ESC:
    52                                 suspend();
     52                                suspend;
    5353                        } // choose
    5454                        if ( lnth >= MaxMsg ) {                                         // buffer full ?
    55                                 status = ELNTH; suspend(); continue msg;
     55                                status = ELNTH; suspend; continue msg;
    5656                        } // if
    5757                        msg[lnth++] = byte;
     
    6060                msg[lnth] = '\0';                                                               // terminate string
    6161                checkCRC( d, sum );                                                             // refactor CRC check
    62                 suspend();
     62                suspend;
    6363        } // for
    6464} // main
  • tests/coroutine/fibonacci.cfa

    r37cdd97 r427854b  
    2222        int fn1, fn2;                                                                           // retained between resumes
    2323        fn = 0;  fn1 = fn;                                                                      // 1st case
    24         suspend();                                                                                      // restart last resume
     24        suspend;                                                                                        // restart last resume
    2525        fn = 1;  fn2 = fn1;  fn1 = fn;                                          // 2nd case
    26         suspend();                                                                                      // restart last resume
     26        suspend;                                                                                        // restart last resume
    2727        for () {
    2828                fn = fn1 + fn2;  fn2 = fn1;  fn1 = fn;                  // general case
    29                 suspend();                                                                              // restart last resume
     29                suspend;                                                                                // restart last resume
    3030        } // for
    3131}
  • tests/coroutine/fibonacci_1.cfa

    r37cdd97 r427854b  
    1212// Last Modified On : Thu Mar 21 08:10:45 2019
    1313// Update Count     : 25
    14 // 
     14//
    1515
    1616#include <fstream.hfa>
     
    2323        [fn1, fn] = [0, 1];                                                                     // precompute first two states
    2424        for () {
    25                 suspend();                                                                              // restart last resume
     25                suspend;                                                                                // restart last resume
    2626                [fn1, fn] = [fn, fn1 + fn];                                             // general case
    2727        } // for
  • tests/coroutine/fmtLines.cfa

    r37cdd97 r427854b  
    2727                        for ( b = 0; b < 4; b += 1 ) {                          // blocks of 4 characters
    2828                                for () {                                                                // for newline characters
    29                                         suspend();
     29                                        suspend;
    3030                                  if ( ch != '\n' ) break;                              // ignore newline
    3131                                } // for
  • tests/coroutine/raii.cfa

    r37cdd97 r427854b  
    3939        Raii raii = { "Coroutine" };
    4040        sout | "Before Suspend";
    41         suspend();
     41        suspend;
    4242        sout | "After Suspend";
    4343}
  • tests/coroutine/runningTotal.cfa

    r37cdd97 r427854b  
    2525void update( RunTotal & rntl, int input ) with( rntl ) { // helper
    2626        total += input;                                                                         // remember between activations
    27         suspend();                                                                                      // inactivate on stack
     27        suspend;                                                                                        // inactivate on stack
    2828}
    2929
  • tests/coroutine/suspend_then.cfa

    r37cdd97 r427854b  
    1818
    1919void then() {
    20         sout | "Then!";
     20
    2121}
    2222
     
    2626        int fn1, fn2;                                                           // retained between resumes
    2727        fn = 0;  fn1 = fn;                                                      // 1st case
    28         suspend_then(then);                                                     // restart last resume
     28        suspend { sout | "Then!"; }                                             // restart last resume
    2929        fn = 1;  fn2 = fn1;  fn1 = fn;                                  // 2nd case
    30         suspend_then(then);                                                     // restart last resume
     30        suspend { sout | "Then!"; }                                             // restart last resume
    3131        for () {
    3232                fn = fn1 + fn2;  fn2 = fn1;  fn1 = fn;                  // general case
    33                 suspend_then(then);                                             // restart last resume
     33                suspend { sout | "Then!"; }                                     // restart last resume
    3434        } // for
    3535}
Note: See TracChangeset for help on using the changeset viewer.