libFAUDES
Sections
Index
|
sp_pexecutor.cppGo to the documentation of this file.00001 /** @file sp_pexecutor.cpp Executor for multiple synchronized timed generators */ 00002 00003 /* 00004 FAU Discrete Event Systems Library (libfaudes) 00005 00006 Copyright (C) 2007, 2008 Thomas Moor 00007 Copyright (C) 2007 Ruediger Berndt 00008 Exclusive copyright is granted to Klaus Schmidt 00009 00010 */ 00011 00012 00013 #include "sp_pexecutor.h" 00014 00015 namespace faudes { 00016 00017 00018 // std faudes type 00019 FAUDES_TYPE_IMPLEMENTATION(ParallelExecutor,ParallelExecutor,Type) 00020 00021 // ParallelExecutor(void) 00022 ParallelExecutor::ParallelExecutor(void) : Type() { 00023 FD_DX("ParallelExecutor(" << this << ")::ParallelExecutor()"); 00024 } 00025 00026 // ParallelExecutor(other) 00027 ParallelExecutor::ParallelExecutor(const ParallelExecutor& rOther) : Type() { 00028 FD_DX("ParallelExecutor(" << this << ")::ParallelExecutor(other)"); 00029 Assign(rOther); 00030 } 00031 00032 // ParallelExecutor(rFileName) 00033 ParallelExecutor::ParallelExecutor(const std::string& rFileName) : Type() { 00034 FD_DX("ParallelExecutor(" << this << ")::ParallelExecutor(" << rFileName << ")"); 00035 Read(rFileName); 00036 } 00037 00038 // ParallelExecutor(void) 00039 ParallelExecutor::~ParallelExecutor(void) { 00040 FD_DX("ParallelExecutor(" << this << ")::~ParallelExecutor()"); 00041 } 00042 00043 // DoAssign(other) 00044 void ParallelExecutor::DoAssign(const ParallelExecutor& rOther) { 00045 FD_DX("ParallelExecutor(" << this << ")::DoAssign(other)"); 00046 mExecutors=rOther.mExecutors; 00047 mExecutorNames=rOther.mExecutorNames; 00048 Compile(); 00049 } 00050 00051 //UpdateParallelTimedState() 00052 void ParallelExecutor::UpdateParallelTimedState(void) { 00053 mCurrentParallelTimedState.State.clear(); 00054 mCurrentParallelTimedState.Clock.clear(); 00055 for(Iterator xit=Begin(); xit!=End(); xit++){ 00056 mCurrentParallelTimedState.State.push_back(xit->CurrentTimedState().State); 00057 mCurrentParallelTimedState.Clock.push_back(xit->CurrentTimedState().ClockValue); 00058 } 00059 } 00060 00061 // Compile() 00062 void ParallelExecutor::Compile(void) { 00063 iterator xit; 00064 FD_DX("ParallelExecutor(" << this << ")::Compile(): with #" << Size() << " generators"); 00065 // reset executors, incl compile 00066 for(xit=mExecutors.begin(); xit!=mExecutors.end(); xit++) 00067 xit->Reset(); 00068 // update state 00069 UpdateParallelTimedState(); 00070 // compute alphabet 00071 mAlphabet.Clear(); 00072 mAlphabet.Name("Alphabet"); 00073 for(xit=mExecutors.begin(); xit!=mExecutors.end(); xit++) 00074 mAlphabet.InsertSet(xit->Generator().Alphabet()); 00075 // reset other members 00076 mCurrentTime=0; 00077 mCurrentStep=0; 00078 mRecentEvent=0; 00079 mEValid=false; 00080 FD_DX("ParallelExecutor(" << this << ")::Compile(): done"); 00081 } 00082 00083 // Reset() 00084 void ParallelExecutor::Reset(void) { 00085 FD_DX("ParallelExecutor(" << this << ")::Reset()"); 00086 // compile includes reset 00087 Compile(); 00088 } 00089 00090 // Insert(rFileName) 00091 void ParallelExecutor::Insert(const std::string& rFileName) { 00092 FD_DX("ParallelExecutor(" << this << ")::Insert(" << rFileName << ")" ); 00093 TokenReader tr(rFileName); 00094 // create executor and read generator 00095 mExecutors.push_back(Executor()); 00096 mExecutorNames.push_back(rFileName); 00097 // read generator 00098 mExecutors.back().Read(tr); 00099 FD_DX("ParallelExecutor(" << this << ")::Insert(" << rFileName 00100 << "): found " << mExecutors.back().Name()); 00101 // compile (incl check determinism) 00102 Compile(); 00103 } 00104 00105 // Insert(rGen) 00106 void ParallelExecutor::Insert(const TimedGenerator& rGen) { 00107 FD_DX("ParallelExecutor(" << this << ")::Insert(rGen): " << rGen.Name() << " at #" << Size()); 00108 mExecutors.push_back(Executor(rGen)); 00109 mExecutorNames.push_back(""); 00110 // compile (incl check determinism) 00111 Compile(); 00112 } 00113 00114 // Clear() 00115 void ParallelExecutor::Clear(void) { 00116 FD_DX("ParallelExecutor(" << this << ")::Clear()"); 00117 mExecutors.clear(); 00118 mExecutorNames.clear(); 00119 Compile(); 00120 } 00121 00122 // Size() 00123 Idx ParallelExecutor::Size(void) const { 00124 return (Idx) mExecutors.size(); 00125 } 00126 00127 00128 00129 //DoWrite(rTr,rLabel) 00130 void ParallelExecutor::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const { 00131 (void) pContext; 00132 std::string label=rLabel; 00133 if(label=="") label = "Executor"; 00134 rTw.WriteBegin(label); 00135 DoWriteGenerators(rTw); 00136 rTw.WriteEnd(label); 00137 } 00138 00139 //DoWriteGenerators(rTr,rLabel) 00140 void ParallelExecutor::DoWriteGenerators(TokenWriter& rTw) const { 00141 rTw.WriteBegin("Generators"); 00142 for(Idx i=0; i<Size(); i++) { 00143 // write filename 00144 if(mExecutorNames.at(i)!="") { 00145 rTw.WriteString(mExecutorNames.at(i)); 00146 } 00147 // write generator 00148 if(mExecutorNames.at(i)=="") { 00149 mExecutors.at(i).Write(rTw); 00150 } 00151 } 00152 rTw.WriteEnd("Generators"); 00153 } 00154 00155 //DoRead(rTr,rLabel) 00156 void ParallelExecutor::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) { 00157 (void) pContext; 00158 // report 00159 FD_DX("ParallelExecutor(" << this << ")::DoRead(tr, " << rLabel << ")"); 00160 // get my section 00161 std::string label=rLabel; 00162 if(label=="") label = "Executor"; 00163 // read section 00164 rTr.ReadBegin(label); 00165 // read generators 00166 DoReadGenerators(rTr); 00167 // done 00168 rTr.ReadEnd(label); 00169 // reset 00170 Reset(); 00171 } 00172 00173 00174 //DoReadGenerators(rTr,rLabel) 00175 void ParallelExecutor::DoReadGenerators(TokenReader& rTr) { 00176 // get relevant directory 00177 std::string dirname=""; 00178 if(rTr.SourceMode()==TokenReader::File) 00179 dirname=ExtractDirectory(rTr.FileName()); 00180 // report 00181 FD_DX("ParallelExecutor(" << this << ")::DoReadGenerators(tr): dirname " << dirname); 00182 // read section 00183 rTr.ReadBegin("Generators"); 00184 Token token; 00185 while(!rTr.Eos("Generators")) { 00186 rTr.Peek(token); 00187 // is it a file name? 00188 if(token.Type()==Token::String) { 00189 Insert(PrependDirectory(dirname,token.StringValue())); 00190 rTr.Get(token); 00191 continue; 00192 } 00193 // is it a generator? 00194 if(token.Type()==Token::Begin) 00195 if(token.StringValue()=="Generator") { 00196 TimedGenerator gen; 00197 gen.Read(rTr); 00198 Insert(gen); 00199 continue; 00200 } 00201 // else report error 00202 std::stringstream errstr; 00203 errstr << "Invalid token" << rTr.FileLine(); 00204 throw Exception("ParallelExecutor::DoReadGenerators", errstr.str(), 502); 00205 } 00206 rTr.ReadEnd("Generators"); 00207 } 00208 00209 // Alphabet() 00210 const EventSet& ParallelExecutor::Alphabet(void) const { 00211 return mAlphabet; 00212 } 00213 00214 // ComputeEnabled() fake const 00215 void ParallelExecutor::ComputeEnabled(void) const { 00216 ParallelExecutor* fakeconst = const_cast<ParallelExecutor*>(this); 00217 fakeconst->ComputeEnabledNonConst(); 00218 } 00219 00220 // ComputeEnabled() 00221 void ParallelExecutor::ComputeEnabledNonConst(void) { 00222 iterator xit; 00223 // compute members (may remove this) 00224 FD_DX("ParallelExecutor(" << this << ")::ComputeEnabled(): members"); 00225 for(xit=mExecutors.begin(); xit != mExecutors.end(); xit++) 00226 xit->IsDeadlocked(); 00227 // compute etime 00228 FD_DX("ParallelExecutor(" << this << ")::ComputeEnabled(): time"); 00229 mETime.SetPositive(); 00230 for(xit=mExecutors.begin(); xit != mExecutors.end(); xit++) 00231 mETime.Intersect(xit->EnabledTime()); 00232 // compute e/d events 00233 FD_DX("ParallelExecutor(" << this << ")::ComputeEnabled(): e/d events"); 00234 mDEvents.Name("DisabledEvents"); 00235 mDEvents.Clear(); 00236 for(xit=mExecutors.begin(); xit != mExecutors.end(); xit++) 00237 mDEvents.InsertSet(xit->DisabledEvents()); 00238 mEEvents=mAlphabet; 00239 mEEvents.Name("EnabledEvents"); 00240 mEEvents.EraseSet(mDEvents); 00241 // compute einterval // TODO: this is conservative 00242 FD_DX("ParallelExecutor(" << this << ")::ComputeEnabled(): interval"); 00243 mEInterval.SetPositive(); 00244 for(xit=mExecutors.begin(); xit != mExecutors.end(); xit++) 00245 mEInterval.Intersect(xit->EnabledInterval()); 00246 // done 00247 mEValid=true; 00248 } 00249 00250 // EnabledTime(void) 00251 const TimeInterval& ParallelExecutor::EnabledTime(void) const { 00252 if(!mEValid) ComputeEnabled(); 00253 return mETime; 00254 00255 } 00256 00257 // EnabledEvents(void) 00258 const EventSet& ParallelExecutor::EnabledEvents(void) const { 00259 if(!mEValid) ComputeEnabled(); 00260 return mEEvents; 00261 } 00262 00263 // DisabledEvents(void) 00264 const EventSet& ParallelExecutor::DisabledEvents(void) const { 00265 if(!mEValid) ComputeEnabled(); 00266 return mDEvents; 00267 } 00268 00269 // EnabledInterval(void) 00270 const TimeInterval& ParallelExecutor::EnabledInterval(void) const { 00271 if(!mEValid) ComputeEnabled(); 00272 return mEInterval; 00273 } 00274 00275 // EnabledEventInterval(event) 00276 TimeInterval ParallelExecutor::EnabledEventTime(Idx event) const { 00277 TimeInterval retInterval; 00278 retInterval.SetPositive(); 00279 Iterator xit; 00280 for(xit=Begin(); xit != End(); xit++){ 00281 retInterval.Intersect(xit->EnabledEventTime(event)); 00282 } 00283 FD_DX("ParalelExecutor(" << this << ")::EnabledEventTime(" << event << "):"<< retInterval.Str()); 00284 return retInterval; 00285 } 00286 00287 // EnabledGuardInterval(event) 00288 TimeInterval ParallelExecutor::EnabledGuardTime(Idx event) const { 00289 TimeInterval retInterval; 00290 retInterval.SetPositive(); 00291 Iterator xit; 00292 for(xit=Begin(); xit != End(); xit++){ 00293 retInterval.Intersect(xit->EnabledGuardTime(event)); 00294 } 00295 FD_DX("ParalelExecutor(" << this << ")::EnabledGuardTime(" << event << "):"<< retInterval.Str()); 00296 return retInterval; 00297 } 00298 00299 //GetCurrentStateVec 00300 const ParallelExecutor::ParallelState& ParallelExecutor::CurrentParallelState(void) const { 00301 return mCurrentParallelTimedState.State; 00302 } 00303 00304 // get current state 00305 const ParallelExecutor::ParallelTimedState& ParallelExecutor::CurrentParallelTimedState(void) const { 00306 return mCurrentParallelTimedState; 00307 } 00308 00309 // set current state 00310 bool ParallelExecutor::CurrentParallelTimedState(const ParallelTimedState& ptstate) { 00311 FD_DX("ParalelExecutor(" << this << ")::CurrentParallelState(ptstate): set " << PTSStr(ptstate)); 00312 // prepare 00313 if(ptstate.State.size()!=Size()) return false; 00314 if(ptstate.Clock.size()!=Size()) return false; 00315 bool res=true; 00316 ParallelTimedState oldstate=CurrentParallelTimedState(); 00317 // loop and set for all executors 00318 int i=0; 00319 for(iterator xit=mExecutors.begin(); xit!=mExecutors.end(); xit++, i++){ 00320 TimedState tstate; 00321 tstate.State=ptstate.State[i]; 00322 tstate.ClockValue=ptstate.Clock[i]; 00323 res = res && xit->CurrentTimedState(tstate); 00324 } 00325 // reject 00326 if(!res) { 00327 ParallelExecutor::CurrentParallelTimedState(oldstate); 00328 return false; 00329 } 00330 // reset time (dont call the virtual fncts here) 00331 ParallelExecutor::CurrentTime(0); 00332 ParallelExecutor::CurrentStep(0); 00333 // fix state rep 00334 UpdateParallelTimedState(); 00335 // invalidate 00336 mEValid=false; 00337 mRecentEvent=0; 00338 FD_DX("ParalelExecutor(" << this << ")::CurrentParallelState(ptstate): done"); 00339 return true; 00340 } 00341 00342 00343 00344 // ExecuteTime(time) 00345 bool ParallelExecutor::ExecuteTime(tpTime::Type time) { 00346 if(mCurrentTime>=tpTime::Max) return false; 00347 if(time==0) return true; 00348 if(!mEValid) ComputeEnabled(); 00349 if(!mETime.In(time) && !((time==tpTime::Max) && mETime.UBinf()) ) { 00350 FD_DX("ParalelExecutor(" << this << ")::ExecuteTime(time): execution of " << time 00351 << " conflicts with enabled status " ); 00352 return false; 00353 } 00354 // progress current time 00355 mCurrentTime += time; 00356 // fix infinity 00357 if(time==tpTime::Max) mCurrentTime=tpTime::Max; 00358 // progress members 00359 bool success=true; 00360 for(iterator xit=mExecutors.begin(); xit != mExecutors.end(); xit++) 00361 success &= xit->ExecuteTime(time); 00362 // update state 00363 UpdateParallelTimedState(); 00364 // indicate invalid (conservative) 00365 mEValid=false; 00366 return success; 00367 } 00368 00369 // ExecuteEvent(event) 00370 bool ParallelExecutor::ExecuteEvent(Idx event) { 00371 if(!mEValid) ComputeEnabled(); 00372 if(!mEEvents.Exists(event)) { 00373 FD_DX("ParallelExecutor(" << this << ")::ExecuteEvent(): execution of event " << EStr(event) 00374 << " conflicts with enabled status " ); 00375 return false; 00376 } 00377 // progress members 00378 bool success=true; 00379 for(iterator xit=mExecutors.begin(); xit != mExecutors.end(); xit++) 00380 if(xit->Generator().ExistsEvent(event)) 00381 success &= xit->ExecuteEvent(event); 00382 if(!success) { 00383 // should throw exception 00384 FD_DX("ParallelExecutor(" << this << ")::ExecuteEvent(): execution of event " << EStr(event) 00385 << " conflicts with internal state data " ); 00386 return false; 00387 } 00388 // progress current time 00389 mCurrentStep += 1; 00390 // update state 00391 UpdateParallelTimedState(); 00392 // record event 00393 mRecentEvent=event; 00394 // invalidate 00395 mEValid=false; 00396 return true; 00397 } 00398 00399 // CurrentTime(time) 00400 void ParallelExecutor::CurrentTime(tpTime::Type time) { 00401 mCurrentTime=time; 00402 for(iterator xit=mExecutors.begin(); xit != mExecutors.end(); xit++) 00403 xit->CurrentTime(time); 00404 mEValid=false; 00405 } 00406 00407 // CurrentTime() 00408 tpTime::Type ParallelExecutor::CurrentTime(void) const { 00409 return mCurrentTime; 00410 } 00411 00412 // CurrentStep(step) 00413 void ParallelExecutor::CurrentStep(int step) { 00414 mCurrentStep=step; 00415 for(iterator xit=mExecutors.begin(); xit != mExecutors.end(); xit++) 00416 xit->CurrentStep(0); 00417 mEValid=false; 00418 } 00419 00420 // CurrentStep() 00421 int ParallelExecutor::CurrentStep(void) const { 00422 return mCurrentStep; 00423 } 00424 00425 // IsDeadlocked() 00426 bool ParallelExecutor::IsDeadlocked(void) const { 00427 if(!mEValid) ComputeEnabled(); 00428 if(!mEEvents.Empty()) return false; 00429 if(!(mETime.UB()<=0)) return false; 00430 return true; 00431 } 00432 00433 // PTSStr(ptstate) 00434 std::string ParallelExecutor::PTSStr(const ParallelTimedState& ptstate) const { 00435 if(Size()!=ptstate.State.size()) return("(undef)"); 00436 std::stringstream res; 00437 res << "(state "; 00438 for(unsigned int i=0; i< Size(); i++){ 00439 res << mExecutors[i].Generator().SStr(ptstate.State[i]); 00440 if(i+1<Size()) res << " x "; 00441 } 00442 res << ") (clocks ("; 00443 for(unsigned int i=0; i< Size(); i++){ 00444 const Executor* execp=&mExecutors[i]; 00445 ClockSet::Iterator cit; 00446 for(cit=execp->Generator().ClocksBegin();cit!=execp->Generator().ClocksEnd();cit++){ 00447 if(cit!=execp->Generator().ClocksBegin()) res << " "; 00448 res << CStr(*cit) << "="; 00449 std::map<Idx,tpTime::Type>::const_iterator cvit=ptstate.Clock[i].find(*cit); 00450 if(cvit!=ptstate.Clock[i].end()) res << cvit->second; 00451 else res << "undef"; 00452 } 00453 res<<")"; 00454 if(i+1<Size()) res << " x ("; 00455 } 00456 res << ")"; 00457 return res.str(); 00458 } 00459 00460 // PSStr(pstate) 00461 std::string ParallelExecutor::PSStr(const ParallelState& pstate) const { 00462 if(Size()!=pstate.size()) return("(undef)"); 00463 std::stringstream res; 00464 res << "(state "; 00465 for(unsigned int i=0; i< Size(); i++){ 00466 res << mExecutors[i].Generator().SStr(pstate[i]); 00467 if(i+1<Size()) res << " x "; 00468 } 00469 res << ")"; 00470 return res.str(); 00471 } 00472 00473 // TEStr(tevent) 00474 std::string ParallelExecutor::TEStr(const TimedEvent& tevent) const { 00475 if(Size()==0) return "(undef)"; 00476 return Begin()->TEStr(tevent); 00477 } 00478 00479 // EStr(event) 00480 std::string ParallelExecutor::EStr(Idx event) const { 00481 if(Size()==0) return "(undef)"; 00482 return Begin()->EStr(event); 00483 } 00484 00485 // CStr(clock) 00486 std::string ParallelExecutor::CStr(Idx clock) const { 00487 if(Size()==0) return "(undef)"; 00488 return Begin()->CStr(clock); 00489 } 00490 00491 // CurrentParallelTimedStateStr() 00492 std::string ParallelExecutor::CurrentParallelTimedStateStr(void) const { 00493 return PTSStr(mCurrentParallelTimedState); 00494 } 00495 00496 // CurrentParallelTimedStateStr() 00497 std::string ParallelExecutor::CurrentParallelStateStr(void) const { 00498 return PSStr(mCurrentParallelTimedState.State); 00499 } 00500 00501 //ActiveEventSet 00502 EventSet ParallelExecutor::ActiveEventSet(const ParallelState& stateVec) const { 00503 EventSet retEventSet=Alphabet(); 00504 Iterator xit; 00505 int i; 00506 for(i=0, xit=Begin(); xit!=End(); xit++, i++) { 00507 retEventSet.EraseSet( xit->Generator().Alphabet() - xit->Generator().ActiveEventSet(stateVec[i])); 00508 } 00509 return retEventSet; 00510 } 00511 00512 //Active(Idx) 00513 bool ParallelExecutor::Active(Idx ev) const{ 00514 return Active(ev, mCurrentParallelTimedState.State); 00515 } 00516 00517 //Active(Idx, ParallelState) 00518 bool ParallelExecutor::Active(Idx ev, const ParallelState& stateVec) const { 00519 Iterator xit; 00520 int i; 00521 for(xit=Begin(), i=0; xit!=End(); ++xit, i++){ 00522 if(xit->Generator().Alphabet().Exists(ev)) 00523 if(xit->Generator().TransRelBegin(stateVec[i],ev) 00524 == xit->Generator().TransRelEnd(stateVec[i],ev)) 00525 return false; 00526 } 00527 return true; 00528 } 00529 00530 00531 //DoWrite(rTr,rLabel,pContext) 00532 void ParallelExecutor::ParallelTimedState::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const { 00533 // allow for two versions only 00534 std::string label=rLabel; 00535 if(label!="DiscreteState") 00536 if(label!="TimedState") 00537 label="TimedState"; 00538 FD_DC("ParallelExecutor::ParallelTimedState::DoWrite(): section " << rLabel << " context " << pContext); 00539 // figure context 00540 const ParallelExecutor* exe=dynamic_cast<const ParallelExecutor*>(pContext); 00541 if(exe) if(exe->Size()!=State.size()) exe=0; 00542 if(exe) if(exe->Size()!=Clock.size()) exe=0; 00543 // do write 00544 if(rLabel=="TimedState") rTw.WriteBegin("TimedState"); 00545 // discrete state 00546 rTw.WriteBegin("DiscreteState"); 00547 for(unsigned int i=0; i< State.size(); i++) { 00548 std::string name=""; 00549 if(exe) name=exe->At(i).StateName(State.at(i)); 00550 if(name!="") rTw.WriteString(name); 00551 else rTw.WriteInteger(State.at(i)); 00552 }; 00553 rTw.WriteEnd("DiscreteState"); 00554 // figure whether to write clocks 00555 bool doclocks=false; 00556 if(rLabel=="TimedState") 00557 for(unsigned int i=0; i< Clock.size(); i++) 00558 if(Clock.at(i).size()>0) doclocks=true; 00559 // write clocks 00560 if(doclocks) { 00561 rTw.WriteBegin("ClockMaps"); 00562 for(unsigned int i=0; i< Clock.size(); i++) { 00563 rTw.WriteBegin("ClockMap"); 00564 std::map<Idx,tpTime::Type>::const_iterator cit; 00565 for(cit=Clock.at(i).begin(); cit!=Clock.at(i).end(); cit++) { 00566 std::string name=""; 00567 if(exe) name=exe->At(i).Generator().ClockName(cit->first); 00568 if(name!="") rTw.WriteString(name); 00569 else rTw.WriteInteger(cit->first); 00570 rTw.WriteInteger(cit->second); 00571 } 00572 rTw.WriteEnd("ClockMap"); 00573 } 00574 rTw.WriteEnd("ClockMaps"); 00575 } 00576 // do write end 00577 if(rLabel=="TimedState") rTw.WriteEnd("TimedState"); 00578 } 00579 00580 //DoRead(rTr,rLabel,pContext) 00581 void ParallelExecutor::ParallelTimedState::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) { 00582 (void) rLabel; (void) pContext; (void) rTr; 00583 FD_DC("ParallelExecutor::ParallelTimedState::DoRead()"); 00584 } 00585 00586 00587 } // namespace faudes 00588 00589 |
libFAUDES 2.22k --- 2013.04.02 --- c++ source docu by doxygen