sp_dplpexecutor.cpp

Go to the documentation of this file.
00001 /** @file sp_dplpexecutor.cpp Executor with IO device  */
00002 
00003 /* 
00004    FAU Discrete Event Systems Library (libfaudes)
00005 
00006    Copyright (C) 2008  Thomas Moor
00007 
00008 */
00009 
00010 
00011 // load configuration
00012 #include "corefaudes.h"
00013 
00014 
00015 #include "sp_dplpexecutor.h"
00016 #include <iostream>
00017 
00018 namespace faudes {
00019 
00020 // std faudes type
00021 FAUDES_TYPE_IMPLEMENTATION(DeviceExecutor,DeviceExecutor,LoggingExecutor)
00022 
00023 // constructor
00024 DeviceExecutor::DeviceExecutor(void) : ProposingExecutor() , pDevice(0) { 
00025   mMaxSyncGap=10*tpTime::Step;
00026   mSyncMode=0x0;
00027 }
00028 
00029 // constructor
00030 DeviceExecutor::DeviceExecutor(const DeviceExecutor& rOther) : ProposingExecutor() , pDevice(0) { 
00031   mMaxSyncGap=10*tpTime::Step;
00032   mSyncMode=0x0;
00033   DoAssign(rOther);
00034 }
00035 
00036 // destructor
00037 DeviceExecutor::~DeviceExecutor(void) { 
00038 }
00039 
00040 
00041 
00042 // DoAssign(other)
00043 void DeviceExecutor::DoAssign(const DeviceExecutor& rOther) {
00044   FD_DX("LoggingExecutor(" << this << ")::DoAssign(other)");
00045   // my members
00046   Devicep(NULL);
00047   // base
00048   ProposingExecutor::DoAssign(rOther);
00049 }
00050 
00051 // set io device
00052 void DeviceExecutor::Devicep(vDevice* dev) {
00053   pDevice=dev;
00054   mSyncError=false;
00055 #ifdef FAUDES_PLUGIN_IODEVICE
00056   if(!dev) return;
00057   pDevice->Reset();
00058 #endif
00059 }
00060 
00061 // reset the device
00062 void DeviceExecutor::DeviceReset(void) {
00063 #ifdef FAUDES_PLUGIN_IODEVICE
00064   if(!pDevice) return;
00065   pDevice->Reset();
00066 #endif
00067 }
00068 
00069 // start the device
00070 void DeviceExecutor::DeviceStart(void) {
00071 #ifdef FAUDES_PLUGIN_IODEVICE
00072   if(!pDevice) return;
00073   pDevice->Start();
00074 #endif
00075 }
00076 
00077 // stop the device
00078 void DeviceExecutor::DeviceStop(void) {
00079 #ifdef FAUDES_PLUGIN_IODEVICE
00080   if(!pDevice) return;
00081   pDevice->Stop();
00082 #endif
00083 }
00084 
00085 // clear static data
00086 void DeviceExecutor::Clear(void){
00087   Reset();
00088   ProposingExecutor::Clear();
00089 }
00090 
00091 // clear dynamic data
00092 void DeviceExecutor::Reset(long int seed){
00093   FD_DS("DeviceExecutor::Reset()");
00094 #ifdef FAUDES_PLUGIN_IODEVICE
00095   // reset the device
00096   if(pDevice) 
00097      pDevice->Reset();
00098   // overwrite input attributes 
00099   if(pDevice) {
00100     SimPriorityEventAttribute neverpa;
00101     neverpa.mPriority=-9999; // todo: have a never-priority                
00102     SimEventAttribute never;
00103     never.Priority(neverpa);
00104     EventSet::Iterator eit=pDevice->Inputs().Begin();
00105     for(;eit!=pDevice->Inputs().End(); eit++) {
00106       if(Alphabet().Exists(*eit)) EventAttribute(*eit,never);
00107     }
00108   }
00109 #endif
00110   // call base
00111   ProposingExecutor::Reset(seed);
00112   mSyncError=false;
00113   FD_DS("DeviceExecutor::Reset(): done");
00114 }
00115 
00116 // Convenience
00117 bool DeviceExecutor::DeviceResetRequest(void) {
00118 #ifdef FAUDES_PLUGIN_IODEVICE
00119   // bail out
00120   if(!pDevice) return false;
00121   // pass on to device
00122   return pDevice->ResetRequest();
00123 #else
00124   return false;
00125 #endif
00126 }
00127 
00128 //ExecuteEvent
00129 bool DeviceExecutor::ExecuteEvent(Idx event){
00130   FD_DS("DeviceExecutor::ExecuteEvent(): "<< EventName(event));
00131   /*
00132 #ifdef FAUDES_PLUGIN_IODEVICE
00133   // sync time
00134   if(pDevice) SyncStep(0);
00135 #endif
00136   */
00137   // execute event
00138   bool res=ProposingExecutor::ExecuteEvent(event);
00139   /*
00140 #ifdef FAUDES_PLUGIN_IODEVICE
00141   // pass on to callbacks
00142   if(res && pDevice) pDevice->WriteOutput(event);
00143 #endif
00144   */
00145   // report
00146   return res;
00147 }
00148 
00149 
00150 //SyncTime()
00151 bool DeviceExecutor::SyncTime(void){
00152 
00153   // no plugin, no run
00154 #ifndef FAUDES_PLUGIN_IODEVICE
00155   return false;
00156 #else
00157 
00158   // no device, no run
00159   if(!pDevice) return false;
00160 
00161   // figure situation
00162   tpTime::Type devNow=pDevice->CurrentTime();
00163   tpTime::Type genNow=CurrentTime();
00164   tpTime::Type syncTime=devNow-genNow;
00165   tpTime::Type propTime=ProposeNextTransition().Time;
00166 
00167 
00168   // time sync: no chance since generator is ahead
00169   if(mSyncMode & SyncStrictTime)
00170   if(syncTime < -mMaxSyncGap) {
00171     FD_DS_SYNC("DeviceExecutor::SyncTime(): device time " << devNow << " gen time " << genNow);
00172     FD_DS_SYNC("DeviceExecutor::SyncTime(): sync error: gen time ahead");
00173     mSyncError=true;
00174     pDevice->Reset();
00175     return false;
00176   }
00177 
00178   // time sync: check whether proposal allows for sync
00179   if(mSyncMode & SyncStrictTime)
00180   if(syncTime - mMaxSyncGap > propTime || propTime==tpTime::UnDef) {
00181     FD_DS_SYNC("DeviceExecutor::SyncTime(): device time " << devNow << " gen time " << genNow);
00182     FD_DS_SYNC("DeviceExecutor::SyncTime(): sync error: cannot sync enough time");
00183     mSyncError=true;
00184     pDevice->Reset();
00185     return false;
00186   }
00187 
00188   // fix undef time (aka deadlock)
00189   // note: this is pointless, since the executor will not recover
00190   if(propTime==tpTime::UnDef) propTime=tpTime::Max;
00191  
00192   // adjust by proposal
00193   if(syncTime > propTime) {
00194     FD_DS_SYNC("DeviceExecutor::SyncTime(): device time " << devNow << " gen time " << genNow);
00195     FD_DS_SYNC("DeviceExecutor::SyncTime(): adjust by proposal");
00196     syncTime=propTime;
00197   }
00198 
00199   // time sync: pass generator time 
00200   if(syncTime>0) {
00201     FD_DS_SYNC("DeviceExecutor::SyncTime(): generator to pass " << syncTime); 
00202     if(!ProposingExecutor::ExecuteTime(syncTime)) {
00203       tpTime::Type maxsync=EnabledTime().UB();
00204       if(maxsync >= syncTime-mMaxSyncGap) {
00205         syncTime=maxsync;
00206       }
00207       FD_DS_SYNC("DeviceExecutor::SyncTime(): retry: generator to pass " << syncTime);
00208       if(!ProposingExecutor::ExecuteTime(syncTime)) 
00209       if(mSyncMode & SyncStrictTime) {
00210         FD_DS_SYNC("DeviceExecutor::SyncTime(): exec error");
00211         mSyncError=true;
00212         pDevice->Reset();
00213         return false;
00214       }
00215     };
00216   }
00217 
00218   // done
00219   /*
00220   FD_DS_SYNC("DeviceExecutor::SyncTime(): ok: device time " << 
00221     pDevice->CurrentTime() << " gen time " << CurrentTime());
00222   */
00223   return true;
00224 
00225 #endif
00226 }
00227 
00228 
00229 //SyncEvents()
00230 Idx DeviceExecutor::SyncEvents(void){
00231 
00232   // no plugin, no run
00233 #ifndef FAUDES_PLUGIN_IODEVICE
00234   return 0;
00235 #else
00236 
00237   // no device, no run
00238   if(!pDevice) return 0;
00239 
00240   // ignore alien hardware event
00241   if(Idx sev=pDevice->PeekInput()) {
00242     if(!ParallelExecutor::Alphabet().Exists(sev)) {
00243       FD_DS_SYNC("DeviceExecutor::SyncEvents(): input event " << EStr(sev) << " ignored");
00244       pDevice->ReadInput();
00245     }
00246   }
00247 
00248   // get and execute hardware events, if accepted
00249   if(Idx sev=pDevice->PeekInput()) {
00250     if(EnabledEvents().Exists(sev)) {
00251       pDevice->ReadInput();
00252       ProposingExecutor::ExecuteEvent(sev);
00253       FD_DS_SYNC("DeviceExecutor::SyncEvents(): input event " << EStr(sev) << " accepted");
00254       return sev;
00255     }
00256     FD_DS_SYNC("DeviceExecutor::SyncEvents(): input event " << EStr(sev) << " postponed");
00257   }
00258 
00259   // check and execute scheduled event
00260   const TimedEvent& proposedTrans=ProposeNextTransition();
00261   if(proposedTrans.Time==0 && proposedTrans.Event!=0) {
00262     FD_DS_SYNC("DeviceExecutor::SyncEvents(): scheduled event: " << EventName(proposedTrans.Event));
00263     ProposingExecutor::ExecuteEvent(proposedTrans.Event);
00264     if(pDevice->Outputs().Exists(proposedTrans.Event))
00265       pDevice->WriteOutput(proposedTrans.Event);
00266     FD_DS_SYNC("DeviceExecutor::SyncEvents(): scheduled event: execueted");
00267     return proposedTrans.Event; 
00268   }
00269 
00270   // get and execute hardware events
00271   if(Idx sev=pDevice->ReadInput()) {
00272     bool exec = ProposingExecutor::ExecuteEvent(sev);
00273     if(!exec && (mSyncMode & SyncStrictEvents)) {
00274       FD_DS_SYNC("DeviceExecutor::SyncEvents(): sync error: invalid input event");
00275       mSyncError=true;
00276       pDevice->Reset();
00277     }
00278     return (exec ? sev : 0);
00279   }
00280 
00281 
00282   /*
00283   FD_DS_SYNC("DeviceExecutor::SyncEvents(): no events ready");
00284   */
00285   return 0;
00286 
00287 #endif
00288 }
00289 
00290 //SyncWait()
00291 bool DeviceExecutor::SyncWait(tpTime::Type duration){
00292 
00293   // no plugin, no run
00294 #ifndef FAUDES_PLUGIN_IODEVICE
00295   return false;
00296 #else
00297 
00298   // no device, no run
00299   if(!pDevice) return false;
00300 
00301   // report
00302   FD_DS_SYNC("DeviceExecutor::SyncWait(): sleep " << tpTime::Str(duration) );
00303 
00304   // adjust
00305   const TimedEvent& proposedTrans=ProposeNextTransition();
00306   if(proposedTrans.Time<duration) duration=proposedTrans.Time;
00307   if(duration <0) duration=0;
00308 
00309   // report
00310   FD_DS_SYNC("DeviceExecutor::SyncWait(): adjusted by proposal: " << tpTime::Str(duration) );
00311 
00312   // doit
00313   bool res=pDevice->WaitInputs(duration);
00314 
00315   // done
00316   return res;
00317 
00318 #endif // io plugin
00319 }
00320 
00321 
00322 //SyncWaitMs()
00323 bool DeviceExecutor::SyncWaitMs(int durationms) {
00324 
00325   // no plugin, no run
00326 #ifndef FAUDES_PLUGIN_IODEVICE
00327   return false;
00328 #else
00329 
00330   // no device, no run
00331   if(!pDevice) return false;
00332 
00333   // report
00334   /*
00335   FD_DS_SYNC("DeviceExecutor::SyncWaitMs(): sleep " << durationms );
00336   */
00337 
00338   // adjust
00339   const TimedEvent& proposedTrans=ProposeNextTransition();
00340   if(proposedTrans.Time*pDevice->TimeScale() <durationms) durationms=proposedTrans.Time *pDevice->TimeScale();
00341   if(durationms <0) durationms=0;
00342 
00343   // report
00344   /*
00345   FD_DS_SYNC("DeviceExecutor::SyncWaitMs(): adjusted by proposal: " << durationms );
00346   */
00347 
00348   // doit
00349   bool res=pDevice->WaitInputsMs(durationms);
00350 
00351   // done
00352   return res;
00353 
00354 #endif // io plugin
00355 }
00356 
00357 
00358 //SyncStep(duartion)
00359 Idx DeviceExecutor::SyncStep(tpTime::Type duration){
00360   FD_DS_SYNC("DeviceExecutor::SyncStep("<< tpTime::Str(duration) << ")");
00361 
00362   // no plugin, no run
00363 #ifndef FAUDES_PLUGIN_IODEVICE
00364   return 0;
00365 #else
00366 
00367   // no device, no run
00368   if(!pDevice) return 0;
00369 
00370   // result
00371   Idx res=0;
00372 
00373   // doit
00374   if(!SyncTime()) return res;
00375   if((res=SyncEvents())!=0) return res;
00376   if(!SyncWait(duration)) return res;
00377   if(!SyncTime()) return res;
00378   res=SyncEvents();
00379 
00380   // done  
00381   return res;
00382 
00383 #endif // io plugin
00384 }
00385 
00386 //SyncRun(duartion)
00387 bool DeviceExecutor::SyncRun(tpTime::Type duration){
00388   FD_DS_SYNC("DeviceExecutor::SyncRun("<< tpTime::Str(duration) << ")");
00389 
00390   // prepare
00391   tpTime::Type genNow=CurrentTime();
00392   tpTime::Type genStop=genNow+duration;
00393   tpTime::Type genLeft=genStop-genNow;
00394   if(duration==tpTime::Max) {
00395     genStop=tpTime::Max;
00396     genLeft=tpTime::Max;
00397   }
00398 
00399   // loop time
00400   while(genLeft>0) {
00401     // step
00402     if(SyncStep(genLeft)==0) return false;
00403     // update
00404     genNow=CurrentTime();
00405     genLeft=genStop-genNow;
00406     if(duration==tpTime::Max) genLeft=tpTime::Max;
00407   }
00408   // done
00409   return true;
00410 }
00411 
00412 } // namespace
00413 

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen