|
libFAUDES
Sections
Index
|
iop_vdevice.cppGo to the documentation of this file.00001 /** @file iop_vdevice.cpp Virtual device for interface definition */ 00002 00003 /* 00004 FAU Discrete Event Systems Library (libfaudes) 00005 00006 Copyright (C) 2008, Thomas Moor 00007 Exclusive copyright is granted to Klaus Schmidt 00008 00009 */ 00010 00011 00012 00013 #include "iop_vdevice.h" 00014 00015 #include "iop_simplenet.h" 00016 #include "iop_comedi.h" 00017 #include "iop_wago.h" 00018 #include "iop_xdevice.h" 00019 #include "sp_densityfnct.h" 00020 #include "sys/time.h" 00021 00022 00023 namespace faudes { 00024 00025 00026 00027 /* 00028 ********************************************** 00029 ********************************************** 00030 ********************************************** 00031 00032 implementation: AttributeDeviceEvent 00033 00034 ********************************************** 00035 ********************************************** 00036 ********************************************** 00037 */ 00038 00039 00040 // statics 00041 AttributeVoid AttributeDeviceEvent::sFallbackAttribute=AttributeVoid(); 00042 00043 // faudes type std 00044 FAUDES_TYPE_IMPLEMENTATION(AttributeDeviceEvent,AttributeVoid) 00045 00046 // Default constructor (no attributes, aka undefined) */ 00047 AttributeDeviceEvent::AttributeDeviceEvent(void) : 00048 AttributeVoid(), 00049 mpActuatorAttribute(0), 00050 mpSensorAttribute(0), 00051 pActuatorPrototype(&sFallbackAttribute), 00052 pSensorPrototype(&sFallbackAttribute) 00053 { 00054 FD_DHV("AttributeDeviceEvent::AttributeDeviceEvent(" << this << ")"); 00055 } 00056 00057 // Copy constructor (never called) 00058 AttributeDeviceEvent::AttributeDeviceEvent(const AttributeDeviceEvent& rOtherAttr) : 00059 AttributeVoid(), 00060 mpActuatorAttribute(0), 00061 mpSensorAttribute(0), 00062 pActuatorPrototype(&sFallbackAttribute), 00063 pSensorPrototype(&sFallbackAttribute) 00064 { 00065 FD_DHV("AttributeDeviceEvent(" << this << "): form other attr " << &rOtherAttr); 00066 DoAssign(rOtherAttr); 00067 } 00068 00069 // Destructor 00070 AttributeDeviceEvent::~AttributeDeviceEvent(void) { 00071 if(mpActuatorAttribute) delete mpActuatorAttribute; 00072 if(mpSensorAttribute) delete mpSensorAttribute; 00073 } 00074 00075 // Clear 00076 void AttributeDeviceEvent::Clear(void) { 00077 if(mpActuatorAttribute) delete mpActuatorAttribute; 00078 if(mpSensorAttribute) delete mpSensorAttribute; 00079 mpActuatorAttribute=0; 00080 mpSensorAttribute=0; 00081 } 00082 00083 // Assignement 00084 AttributeDeviceEvent& AttributeDeviceEvent::DoAssign(const AttributeDeviceEvent& rSrcAttr) { 00085 FD_DHV("AttributeDeviceEvent(" << this << "):DoAssign(): " 00086 << typeid(*this).name() << " from " << typeid(rSrcAttr).name()); 00087 Clear(); 00088 if(rSrcAttr.IsSensor()) Sensor(*rSrcAttr.Sensorp()); 00089 if(rSrcAttr.IsActuator()) Actuator(*rSrcAttr.Actuatorp()); 00090 return *this; 00091 } 00092 00093 00094 00095 // DoWrite(rTw,rLabel,pContext) 00096 void AttributeDeviceEvent::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const { 00097 FD_DHV("AttributeDeviceEvent(" << this << ")::DoWrite(tw): " << IsActuator() << " " << IsSensor() ); 00098 if(IsActuator()) mpActuatorAttribute->Write(rTw,rLabel,pContext); 00099 if(IsSensor()) mpSensorAttribute->Write(rTw,rLabel,pContext); 00100 } 00101 00102 //DoRead(rTr,rLabel,pContext) 00103 void AttributeDeviceEvent::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) { 00104 FD_DHV("AttributeDeviceEvent(" << this << ")::DoRead(tr)"); 00105 // clear 00106 if(mpSensorAttribute) delete mpSensorAttribute; 00107 if(mpActuatorAttribute) delete mpActuatorAttribute; 00108 mpSensorAttribute=0; 00109 mpActuatorAttribute=0; 00110 // test for actuator/sensor section 00111 Token token; 00112 rTr.Peek(token); 00113 if(token.Type()!=Token::Begin) return; 00114 // read actuator/sensor 00115 if(token.StringValue()=="Actuator" || token.StringValue()=="Output") { 00116 DefaultActuator(); 00117 mpActuatorAttribute->Read(rTr,rLabel,pContext); 00118 FD_DH("Found Actuator : " << mpActuatorAttribute->ToString()); 00119 } 00120 // read actuator/sensor 00121 if(token.StringValue()=="Sensor" || token.StringValue()=="Input") { 00122 DefaultSensor(); 00123 mpSensorAttribute->Read(rTr,rLabel,pContext); 00124 FD_DH("Found Sensor: " << mpSensorAttribute->ToString()); 00125 } 00126 } 00127 00128 00129 /* 00130 ********************************************** 00131 ********************************************** 00132 ********************************************** 00133 00134 implementation: vDevice 00135 00136 ********************************************** 00137 ********************************************** 00138 ********************************************** 00139 */ 00140 00141 // static members 00142 std::set<vDevice*> vDevice::msAllDevices; 00143 00144 //vDevice() 00145 vDevice::vDevice(void) { 00146 // constructor 00147 00148 FD_DHV("vDevice(" << mName << ")::vDevice()"); 00149 //set defaults 00150 mName = "IoDevice"; //device-name 00151 mpConfiguration = NULL; //TODO: pointer to config-set 00152 mState = Down; //initial state 00153 mDefaultLabel ="Device"; //label used with token-io 00154 mTimeScale = 1000; //fauDES-time scaling-factor 1[ftu] =^ 1[sec] 00155 mMaxSyncGap = tpTime::Step; //max time-delay used with simulator 00156 pWaitMutex=&mWaitMutex; //use object - mutex 00157 pWaitCondition=&mWaitCondition; //use object - condition 00158 pBufferMutex=&mBufferMutex; //use object - buffer-mutex 00159 pSensorBuffer=&mSensorBuffer; //use object - sensor-buffer 00160 00161 //initial mutex- and condition variables 00162 pthread_mutex_init(&mWaitMutex,NULL); 00163 pthread_cond_init(&mWaitCondition,NULL); 00164 pthread_mutex_init(&mBufferMutex,NULL); 00165 00166 #ifdef FAUDES_DEBUG_IOPERF 00167 // initialize arrays to store time stamps 00168 mpPerformanceWaitEnter = new timeval[FAUDES_DEBUG_IOPERF_SAMPLES]; 00169 mpPerformanceWaitExit = new timeval[FAUDES_DEBUG_IOPERF_SAMPLES]; 00170 mPerformanceEndIterator = 0; 00171 mPerformanceBeginIterator = 0; 00172 #endif 00173 00174 // track devices 00175 msAllDevices.insert(this); 00176 00177 } 00178 00179 //~vDevice() 00180 vDevice::~vDevice(void) { 00181 // destructor 00182 FD_DHV("vDevice(" << mName << ")::~vDevice()"); 00183 //delete configuration 00184 if(mpConfiguration) delete mpConfiguration; 00185 //destroy mutex 00186 pthread_mutex_destroy(&mWaitMutex); 00187 pthread_cond_destroy(&mWaitCondition); 00188 pthread_mutex_destroy(&mBufferMutex); 00189 00190 #ifdef FAUDES_DEBUG_IOPERF 00191 // delete time stamps 00192 delete mpPerformanceWaitEnter; 00193 delete mpPerformanceWaitExit; 00194 #endif 00195 00196 // track devices 00197 msAllDevices.erase(this); 00198 } 00199 00200 //FromTokenReader 00201 vDevice* vDevice::FromTokenReader(TokenReader& rTr) { 00202 // construct from token reader 00203 FD_DHV("vDevice::FromTokenReader()"); 00204 // peek first token // s&e tr->rTr 00205 Token token; 00206 rTr.Peek(token); 00207 if(!token.Type()==Token::Begin) { 00208 std::stringstream errstr; 00209 errstr << "Expected Begin Section in \"" << rTr.FileName() << "\""; 00210 throw Exception("vDevice::FromFile", errstr.str(), 52); 00211 } 00212 // figure proper class and read 00213 #ifdef FAUDES_IODEVICE_SIMPLENET 00214 // simple net device 00215 if(token.StringValue()=="SimplenetDevice") { 00216 FD_DHV("vDevice::FromFile(" << rTr.FileName() <<"): simplenet device"); 00217 vDevice* ndevp=new nDevice(); 00218 ndevp->Read(rTr); 00219 return ndevp; 00220 } 00221 #endif 00222 #ifdef FAUDES_IODEVICE_COMEDI 00223 // comedi device 00224 if(token.StringValue()=="ComediDevice") { 00225 FD_DHV("vDevice::FromFile(" << rTr.FileName() <<"): comedi device"); 00226 cDevice* cdevp=new cDevice(); 00227 cdevp->Read(rTr); 00228 return cdevp; 00229 } 00230 #endif 00231 #ifdef FAUDES_IODEVICE_WAGO 00232 // wago device 00233 if(token.StringValue()=="WagoDevice") { 00234 FD_DHV("vDevice::FromFile(" << rTr.FileName() <<"): wago device"); 00235 wDevice* wdevp=new wDevice(); 00236 wdevp->Read(rTr); 00237 return wdevp; 00238 } 00239 #endif 00240 // device container aka xdevice 00241 if(token.StringValue()=="DeviceContainer") { 00242 FD_DHV("xDevice::FromFile(" << rTr.FileName() <<"): device container"); 00243 xDevice* xdevp=new xDevice(); 00244 xdevp->Read(rTr); 00245 return xdevp; 00246 } 00247 // unknown device type 00248 std::stringstream errstr; 00249 errstr << "Unknown type \"" << token.StringValue() << "\" at \"" << rTr.FileLine() << "\""; 00250 throw Exception("vDevice()::FromFile", errstr.str(), 52); 00251 return 0; 00252 } 00253 00254 00255 //FromFile(rFileName) 00256 vDevice* vDevice::FromFile(const std::string& rFileName) { 00257 FD_DHV("vDevice::FromFile(" << rFileName <<")"); 00258 // peek first token 00259 TokenReader tr(rFileName); 00260 return FromTokenReader(tr); 00261 } 00262 00263 00264 // static member function 00265 void vDevice::StopAll(void) { 00266 // cosmetic bail out 00267 if(msAllDevices.size()==0) return; 00268 // report 00269 FD_DH("vDevice::StopAll()"); 00270 // reset 00271 std::set<vDevice*>::const_iterator dit; 00272 for(dit=msAllDevices.begin(); dit != msAllDevices.end(); dit++) { 00273 if( dynamic_cast<xDevice*>(*dit) ) continue; 00274 FD_DH("vDevice::StopAll(): Reset " << *dit); 00275 (*dit)->Reset(); 00276 } 00277 // stop 00278 for(dit=msAllDevices.begin(); dit != msAllDevices.end(); dit++) { 00279 if( dynamic_cast<xDevice*>(*dit) ) continue; 00280 FD_DH("vDevice::StopAll(): Stop " << *dit); 00281 (*dit)->Stop(); 00282 } 00283 } 00284 00285 00286 // Start(void) 00287 void vDevice::Start(void) { 00288 // only start if currently down 00289 if(mState!=Down) return; 00290 00291 FD_DHV("vDevice(" << mName << ")::Start()"); 00292 if(!mpConfiguration) { 00293 std::stringstream errstr; 00294 errstr << "cannot start device when not configured"; 00295 throw Exception("vDevice()::Start()", errstr.str(), 550); 00296 } 00297 // optimistic default in base class 00298 mState=Up; 00299 // Start implies Reset 00300 Reset(); 00301 } 00302 00303 00304 // Stop() 00305 void vDevice::Stop(void) { 00306 // only stop if up or starting up 00307 if(mState!=Up && mState!=StartUp) return; 00308 FD_DHV("vDevice(" << mName << ")::Stop()"); 00309 // Stop() implies Reset 00310 Reset(); 00311 // optimistic default in base class 00312 mState=Down; 00313 } 00314 00315 00316 // Reset() 00317 void vDevice::Reset(void){ 00318 //delete dynamic data 00319 FD_DHV("vDevice(" << mName <<")::Reset()"); 00320 //reset time and delete dynamic data 00321 CurrentTime(0); 00322 // reset sensor buffer 00323 pthread_mutex_lock(pBufferMutex); 00324 pSensorBuffer->clear(); 00325 mResetRequest=false; 00326 pthread_mutex_unlock(pBufferMutex); 00327 } 00328 00329 00330 // Clear() 00331 void vDevice::Clear(void) { 00332 //delete static data 00333 00334 FD_DHV("vDevice("<< mName <<")::Clear()"); 00335 //implies stop 00336 Stop(); 00337 //clear exisiting data 00338 if(mpConfiguration) mpConfiguration->Clear(); 00339 mActuators.Clear(); 00340 mSensors.Clear(); 00341 } 00342 00343 00344 // Name(rName) 00345 void vDevice::Name(const std::string& rName) { 00346 FD_DHV("vDevice(" << mName << ")::Name(\"" << rName << "\")"); 00347 mName = rName; 00348 } 00349 00350 // Name() 00351 const std::string& vDevice::Name(void) const { 00352 FD_DHV("vDevice(" << mName << ")::Name()"); 00353 return mName; 00354 } 00355 00356 00357 //StatusString() 00358 std::string vDevice::StatusString(void) { 00359 //status string, informal (should prepare mutex) 00360 00361 FD_DHV("vDevice(" << mName << ")::Name()"); 00362 //prepare result 00363 std::string res; 00364 //get curretn device state 00365 DeviceState currentState=Status(); 00366 switch(currentState) { 00367 case Down: res="down"; break; 00368 case StartUp: res="starting up"; break; 00369 case Up: res="up and running"; break; 00370 case ShutDown: res="shutting down"; break; 00371 } 00372 00373 return res; 00374 } 00375 00376 00377 //DoWrite(rTr,rLabel,pContext) 00378 void vDevice::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const { 00379 (void) pContext; (void) rTw; 00380 //dummy for token output 00381 00382 FD_DHV("vDevice("<<mName<<")::DoWrite()"); 00383 //set default label if no label specified (configure in type constructor)) 00384 std::string label = rLabel; 00385 if(label=="") label = mDefaultLabel; 00386 // write my section 00387 rTw.WriteBegin(label); 00388 //call DoWritePreface DoWriteConfiguration 00389 DoWritePreface(rTw,"",pContext); 00390 DoWriteConfiguration(rTw,"",pContext); 00391 // end of my section 00392 rTw.WriteEnd(label); 00393 } 00394 00395 //DoWriteConfiguration(rTw,rLabel,pContext) 00396 void vDevice::DoWriteConfiguration(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const { 00397 (void) pContext; (void) rTw; 00398 //dummy for token-input; writes configuration 00399 00400 FD_DHV("vDevice("<<mName<<")::DoWriteConfiguration()"); 00401 //Write label "EventConfiguration" if no label specified 00402 std::string label = rLabel; 00403 if(label == "") label = "EventConfiguration"; 00404 //write event-configuration 00405 if(mpConfiguration) mpConfiguration->Write(rTw,rLabel); 00406 } 00407 00408 //DoWritePreface(rTw,rLabel,pContext) 00409 void vDevice::DoWritePreface(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const { 00410 (void) pContext; (void) rTw; 00411 //dummy for token-output; writes non-config data 00412 00413 FD_DHV("vDevice("<<mName<<")::DoWritePreface()"); 00414 //write device name and fauDES-time scaling-factor 00415 rTw.WriteString(mName); 00416 rTw.WriteInteger(mTimeScale); 00417 } 00418 00419 00420 //DoRead(rTr,rLabel,pContext) 00421 void vDevice::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) { 00422 (void) pContext; (void) rLabel; (void) rTr; 00423 //dummy for token-input; 00424 00425 FD_DHV("vDevice("<<mName<<")::DoRead()"); 00426 Clear(); 00427 //set default label if no label specified (configire in type constructor)) 00428 std::string label = rLabel; 00429 if(label=="") label = mDefaultLabel; 00430 // read my section 00431 rTr.ReadBegin(label); 00432 //call DoReadConfiguration and DoReadPreface 00433 DoReadPreface(rTr,"",pContext); 00434 DoReadConfiguration(rTr,"",pContext); 00435 // end of my section 00436 rTr.ReadEnd(label); 00437 // organize internal data structures 00438 Compile(); 00439 } 00440 00441 //DoReadConfiguration(rTr,rLabel,pContext) 00442 void vDevice::DoReadConfiguration(TokenReader& rTr,const std::string& rLabel, const Type* pContext){ 00443 //dummy for token-input; reads configuration 00444 FD_DH("vDevice("<<mName<<")::DoReadConfiguration()"); 00445 //set default label if no label specified 00446 std::string label=rLabel; 00447 if(label=="") label="EventConfiguration"; 00448 //read event-configuration 00449 if(mpConfiguration) mpConfiguration->Read(rTr,label); 00450 } 00451 00452 //DoReadPreface(rTr,rLabel,pContext) 00453 void vDevice::DoReadPreface(TokenReader& rTr, const std::string& rLabel, const Type* pContext){ 00454 (void) pContext; (void) rLabel; (void) rTr; 00455 //dummy for token-input; reads non-config data 00456 00457 FD_DHV("vDevice("<<mName<<")::DoReadPreface()"); 00458 // read name and fauDES-time scaling factor 00459 mName = rTr.ReadString(); 00460 mTimeScale = rTr.ReadInteger(); 00461 } 00462 00463 // Configure(Idx,AttributeDeviceEvent&) 00464 void vDevice::Configure(Idx event, const AttributeDeviceEvent& attr){ 00465 //inserts an attributed event and compiles internal data structure 00466 00467 FD_DHV("vDevice(" << mName << ")::Configure(event)"); 00468 Stop(); 00469 // test type 00470 if(typeid(attr)!=typeid(mpConfiguration->Attribute())) { 00471 std::stringstream errstr; 00472 errstr << "Cannot cast attribute to device event attribute"; 00473 throw Exception("vDevice::Configure", errstr.str(), 550); 00474 } 00475 // record 00476 mpConfiguration->Insert(event); 00477 mpConfiguration->Attribute(event,attr); 00478 // setup internal data structure 00479 Compile(); 00480 } 00481 00482 // Configure(EventSet) 00483 void vDevice::Configure(const EventSet& rPhysicalEvents){ 00484 FD_DHV("vDevice(" << mName << ")::Configure(alphabet)"); 00485 Stop(); 00486 // test type 00487 if(typeid(rPhysicalEvents.Attribute())!=typeid(mpConfiguration->Attribute())) { 00488 std::stringstream errstr; 00489 errstr << "Cannot cast attribute to device event attribute"; 00490 throw Exception("vDevice::Configure", errstr.str(), 550); 00491 } 00492 // record events 00493 for(EventSet::Iterator eit=rPhysicalEvents.Begin(); eit!=rPhysicalEvents.End(); eit++) { 00494 const AttributeVoid attr = rPhysicalEvents.Attribute(*eit); 00495 mpConfiguration->Insert(*eit); 00496 mpConfiguration->Attribute(*eit,attr); // why does this do the job??? 00497 } 00498 // setup internal data structure 00499 Compile(); 00500 } 00501 00502 //Compile() 00503 void vDevice::Compile(void){ 00504 FD_DHV("vDevice(" << mName << ")::Compile()"); 00505 // Compile() implies Stop() 00506 Stop(); 00507 // clear sensor- and actuator-set 00508 mSensors.Clear(); 00509 mActuators.Clear(); 00510 // loop over events and set actuators and sensors 00511 mSensors.Clear(); 00512 mActuators.Clear(); 00513 for(EventSet::Iterator eit=mpConfiguration->Begin(); eit!=mpConfiguration->End(); eit++) { 00514 AttributeVoid* attr = mpConfiguration->Attributep(*eit); 00515 AttributeDeviceEvent* dattr = dynamic_cast< AttributeDeviceEvent* >(attr); 00516 if(!dattr) { 00517 std::stringstream errstr; 00518 errstr << "Cannot cast attribute to device event attribute"; 00519 throw Exception("vDevice()::Configure", errstr.str(), 550); 00520 } 00521 if(dattr->IsSensor()) mSensors.Insert(*eit); 00522 if(dattr->IsActuator()) mActuators.Insert(*eit); 00523 } 00524 } 00525 00526 //UseCondition(pthread_mutex_t*) 00527 void vDevice::UseCondition(pthread_mutex_t* wmutex, pthread_cond_t* wcond) { 00528 // tell device which condition variable to use 00529 FD_DHV("vDevice(" << mName << ")::UseCondition()"); 00530 // set cond/mutex for wait sensors 00531 if(wmutex) pWaitMutex=wmutex; 00532 if(wcond) pWaitCondition=wcond; 00533 } 00534 00535 //UseBuffer(mutex, buffer) 00536 void vDevice::UseBuffer(pthread_mutex_t* bmutex, std::deque<Idx>* bbuffer) { 00537 // Tell the device which buffer to use 00538 FD_DHV("vDevice(" << mName << ")::UseBuffer()"); 00539 //set sensor buffer and buffer-mutex and 00540 if(bmutex) pBufferMutex=bmutex; 00541 if(bbuffer) pSensorBuffer=bbuffer; 00542 } 00543 00544 // Actuators() 00545 const EventSet& vDevice::Actuators(void) const { 00546 return mActuators; 00547 } 00548 00549 // Sensors() 00550 const EventSet& vDevice::Sensors(void) const { 00551 return mSensors; 00552 } 00553 00554 //DiffTime(timeval,timeval) 00555 timeval vDevice::DiffTime(timeval end, timeval start){ 00556 // computes differenz between two timval-structs 00557 FD_DHV("vDevice::DiffTime()"); 00558 // declare a new timval construct to store the result in 00559 timeval res; 00560 // perform subtraction 00561 res.tv_sec = end.tv_sec-start.tv_sec; 00562 res.tv_usec = end.tv_usec-start.tv_usec; 00563 // and treat the carryover 00564 if(res.tv_usec <= 0){ 00565 res.tv_sec--; 00566 res.tv_usec += 1000000; 00567 } 00568 return res; 00569 } 00570 00571 //SumTime(timeval,timeval) 00572 timeval vDevice::SumTime(timeval start, timeval duration){ 00573 // computes sum of two timeval-structs 00574 FD_DHV("vDevice::SumTime()"); 00575 // hypothesis: usec component is (to be kept) below 1000000 00576 timeval res; 00577 // perform addition 00578 res.tv_sec = start.tv_sec + duration.tv_sec; 00579 res.tv_usec = start.tv_usec + duration.tv_usec; 00580 // and treat the carryover 00581 if(res.tv_usec >= 1000000) { 00582 res.tv_sec++; 00583 res.tv_usec-=1000000; 00584 } 00585 return res; 00586 } 00587 00588 //FtuToNsec(int) 00589 timespec vDevice::FtuToTimeSpec(tpTime::Type duration){ 00590 // convert fauDES-time to nsec(timespec) 00591 FD_DHV("vDevice("<<mName<<")::FtuToTimeSpec(" << duration << "): using scale " << mTimeScale); 00592 //prepare result 00593 timespec res; 00594 //convert duration to real time 00595 long int durationMsec = mTimeScale*duration; 00596 //get current system-time 00597 timeval now; 00598 gettimeofday(&now,0); 00599 // convert duration from mssec (long int) to usec (timeval) 00600 timeval delta; 00601 delta.tv_sec = durationMsec/1000; 00602 delta.tv_usec = ( durationMsec - ((durationMsec/1000)*1000) ) *1000; 00603 //specify the absolut point of time 00604 timeval tmp_res = vDevice::SumTime(now,delta); 00605 // convert to timespec 00606 res.tv_sec = tmp_res.tv_sec; 00607 res.tv_nsec = tmp_res.tv_usec*1000; 00608 00609 return res; 00610 } 00611 00612 //FtuMsecToNsec(long int) 00613 timespec vDevice::MsToTimeSpec(long int duration){ 00614 //convert msec to nsec(timespec) 00615 FD_DHV("vDevice::MsToTimeSpec()"); 00616 //prepare result 00617 timespec res; 00618 //get current system-time 00619 timeval now; 00620 gettimeofday(&now,0); 00621 // convert duration from msec (long int) to usec (timeval) 00622 timeval durationMsec; 00623 durationMsec.tv_sec = duration/1000; 00624 durationMsec.tv_usec = ( duration - ((duration/1000)*1000) ) *1000; 00625 // has to wait before false is returned 00626 timeval tmp_res = vDevice::SumTime(now,durationMsec); 00627 // convertto timespec 00628 res.tv_sec = tmp_res.tv_sec; 00629 res.tv_nsec = tmp_res.tv_usec*1000; 00630 00631 return res; 00632 } 00633 00634 // FtuToMs(tpTime::Type) 00635 long int vDevice::FtuToMs(tpTime::Type fauDES_time){ 00636 //convert fauDES-time to realtime in ms 00637 00638 FD_DHV("vDevice("<<mName<<")::FtuToMs() "); 00639 // avoid buffer-overflow while trying to convert an 00640 // "infinite" periode of time 00641 if(fauDES_time>= tpTime::Max/ (mTimeScale+1)) return tpTime::Max; 00642 // return real time in ms 00643 return mTimeScale*fauDES_time; 00644 } 00645 00646 // MsToFtu(long int) 00647 tpTime::Type vDevice::MsToFtu(long int real_time){ 00648 //Convert real time in ms to fauDES-time 00649 00650 FD_DHV("vDevice(" << mName << ")::MsToFtu()"); 00651 return (long int)((1.0/mTimeScale)*real_time/1000*1000); 00652 } 00653 00654 //CurrentTime(void) 00655 tpTime::Type vDevice::CurrentTime(void) { 00656 //return current fauDES-time 00657 00658 FD_DHV("vDevice("<<mName<<")::CurrentTime() "); 00659 // declarate a local timestructure 00660 struct timeval now; 00661 // and store the current system in it 00662 gettimeofday(&now,0); 00663 // compute the time elapsed since backgroundthread-startup 00664 timeval diffTime = vDevice::DiffTime(now,mTimeZero); 00665 // convert current physical time to current fauDES-time 00666 return (long int) ((1000.0/mTimeScale) * (diffTime.tv_sec + diffTime.tv_usec*1e-6)); 00667 } 00668 00669 //CurrentTime(now) 00670 void vDevice::CurrentTime(tpTime::Type now){ 00671 // set current fauDES-time 00672 00673 FD_DHV("vDevice(" << mName <<")::CurrentTime("<<tpTime::Str(now) <<")"); 00674 CurrentTimeMs(mTimeScale*now); 00675 } 00676 00677 //CurrentTimeMs() 00678 long int vDevice::CurrentTimeMs(void) { 00679 //return current real-time in ms 00680 00681 FD_DHV("vDevice("<<mName<<")::CurrentTimeMs() "); 00682 // declare a local timestructure 00683 struct timeval now; 00684 // and store the current system in it 00685 gettimeofday(&now,0); 00686 // compute the time elapsed since backgroundthread-startup 00687 timeval diffTime = vDevice::DiffTime(now,mTimeZero); 00688 // convert current physical time to msecs 00689 return 1000*diffTime.tv_sec + diffTime.tv_usec/1000; 00690 } 00691 00692 00693 //CurrentTimeMs(long int) 00694 void vDevice::CurrentTimeMs(long int nowms){ 00695 // set current real-time in ms 00696 FD_DHV("vDevice("<<mName<<")::CurrentTimeMs(nowms) "); 00697 // set for now =0 00698 gettimeofday(&mTimeZero,0); 00699 // adjust to now 00700 timeval delta; 00701 delta.tv_sec = nowms/1000; 00702 delta.tv_usec = 1000*(nowms%1000); 00703 // carry 00704 if(delta.tv_usec >= 1000*1000){ 00705 delta.tv_sec++; 00706 delta.tv_usec -= 1000000; 00707 } 00708 // do adjust 00709 mTimeZero=DiffTime(mTimeZero,delta); 00710 // report 00711 time_t systime; 00712 time(&systime); 00713 struct tm* timeinfo; 00714 timeinfo= localtime(&systime); 00715 char strbuf[80]; 00716 strftime(strbuf,80,"%X",timeinfo); 00717 } 00718 00719 00720 // WaitSensors(tpTime::Type) 00721 bool vDevice::WaitSensors(tpTime::Type duration) { 00722 //wait a specified time for sensor events to occur 00723 00724 FD_DHV("vDevice("<<mName<<")::WaitSensors("<< duration << ")"); 00725 00726 // adjust arguments TODO 00727 if(duration> 3600*24) { duration= 3600*24;}; 00728 00729 // wait mutex gets released while waiting 00730 pthread_mutex_lock(pWaitMutex); 00731 00732 // get preliminary result 00733 bool sr=SensorReady(); 00734 // actually wait only if there are no sensor yet 00735 if(!sr && duration>0) { 00736 00737 #ifdef FAUDES_DEBUG_IOPERF 00738 // performance time stamp 00739 gettimeofday(mpPerformanceWaitEnter + mPerformanceEndIterator,0); 00740 #endif 00741 00742 //convert duration in nsec spec 00743 timespec condtime = vDevice::FtuToTimeSpec(duration); 00744 //wait for report from mThreadSynchro about occured sensor events 00745 FD_DH("vDevice("<<mName<<")::WaitSensors("<< duration << "): waiting for condition"); 00746 pthread_cond_timedwait(pWaitCondition, pWaitMutex, &condtime); 00747 FD_DH("vDevice("<<mName<<")::WaitSensors("<< duration << "): release at "<< CurrentTime()); 00748 // update result 00749 sr=SensorReady(); 00750 00751 #ifdef FAUDES_DEBUG_IOPERF 00752 // performance time stamp 00753 gettimeofday(mpPerformanceWaitExit + mPerformanceEndIterator,0); 00754 mPerformanceEndIterator++; 00755 if(mPerformanceEndIterator >= FAUDES_DEBUG_IOPERF_SAMPLES) 00756 mPerformanceEndIterator=0; 00757 if(mPerformanceEndIterator == mPerformanceBeginIterator) 00758 mPerformanceBeginIterator++; 00759 if(mPerformanceBeginIterator >= FAUDES_DEBUG_IOPERF_SAMPLES) 00760 mPerformanceBeginIterator=0; 00761 #endif 00762 00763 } 00764 00765 // release wait mutex 00766 pthread_mutex_unlock(pWaitMutex); 00767 00768 00769 return sr; 00770 } 00771 00772 00773 // WaitSensorsMs(long int) 00774 bool vDevice::WaitSensorsMs(long int duration) { 00775 //wait a specified time for sensor events to occur 00776 00777 FD_DHV("vDevice("<<mName<<")::WaitSensorsMs("<< duration << ")"); 00778 00779 // adjust arguments TODO 00780 if(duration> 30*3600*24) { duration= 30*3600*24;}; 00781 00782 // wait mutex gets released while waiting 00783 pthread_mutex_lock(pWaitMutex); 00784 00785 // get preliminary result 00786 bool sr=SensorReady(); 00787 // actually wait onnly if there are no sensor yet 00788 if(!sr && duration>0) { 00789 00790 #ifdef FAUDES_DEBUG_IOPERF 00791 // performance time stamp 00792 gettimeofday(mpPerformanceWaitEnter + mPerformanceEndIterator,0); 00793 #endif 00794 00795 //convert duration in nsec spec 00796 timespec condtime = vDevice::MsToTimeSpec( duration ); 00797 //wait for report from mThreadSynchro about occured sensor events 00798 pthread_mutex_lock(pWaitMutex); 00799 pthread_cond_timedwait(pWaitCondition, pWaitMutex, &condtime); 00800 pthread_mutex_unlock(pWaitMutex); 00801 // update result 00802 sr=SensorReady(); 00803 00804 #ifdef FAUDES_DEBUG_IOPERF 00805 // performance time stamp 00806 gettimeofday(mpPerformanceWaitExit + mPerformanceEndIterator,0); 00807 mPerformanceEndIterator++; 00808 if(mPerformanceEndIterator >= FAUDES_DEBUG_IOPERF_SAMPLES) 00809 mPerformanceEndIterator=0; 00810 if(mPerformanceEndIterator == mPerformanceBeginIterator) 00811 mPerformanceBeginIterator++; 00812 if(mPerformanceBeginIterator >= FAUDES_DEBUG_IOPERF_SAMPLES) 00813 mPerformanceBeginIterator=0; 00814 #endif 00815 00816 } 00817 00818 // released wait mutex 00819 pthread_mutex_unlock(pWaitMutex); 00820 00821 return sr; 00822 } 00823 00824 // ResetRequest() 00825 bool vDevice::ResetRequest(void) { 00826 bool res=false; 00827 pthread_mutex_lock(pBufferMutex); 00828 res=mResetRequest; 00829 mResetRequest=false; 00830 pthread_mutex_unlock(pBufferMutex); 00831 return res; 00832 } 00833 00834 //ReadSensors() 00835 Idx vDevice::ReadSensor(void) { 00836 //reads sensor-buffer and returns first occured events by index 00837 00838 FD_DHV("vDevice("<<mName<<")::ReadSensor()"); 00839 // prepare result, invalid 00840 Idx res=0; 00841 00842 // take oldest entry 00843 pthread_mutex_lock(pBufferMutex); 00844 if(!pSensorBuffer->empty()) { 00845 res=pSensorBuffer->front(); 00846 pSensorBuffer->pop_front(); 00847 } 00848 pthread_mutex_unlock(pBufferMutex); 00849 FD_DHV("vDevice("<<mName<<")::ReadSensor(): found: " << res); 00850 return res; 00851 } 00852 00853 00854 //PeekSensors() 00855 Idx vDevice::PeekSensor(void) { 00856 //reads sensor-buffer and returns first occured events by index 00857 // does not remove the event from the buffer 00858 00859 FD_DHV("vDevice("<<mName<<")::PeekSensor()"); 00860 // prepare result, invalid 00861 Idx res=0; 00862 00863 // take oldest entry 00864 pthread_mutex_lock(pBufferMutex); 00865 if(!pSensorBuffer->empty()) { 00866 res=pSensorBuffer->front(); 00867 } 00868 pthread_mutex_unlock(pBufferMutex); 00869 00870 FD_DHV("vDevice("<<mName<<")::PeekSensor(): found: " << res); 00871 return res; 00872 } 00873 00874 00875 //SensorReady() 00876 bool vDevice::SensorReady(void) { 00877 // returns true if a sensor-event occured 00878 00879 FD_DHV("vDevice("<<mName<<")::ReadSensor()"); 00880 //prepare result 00881 bool res; 00882 //read buffer 00883 pthread_mutex_lock(pBufferMutex); 00884 res= !mSensorBuffer.empty(); 00885 pthread_mutex_unlock(pBufferMutex); 00886 00887 return res; 00888 } 00889 00890 00891 // timing analysis 00892 SampledDensityFunction vDevice::Performance(void) { 00893 #ifdef FAUDES_DEBUG_IOPERF 00894 00895 FD_DH("vDevice::Performance(" << Name() << "): " << mPerformanceBeginIterator << " " << mPerformanceEndIterator); 00896 00897 // have samples 00898 SampledDensityFunction busyduration; 00899 busyduration.Dim(50); 00900 busyduration.Clear(); 00901 busyduration.Name("performance " + Name() + " (busy duration in usecs)"); 00902 00903 // inspect time stamps 00904 for(int i = mPerformanceBeginIterator; ;i++){ 00905 if(i>= FAUDES_DEBUG_IOPERF_SAMPLES) i=0; 00906 int ip = i+1; 00907 if(ip>= FAUDES_DEBUG_IOPERF_SAMPLES) ip =0; 00908 if(ip==mPerformanceEndIterator) break; 00909 timeval busy=vDevice::DiffTime(mpPerformanceWaitEnter[ip],mpPerformanceWaitExit[i]); 00910 busyduration.Sample(busy.tv_sec*1000000 + busy.tv_usec); 00911 } 00912 00913 // compile 00914 busyduration.Compile(); 00915 00916 // done 00917 return busyduration; 00918 00919 #else 00920 00921 FD_DH("vDevice::Performance(" << Name() << "): not enabled"); 00922 SampledDensityFunction busyduration; 00923 return busyduration; 00924 00925 #endif 00926 } 00927 00928 // WritePerformance 00929 void vDevice::WritePerformance(void) { 00930 00931 SampledDensityFunction busyduration=Performance(); 00932 00933 // token output 00934 busyduration.Write(); 00935 00936 // pretty print 00937 std::cout << busyduration.Str() << std::endl; 00938 } 00939 00940 // ClearPerformance 00941 void vDevice::ResetPerformance(void) { 00942 00943 #ifdef FAUDES_DEBUG_IOPERF 00944 mPerformanceEndIterator = 0; 00945 mPerformanceBeginIterator = 0; 00946 #endif 00947 00948 } 00949 00950 } // name space 00951 |
libFAUDES 2.16b --- 2010-9-8 --- c++ source docu by doxygen 1.6.3