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