Changes in / [7a24d76:03936530]
- Files:
-
- 2 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/actor.hfa
r7a24d76 r03936530 1 #pragma once 2 1 3 #include <locks.hfa> 2 4 #include <limits.hfa> 3 5 #include <list.hfa> 6 #include <kernel.hfa> 4 7 5 8 #ifdef __CFA_DEBUG__ -
src/Concurrency/Actors.cpp
r7a24d76 r03936530 21 21 #include "AST/TranslationUnit.hpp" 22 22 #include "AST/Expr.hpp" 23 #include <algorithm> 23 24 using namespace ast; 25 using namespace std; 24 26 25 27 namespace Concurrency { 26 28 27 29 struct 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; 30 32 const StructDecl ** requestDecl; 31 33 const EnumDecl ** allocationDecl; … … 34 36 StructDecl * parentDecl; 35 37 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 37 41 void previsit( const EnumDecl * decl ) { 38 42 if( decl->name == "Allocation" ) *allocationDecl = decl; 39 43 } 40 44 45 // finds and sets a ptr to the actor, message, and request structs, which are needed in the next pass 41 46 void previsit( const StructDecl * decl ) { 42 47 GuardValue(insideStruct); … … 45 50 if( decl->name == "actor" ) *actorDecl = decl; 46 51 if( decl->name == "message" ) *msgDecl = decl; 47 if( decl->name == "request" ) *requestDecl = decl; 52 if( decl->name == "request" ) *requestDecl = decl; 48 53 } 49 54 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 50 67 void postvisit( const StructInstType * node ) { 51 68 if ( ! *actorDecl || ! *msgDecl ) return; 52 if ( insideStruct ) {69 if ( insideStruct && !namedDecl ) { 53 70 if ( node->aggr() == *actorDecl ) { 54 actorStructDecls.insert( {parentDecl, 1});71 actorStructDecls.insert( parentDecl ); 55 72 } else if ( node->aggr() == *msgDecl ) { 56 messageStructDecls.insert( {parentDecl, 1});73 messageStructDecls.insert( parentDecl ); 57 74 } 58 75 } … … 60 77 61 78 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, 63 80 const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl ) 64 81 : actorStructDecls( actorStructDecls ), messageStructDecls( messageStructDecls ), requestDecl( requestDecl ), … … 66 83 }; 67 84 85 // keeps track of all fwdDecls of message routines so that we can hoist them to right after the appropriate decls 86 class 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 68 182 struct 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; 71 185 const StructDecl ** requestDecl; 72 186 const EnumDecl ** allocationDecl; 73 187 const StructDecl ** actorDecl; 74 188 const StructDecl ** msgDecl; 75 std::vector<FunctionDecl *>& forwardDecls;189 FwdDeclTable & forwardDecls; 76 190 77 191 void postvisit( const FunctionDecl * decl ) { … … 90 204 91 205 // 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() ) { 93 209 94 210 // check that we have found all the decls we need from <actor.hfa> … … 225 341 226 342 // 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 ) ); 228 345 229 346 sendOperatorFunction->stmts = sendBody; … … 233 350 234 351 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, 236 353 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), 238 355 requestDecl(requestDecl), allocationDecl(allocationDecl), actorDecl(actorDecl), msgDecl(msgDecl), forwardDecls(forwardDecls) {} 239 356 }; 240 357 241 358 struct 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 forwarddecl250 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 instances258 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 routine263 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 ); 268 385 } 269 386 } 270 387 271 388 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) {} 275 392 }; 276 393 277 394 void implementActors( TranslationUnit & translationUnit ) { 278 // maps to collect all derived actor and message types279 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; 282 399 283 400 // for storing through the passes -
tests/concurrent/actors/types.cfa
r7a24d76 r03936530 5 5 #include <stdio.h> 6 6 #include <mutex_stmt.hfa> 7 8 struct dummy_actor { actor a; }; // this won't work since the actor isn't inlined 7 9 8 10 struct derived_actor { … … 26 28 } 27 29 30 Allocation receive( derived_actor & receiver, d_msg & msg ) { 31 return receive( receiver, msg.num ); 32 } 33 28 34 struct derived_actor2 { 35 struct nested { int i; }; // testing nested before inline 29 36 inline actor; 30 37 }; 31 38 static inline void ?{}( derived_actor2 & this ) { ((actor &)this){}; } 39 40 Allocation receive( derived_actor2 & receiver, d_msg & msg ) { 41 mutex(sout) sout | msg.num; 42 return Finished; 43 } 32 44 33 45 struct derived_actor3 { … … 41 53 }; 42 54 static 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 }52 55 53 56 Allocation receive( derived_actor3 & receiver, d_msg & msg ) {
Note:
See TracChangeset
for help on using the changeset viewer.