About
User Reference
C++ API
luafaudes
Developer
Links
libFAUDES online
libFAUDES

Sections

Index

sp_pexecutor.cpp

Go 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.20s --- 2011.10.12 --- c++ source docu by doxygen