Changes in / [7a24d76:03936530]


Ignore:
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/actor.hfa

    r7a24d76 r03936530  
     1#pragma once
     2
    13#include <locks.hfa>
    24#include <limits.hfa>
    35#include <list.hfa>
     6#include <kernel.hfa>
    47
    58#ifdef __CFA_DEBUG__
  • src/Concurrency/Actors.cpp

    r7a24d76 r03936530  
    2121#include "AST/TranslationUnit.hpp"
    2222#include "AST/Expr.hpp"
     23#include <algorithm>
    2324using namespace ast;
     25using namespace std;
    2426
    2527namespace Concurrency {
    2628
    2729struct CollectactorStructDecls : public ast::WithGuards {
    28     std::map<const StructDecl *, int> & actorStructDecls;
    29     std::map<const StructDecl *, int>  & messageStructDecls;
     30    unordered_set<const StructDecl *> & actorStructDecls;
     31    unordered_set<const StructDecl *>  & messageStructDecls;
    3032    const StructDecl ** requestDecl;
    3133    const EnumDecl ** allocationDecl;
     
    3436    StructDecl * parentDecl;
    3537    bool insideStruct = false;
    36 
     38    bool namedDecl = false;
     39
     40    // finds and sets a ptr to the Allocation enum, which is needed in the next pass
    3741    void previsit( const EnumDecl * decl ) {
    3842        if( decl->name == "Allocation" ) *allocationDecl = decl;
    3943    }
    4044
     45    // finds and sets a ptr to the actor, message, and request structs, which are needed in the next pass
    4146    void previsit( const StructDecl * decl ) {
    4247        GuardValue(insideStruct);
     
    4550        if( decl->name == "actor" ) *actorDecl = decl;
    4651        if( decl->name == "message" ) *msgDecl = decl;
    47         if( decl->name == "request" ) *requestDecl = decl;       
     52        if( decl->name == "request" ) *requestDecl = decl;
    4853        }
    4954
     55    // this catches structs of the form:
     56    //     struct dummy_actor { actor a; };
     57    // since they should be:
     58    //     struct dummy_actor { inline actor; };
     59    void previsit ( const ObjectDecl * decl ) {
     60        if ( insideStruct && ! decl->name.empty() ) {
     61            GuardValue(namedDecl);
     62            namedDecl = true;
     63        }
     64    }
     65
     66    // this collects the valid actor and message struct decl pts
    5067    void postvisit( const StructInstType * node ) {
    5168        if ( ! *actorDecl || ! *msgDecl ) return;
    52         if ( insideStruct ) {
     69        if ( insideStruct && !namedDecl ) {
    5370            if ( node->aggr() == *actorDecl ) {
    54                 actorStructDecls.insert({parentDecl, 1});
     71                actorStructDecls.insert( parentDecl );
    5572            } else if ( node->aggr() == *msgDecl ) {
    56                 messageStructDecls.insert({parentDecl, 1});
     73                messageStructDecls.insert( parentDecl );
    5774            }
    5875        }
     
    6077
    6178  public:
    62     CollectactorStructDecls( std::map<const StructDecl *, int> & actorStructDecls, std::map<const StructDecl *, int> & messageStructDecls,
     79    CollectactorStructDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
    6380        const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl )
    6481        : actorStructDecls( actorStructDecls ), messageStructDecls( messageStructDecls ), requestDecl( requestDecl ),
     
    6683};
    6784
     85// keeps track of all fwdDecls of message routines so that we can hoist them to right after the appropriate decls
     86class FwdDeclTable {
     87
     88    // tracks which decls we have seen so that we can hoist the FunctionDecl to the highest point possible
     89    struct FwdDeclData {
     90        const StructDecl * actorDecl;
     91        const StructDecl * msgDecl;
     92        FunctionDecl * fwdDecl;
     93        bool actorFound;
     94        bool msgFound;
     95
     96        bool readyToInsert() { return actorFound && msgFound; }
     97        bool foundActor() { actorFound = true; return readyToInsert(); }
     98        bool foundMsg() { msgFound = true; return readyToInsert(); }
     99
     100        FwdDeclData( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) :
     101            actorDecl(actorDecl), msgDecl(msgDecl), fwdDecl(fwdDecl), actorFound(false), msgFound(false) {}
     102    };
     103
     104    // map indexed by actor struct ptr
     105    // value is map of all FwdDeclData that contains said actor struct ptr
     106    // inner map is indexed by the message struct ptr of FwdDeclData
     107    unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> actorMap;
     108
     109    // this map is the same except the outer map is indexed by message ptr and the inner is indexed by actor ptr
     110    unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> msgMap;
     111
     112    void insert( const StructDecl * decl, const StructDecl * otherDecl, unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map, FwdDeclData * data ) {
     113        auto iter = map.find( decl );
     114        if ( iter != map.end() ) { // if decl exists in map append data to existing inner map
     115            iter->second.emplace( make_pair( otherDecl, data ) );
     116        } else { // else create inner map for key
     117            map.emplace( make_pair( decl, unordered_map<const StructDecl *, FwdDeclData *>( { make_pair( otherDecl, data ) } ) ) );
     118        }
     119    }
     120
     121  public:
     122    // insert decl into table so that we can fwd declare it later (average cost: O(1))
     123    void insertDecl( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) {
     124        FwdDeclData * declToInsert = new FwdDeclData( actorDecl, msgDecl, fwdDecl );
     125        insert( actorDecl, msgDecl, actorMap, declToInsert );
     126        insert( msgDecl, actorDecl, msgMap, declToInsert );
     127    }
     128
     129    // returns list of decls to insert after current struct decl
     130    // Over the entire pass the runtime of this routine is O(r) where r is the # of receive routines
     131    list<FunctionDecl *> updateDecl( const StructDecl * decl, bool isMsg ) {
     132        unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map = isMsg ? msgMap : actorMap;
     133        unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & otherMap =  isMsg ? actorMap : msgMap;
     134        auto iter = map.find( decl );
     135        list<FunctionDecl *> toInsertAfter; // this is populated with decls that are ready to insert
     136        if ( iter == map.end() ) return toInsertAfter;
     137       
     138        // iterate over inner map
     139        unordered_map<const StructDecl *, FwdDeclData *> & currInnerMap = iter->second;
     140        for ( auto innerIter = currInnerMap.begin(); innerIter != currInnerMap.end(); ) {
     141            FwdDeclData * currentDatum = innerIter->second;
     142            bool readyToInsert = isMsg ? currentDatum->foundMsg() : currentDatum->foundActor();
     143            if ( ! readyToInsert ) { ++innerIter; continue; }
     144           
     145            // readyToInsert is true so we are good to insert the forward decl of the message fn
     146            toInsertAfter.push_back( currentDatum->fwdDecl );
     147
     148            // need to remove from other map before deleting
     149            // find inner map in other map ( other map is actor map if original is msg map and vice versa )
     150            const StructDecl * otherDecl = isMsg ? currentDatum->actorDecl : currentDatum->msgDecl;
     151            auto otherMapIter = otherMap.find( otherDecl );
     152
     153            unordered_map<const StructDecl *, FwdDeclData *> & otherInnerMap = otherMapIter->second;
     154
     155            // find the FwdDeclData we need to remove in the other inner map
     156            auto otherInnerIter = otherInnerMap.find( decl );
     157
     158            // remove references to deleted FwdDeclData from current inner map
     159            innerIter = currInnerMap.erase( innerIter ); // this does the increment so no explicit inc needed
     160
     161            // remove references to deleted FwdDeclData from other inner map
     162            otherInnerMap.erase( otherInnerIter );
     163           
     164            // if other inner map is now empty, remove key from other outer map
     165            if ( otherInnerMap.empty() )
     166                otherMap.erase( otherDecl );
     167
     168            // now we are safe to delete the FwdDeclData since we are done with it
     169            // and we have removed all references to it from our data structures
     170            delete currentDatum;
     171        }
     172
     173        // if current inner map is now empty, remove key from outer map.
     174        // Have to do this after iterating for safety
     175        if ( currInnerMap.empty() )
     176            map.erase( decl );
     177
     178        return toInsertAfter;
     179    }
     180};
     181
    68182struct GenReceiveDecls : public ast::WithDeclsToAdd<> {
    69     std::map<const StructDecl *, int> & actorStructDecls;
    70     std::map<const StructDecl *, int>  & messageStructDecls;
     183    unordered_set<const StructDecl *> & actorStructDecls;
     184    unordered_set<const StructDecl *>  & messageStructDecls;
    71185    const StructDecl ** requestDecl;
    72186    const EnumDecl ** allocationDecl;
    73187    const StructDecl ** actorDecl;
    74188    const StructDecl ** msgDecl;
    75     std::vector<FunctionDecl *> & forwardDecls;
     189    FwdDeclTable & forwardDecls;
    76190
    77191        void postvisit( const FunctionDecl * decl ) {
     
    90204
    91205        // If the struct instances are derived actor and message types then generate the message send routine
    92         if ( actorStructDecls.count( arg1InstType->aggr() ) && messageStructDecls.count( arg2InstType->aggr() ) ) {
     206        auto actorIter = actorStructDecls.find( arg1InstType->aggr() );
     207        auto messageIter = messageStructDecls.find( arg2InstType->aggr() );
     208        if ( actorIter != actorStructDecls.end() && messageIter != messageStructDecls.end() ) {
    93209
    94210            // check that we have found all the decls we need from <actor.hfa>
     
    225341           
    226342            // forward decls to resolve use before decl problem for '|' routines
    227             forwardDecls.push_back( ast::deepCopy( sendOperatorFunction ) );
     343            forwardDecls.insertDecl( *actorIter, *messageIter , ast::deepCopy( sendOperatorFunction ) );
     344            // forwardDecls.push_back( ast::deepCopy( sendOperatorFunction ) );
    228345
    229346            sendOperatorFunction->stmts = sendBody;
     
    233350
    234351  public:
    235     GenReceiveDecls( std::map<const StructDecl *, int> & actorStructDecls, std::map<const StructDecl *, int> & messageStructDecls,
     352    GenReceiveDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
    236353        const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl,
    237         std::vector<FunctionDecl *> & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
     354        FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
    238355        requestDecl(requestDecl), allocationDecl(allocationDecl), actorDecl(actorDecl), msgDecl(msgDecl), forwardDecls(forwardDecls) {}
    239356};
    240357
    241358struct GenFwdDecls : public ast::WithDeclsToAdd<> {
    242     std::map<const StructDecl *, int> & actorStructDecls;
    243     std::map<const StructDecl *, int>  & messageStructDecls;
    244     std::vector<FunctionDecl *> & forwardDecls;
    245     bool done;
    246 
    247     void postvisit( const FunctionDecl * decl ) {
    248         if ( done ) return;
    249         // return if not of the form receive( param1, param2 ) or if it is a forward decl
    250         if ( decl->name != "receive" || decl->params.size() != 2 || !decl->stmts ) return;
    251 
    252         // the params should be references
    253         const ReferenceType * derivedActorRef = dynamic_cast<const ReferenceType *>(decl->params.at(0)->get_type());
    254         const ReferenceType * derivedMsgRef = dynamic_cast<const ReferenceType *>(decl->params.at(1)->get_type());
    255         if ( !derivedActorRef || !derivedMsgRef ) return;
    256 
    257         // the references should be to struct instances
    258         const StructInstType * arg1InstType = dynamic_cast<const StructInstType *>(derivedActorRef->base.get());
    259         const StructInstType * arg2InstType = dynamic_cast<const StructInstType *>(derivedMsgRef->base.get());
    260         if ( !arg1InstType || !arg2InstType ) return;
    261 
    262         // If the struct instances are derived actor and message types then generate the message send routine
    263         if ( actorStructDecls.count( arg1InstType->aggr() ) && messageStructDecls.count( arg2InstType->aggr() ) ) {
    264             done = true;
    265             for ( const auto & func : forwardDecls ) {
    266                 declsToAddBefore.push_back( func );
    267             }
     359    unordered_set<const StructDecl *> & actorStructDecls;
     360    unordered_set<const StructDecl *>  & messageStructDecls;
     361    FwdDeclTable & forwardDecls;
     362
     363    void postvisit( const StructDecl * decl ) {
     364        list<FunctionDecl *> toAddAfter;
     365        auto actorIter = actorStructDecls.find( decl );
     366        if ( actorIter != actorStructDecls.end() ) { // this is a derived actor decl
     367            // get list of fwd decls that we can now insert
     368            toAddAfter = forwardDecls.updateDecl( decl, false );
     369
     370            // get rid of decl from actorStructDecls since we no longer need it
     371            actorStructDecls.erase( actorIter );
     372        } else {
     373            auto messageIter = messageStructDecls.find( decl );
     374            if ( messageIter == messageStructDecls.end() ) return;
     375
     376            toAddAfter = forwardDecls.updateDecl( decl, true );
     377
     378            // get rid of decl from messageStructDecls since we no longer need it
     379            messageStructDecls.erase( messageIter );
     380        }
     381
     382        // add the fwd decls to declsToAddAfter
     383        for ( FunctionDecl * func : toAddAfter ) {
     384            declsToAddAfter.push_back( func );
    268385        }
    269386    }
    270387
    271388  public:
    272     GenFwdDecls( std::map<const StructDecl *, int> & actorStructDecls, std::map<const StructDecl *, int> & messageStructDecls,
    273         std::vector<FunctionDecl *> & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
    274         forwardDecls(forwardDecls), done(false) {}
     389    GenFwdDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
     390        FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
     391        forwardDecls(forwardDecls) {}
    275392};
    276393
    277394void implementActors( TranslationUnit & translationUnit ) {
    278     // maps to collect all derived actor and message types
    279     std::map<const StructDecl *, int> actorStructDecls;
    280     std::map<const StructDecl *, int> messageStructDecls;
    281     std::vector<FunctionDecl *> forwardDecls;
     395    // unordered_maps to collect all derived actor and message types
     396    unordered_set<const StructDecl *> actorStructDecls;
     397    unordered_set<const StructDecl *> messageStructDecls;
     398    FwdDeclTable forwardDecls;
    282399
    283400    // for storing through the passes
  • tests/concurrent/actors/types.cfa

    r7a24d76 r03936530  
    55#include <stdio.h>
    66#include <mutex_stmt.hfa>
     7
     8struct dummy_actor { actor a; }; // this won't work since the actor isn't inlined
    79
    810struct derived_actor {
     
    2628}
    2729
     30Allocation receive( derived_actor & receiver, d_msg & msg ) {
     31    return receive( receiver, msg.num );
     32}
     33
    2834struct derived_actor2 {
     35    struct nested { int i; }; // testing nested before inline
    2936    inline actor;
    3037};
    3138static inline void ?{}( derived_actor2 & this ) { ((actor &)this){}; }
     39
     40Allocation receive( derived_actor2 & receiver, d_msg & msg ) {
     41    mutex(sout) sout | msg.num;
     42    return Finished;
     43}
    3244
    3345struct derived_actor3 {
     
    4153};
    4254static inline void ?{}( d_msg2 & this ) { ((message &)this){}; }
    43 
    44 Allocation receive( derived_actor2 & receiver, d_msg & msg ) {
    45     mutex(sout) sout | msg.num;
    46     return Finished;
    47 }
    48 
    49 Allocation receive( derived_actor & receiver, d_msg & msg ) {
    50     return receive( receiver, msg.num );
    51 }
    5255
    5356Allocation receive( derived_actor3 & receiver, d_msg & msg ) {
Note: See TracChangeset for help on using the changeset viewer.