sp_dplpexecutor.cppGo 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 |