libFAUDES

Sections

Index

iop_vdevice.cpp

Go 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