iop_vdevice.cpp
Go to the documentation of this file.
1 /** @file iop_vdevice.cpp Virtual device for interface definition */
2 
3 /*
4  FAU Discrete Event Systems Library (libfaudes)
5 
6  Copyright (C) 2008, Thomas Moor
7  Exclusive copyright is granted to Klaus Schmidt
8 
9 */
10 
11 
12 
13 #include "iop_vdevice.h"
14 
15 #include "iop_simplenet.h"
16 #include "iop_comedi.h"
17 #include "iop_wago.h"
18 #include "iop_xdevice.h"
19 #include "sp_densityfnct.h"
20 
21 
22 namespace faudes {
23 
24 
25 
26 /*
27  **********************************************
28  **********************************************
29  **********************************************
30 
31  implementation: AttributeDeviceEvent
32 
33  **********************************************
34  **********************************************
35  **********************************************
36  */
37 
38 
39 // faudes type std
40 FAUDES_TYPE_IMPLEMENTATION(Void,AttributeDeviceEvent,AttributeVoid)
41 
42 // Default constructor (no attributes, aka undefined) */
44  AttributeVoid(),
45  mpOutputAttribute(0),
46  mpInputAttribute(0),
47  pOutputPrototype(0),
48  pInputPrototype(0)
49 {
50  FD_DHV("AttributeDeviceEvent::AttributeDeviceEvent(" << this << ")");
51  pOutputPrototype= FallbackAttributep();
52  pInputPrototype= FallbackAttributep();
53 }
54 
55 // Copy constructor (never called)
57  AttributeVoid(),
58  mpOutputAttribute(0),
59  mpInputAttribute(0),
60  pOutputPrototype(0),
61  pInputPrototype(0)
62 {
63  FD_DHV("AttributeDeviceEvent(" << this << "): form other attr " << &rOtherAttr);
66  DoAssign(rOtherAttr);
67 }
68 
69 // Destructor
73 }
74 
75 // pseudo statics
77  static AttributeVoid* avoid=new AttributeVoid();
78  return avoid;
79 }
80 
81 // Clear
87 }
88 
89 // Assignement
91  FD_DHV("AttributeDeviceEvent(" << this << "):DoAssign(): "
92  << typeid(*this).name() << " from " << typeid(rSrcAttr).name());
93  Clear();
94  if(rSrcAttr.IsInput()) Input(*rSrcAttr.Inputp());
95  if(rSrcAttr.IsOutput()) Output(*rSrcAttr.Outputp());
96 }
97 
98 
99 
100 // DoWrite(rTw,rLabel,pContext)
101 void AttributeDeviceEvent::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
102  FD_DHV("AttributeDeviceEvent(" << this << ")::DoWrite(tw): " << IsOutput() << " " << IsInput() );
103  if(IsOutput()) mpOutputAttribute->Write(rTw,rLabel,pContext);
104  if(IsInput()) mpInputAttribute->Write(rTw,rLabel,pContext);
105 }
106 
107 //DoRead(rTr,rLabel,pContext)
108 void AttributeDeviceEvent::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
109  FD_DHV("AttributeDeviceEvent(" << this << ")::DoRead(tr)");
110  // clear
115  // test for output/input section
116  Token token;
117  rTr.Peek(token);
118  if(token.Type()!=Token::Begin) return;
119  // read output/input
120  if(token.StringValue()=="Output" || token.StringValue()=="Actuator") {
121  DefaultOutput();
122  mpOutputAttribute->Read(rTr,rLabel,pContext);
123  FD_DHV("Found Output : " << mpOutputAttribute->ToString());
124  }
125  // read output/input
126  if(token.StringValue()=="Input" || token.StringValue()=="Sensor") {
127  DefaultInput();
128  mpInputAttribute->Read(rTr,rLabel,pContext);
129  FD_DHV("Found Input: " << mpInputAttribute->ToString() << " " << rLabel);
130  }
131  // ignore others
132 }
133 
134 
135 /*
136  **********************************************
137  **********************************************
138  **********************************************
139 
140  implementation: vDevice
141 
142  **********************************************
143  **********************************************
144  **********************************************
145  */
146 
147 
148 //vDevice()
150  // constructor
151 
152  FD_DHV("vDevice(" << mName << ")::vDevice()");
153  //set defaults
154  mName = "IoDevice"; //device-name
155  mpConfiguration = NULL; //derived class to set: pointer to config-set
156  mState = Down; //initial state
157  mDefaultLabel ="Device"; //label used with token-io
158  mTimeScale = 1000; //faudes-time scaling-factor 1[ftu] =^ 1[sec]
159  mMaxSyncGap = tpTime::Step; //max time-delay used with simulator
160  pWaitMutex=&mWaitMutex; //use object - mutex
161  pWaitCondition=&mWaitCondition; //use object - condition
162  pBufferMutex=&mBufferMutex; //use object - buffer-mutex
163  pInputBuffer=&mInputBuffer; //use object - input-buffer
164 
165  //initial mutex- and condition variables
166  faudes_mutex_init(&mWaitMutex);
167  faudes_cond_init(&mWaitCondition);
168  faudes_mutex_init(&mBufferMutex);
169 
170 #ifdef FAUDES_DEBUG_IOPERF
171  // initialize arrays to store time stamps
172  mpPerformanceWaitEnter = new faudes_systime_t[FAUDES_DEBUG_IOPERF_SAMPLES];
173  mpPerformanceWaitExit = new faudes_systime_t[FAUDES_DEBUG_IOPERF_SAMPLES];
176 #endif
177 
178  // track devices
179  AllDevices().insert(this);
180 
181 }
182 
183 // pseudo static members
184 std::set<vDevice*>& vDevice::AllDevices(void) {
185  static std::set<vDevice*> *dlist = new std::set< vDevice* >();
186  return *dlist;
187 }
188 
189 
190 //~vDevice()
192  // destructor
193  FD_DHV("vDevice(" << mName << ")::~vDevice()");
194  //delete configuration
195  if(mpConfiguration) delete mpConfiguration;
196  //destroy mutex
197  faudes_mutex_destroy(&mWaitMutex);
198  faudes_cond_destroy(&mWaitCondition);
199  faudes_mutex_destroy(&mBufferMutex);
200 
201 #ifdef FAUDES_DEBUG_IOPERF
202  // delete time stamps
203  delete mpPerformanceWaitEnter;
204  delete mpPerformanceWaitExit;
205 #endif
206 
207  // track devices
208  AllDevices().erase(this);
209 }
210 
211 //FromTokenReader
213  // construct from token reader
214  FD_DHV("vDevice::FromTokenReader()");
215  // peek first token // s&e tr->rTr
216  Token token;
217  rTr.Peek(token);
218  if(!token.Type()==Token::Begin) {
219  std::stringstream errstr;
220  errstr << "Expected Begin Section in \"" << rTr.FileName() << "\"";
221  throw Exception("vDevice::FromFile", errstr.str(), 52);
222  }
223  // instantiate typed faudes object
224  std::string ftype=token.StringValue();
225  FD_DHV("vDevice::FromFile(" << rTr.FileName() <<"): device type " << ftype);
226  Type* fobject= NewFaudesObject(ftype);
227  if(!fobject) {
228  std::stringstream errstr;
229  errstr << "Unknown type \"" << ftype << "\" at \"" << rTr.FileLine() << "\"";
230  throw Exception("vDevice()::FromFile", errstr.str(), 52);
231  return 0;
232  }
233  // cast to vdevice
234  vDevice* fdevice= dynamic_cast<vDevice*>(fobject);
235  if(!fdevice) {
236  std::stringstream errstr;
237  errstr << "Could not cast to device object from type \"" << ftype << "\" at \"" << rTr.FileLine() << "\")";
238  throw Exception("vDevice()::FromFile", errstr.str(), 52);
239  return 0;
240  }
241  // do read stream
242  fdevice->Read(rTr);
243  return fdevice;
244 }
245 
246 
247 //FromFile(rFileName)
248 vDevice* vDevice::FromFile(const std::string& rFileName) {
249  FD_DHV("vDevice::FromFile(" << rFileName <<")");
250  // peek first token
251  TokenReader tr(rFileName);
252  return FromTokenReader(tr);
253 }
254 
255 
256 // static member function
257 void vDevice::StopAll(void) {
258  // cosmetic bail out
259  if(AllDevices().size()==0) return;
260  // report
261  FD_DH("vDevice::StopAll()");
262  // reset
263  std::set<vDevice*>::const_iterator dit;
264  for(dit=AllDevices().begin(); dit != AllDevices().end(); dit++) {
265  if( dynamic_cast<xDevice*>(*dit) ) continue;
266  FD_DH("vDevice::StopAll(): Reset: " << (*dit)->Name());
267  (*dit)->Reset();
268  }
269  // stop
270  for(dit=AllDevices().begin(); dit != AllDevices().end(); dit++) {
271  if( dynamic_cast<xDevice*>(*dit) ) continue;
272  FD_DH("vDevice::StopAll(): Stop " << (*dit)->Name());
273  (*dit)->Stop();
274  }
275 }
276 
277 
278 // Start(void)
279 void vDevice::Start(void) {
280  // only start if currently down
281  if(mState!=Down) return;
282 
283  FD_DHV("vDevice(" << mName << ")::Start()");
284  if(!mpConfiguration) {
285  std::stringstream errstr;
286  errstr << "cannot start device when not configured";
287  throw Exception("vDevice()::Start()", errstr.str(), 550);
288  }
289  // optimistic default in base class
290  mState=Up;
291  // Start implies Reset
292  Reset();
293 }
294 
295 
296 // Stop()
297 void vDevice::Stop(void) {
298  // stop implies Reset
299  Reset();
300  // only stop if up or starting up
301  if(mState!=Up && mState!=StartUp) return;
302  FD_DHV("vDevice(" << mName << ")::Stop()");
303  // indicate success
304  mState=Down;
305 }
306 
307 
308 // Reset()
309 void vDevice::Reset(void){
310  //delete dynamic data
311  FD_DHV("vDevice(" << mName <<")::Reset()");
312  //reset time and delete dynamic data
313  CurrentTime(0);
314  // reset input buffer
315  faudes_mutex_lock(pBufferMutex);
316  pInputBuffer->clear();
317  mResetRequest=false;
318  faudes_mutex_unlock(pBufferMutex);
319 }
320 
321 
322 // Clear()
323 void vDevice::Clear(void) {
324  //delete static data
325  FD_DHV("vDevice("<< mName <<")::Clear()");
326  //implies stop
327  Stop();
328  //clear exisiting data
330  mOutputs.Clear();
331  mInputs.Clear();
332  // sensible defaults
333  mTimeScale=1000;
334 }
335 
336 
337 // Name(rName)
338 void vDevice::Name(const std::string& rName) {
339  FD_DHV("vDevice(" << mName << ")::Name(\"" << rName << "\")");
340  mName = rName;
341 }
342 
343 // Name()
344 const std::string& vDevice::Name(void) const {
345  FD_DHV("vDevice(" << mName << ")::Name()");
346  return mName;
347 }
348 
349 
350 //StatusString()
351 std::string vDevice::StatusString(void) {
352  //status string, informal (should prepare mutex)
353 
354  FD_DHV("vDevice(" << mName << ")::Name()");
355  //prepare result
356  std::string res;
357  //get curretn device state
358  DeviceState currentState=Status();
359  switch(currentState) {
360  case Down: res="down"; break;
361  case StartUp: res="starting up"; break;
362  case Up: res="up and running"; break;
363  case ShutDown: res="shutting down"; break;
364  }
365 
366  return res;
367 }
368 
369 
370 //DoWrite(rTr,rLabel,pContext)
371 void vDevice::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
372  (void) pContext; (void) rTw;
373  FD_DHV("vDevice("<<mName<<")::DoWrite()");
374  // Set up defaults
375  std::string label=rLabel;
376  std::string ftype=TypeName();
377  // Write begin
378  if(label=="") label=TypeName();
379  if(label=="") label = mDefaultLabel;
380  Token btag;
381  btag.SetBegin(label);
382  if(Name()!=label) btag.InsAttributeString("name",Name());
383  if(ftype!=label && ftype!="") btag.InsAttributeString("ftype",ftype);
384  rTw << btag;
385  // dispatch
386  DoWritePreface(rTw,"",pContext);
387  DoWriteConfiguration(rTw,"",pContext);
388  // end of my section
389  rTw.WriteEnd(label);
390 }
391 
392 //DoWritePreface(rTw,rLabel,pContext)
393 void vDevice::DoWritePreface(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
394  (void) pContext; (void) rTw;
395  // virtual interface for token-output: device specific parameters
396  FD_DHV("vDevice("<<mName<<")::DoWritePreface()");
397  // write faudes-time scaling-factor
398  Token atoken;
399  atoken.SetEmpty("TimeScale");
400  atoken.InsAttributeInteger("value",mTimeScale);
401  rTw<<atoken;
402 }
403 
404 
405 //DoWriteConfiguration(rTw,rLabel,pContext)
406 void vDevice::DoWriteConfiguration(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
407  (void) pContext; (void) rTw;
408  // virtual interface for for token-output: event configuration
409  FD_DHV("vDevice("<<mName<<")::DoWriteConfiguration()");
410  // figure section, write begin
411  std::string label=rLabel;
412  if(label == "") label = "EventConfiguration";
413  rTw.WriteBegin(label);
414  // loop events
415  for (EventSet::Iterator it = mpConfiguration->Begin(); it != mpConfiguration->End(); ++it) {
416  Token etoken;
417  const AttributeVoid& attr=mpConfiguration->Attribute(*it);
418  const AttributeDeviceEvent* attrp = dynamic_cast<const AttributeDeviceEvent*>(&attr);
419 #ifdef FAUDES_DEBUG_CODE
420  if(!attrp) {
421  std::stringstream errstr;
422  errstr << "Invalid attribute configuration";
423  throw Exception("vDevice::DoWriteConfiguration", errstr.str(), 550);
424  }
425 #endif
426  if(!attrp) continue;
427  // figure whether we have an effetively default attribute
428  // note: we should have a smart token writer to figure empty sections automatically
429  bool def=false;
430  if(attrp->IsInput())
431  if(attrp->Inputp()->IsDefault()) def=true;
432  if(attrp->IsOutput())
433  if(attrp->Outputp()->IsDefault()) def=true;
434  // case a: no attribute value
435  if(def) {
436  etoken.SetEmpty("Event");
437  etoken.InsAttributeString("name",mpConfiguration->SymbolicName(*it));
438  if(attrp->IsInput()) etoken.InsAttributeString("iotype","input");
439  if(attrp->IsOutput()) etoken.InsAttributeString("iotype","output");
440  rTw << etoken;
441  }
442  // case b: incl attribute value
443  if(!def) {
444  etoken.SetBegin("Event");
445  etoken.InsAttributeString("name",mpConfiguration->SymbolicName(*it));
446  if(attrp->IsInput()) etoken.InsAttributeString("iotype",std::string("input"));
447  if(attrp->IsOutput()) etoken.InsAttributeString("iotype","output");
448  rTw << etoken;
449  attrp->Write(rTw,"",pContext);
450  etoken.SetEnd("Event");
451  rTw << etoken;
452  }
453  }
454  // loop done
455  rTw.WriteEnd(label);
456 
457 
458  // write event-configuration
459  //if(mpConfiguration) mpConfiguration->XWrite(rTw,label);
460 }
461 
462 //DoRead(rTr,rLabel,pContext)
463 void vDevice::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
464  (void) pContext; (void) rLabel; (void) rTr;
465  // virtual interface for token-input: dispatcher
466  FD_DHV("vDevice("<<mName<<")::DoRead()");
467  Clear();
468  // set default label if no label specified (configure in type constructor)
469  std::string label = rLabel;
470  if(label=="") label = mDefaultLabel;
471  // read my section
472  Token btag;
473  rTr.ReadBegin(label,btag);
474  // extract name
475  Name(label);
476  if(btag.ExistsAttributeString("name"))
477  Name(btag.AttributeStringValue("name"));
478  // call DoReadConfiguration and DoReadPreface
479  DoReadPreface(rTr,"",pContext);
480  DoReadConfiguration(rTr,"",pContext);
481  // end of my section
482  rTr.ReadEnd(label);
483  // organize internal data structures
484  Compile();
485 }
486 
487 //DoReadConfiguration(rTr,rLabel,pContext)
488 void vDevice::DoReadConfiguration(TokenReader& rTr,const std::string& rLabel, const Type* pContext){
489  // bail out on bad configuration
490  if(!mpConfiguration) return;
491  // set default label if no label specified
492  std::string label=rLabel;
493  if(label=="") label="EventConfiguration";
494  // set name
495  mpConfiguration->Name(label);
496  // test for begin
497  /*
498  Token token;
499  rTr.Peek(token);
500  if(!token.IsBegin()) return;
501  if(token.StringValue()!=label) return;
502  */
503  // read begin
504  rTr.ReadBegin(label);
505  FD_DHV("vDevice("<<mName<<")::DoReadConfiguration()");
506  // prepare attribute
508  AttributeDeviceEvent* attrp = dynamic_cast<AttributeDeviceEvent*>(vattrp);
509 #ifdef FAUDES_DEBUG_CODE
510  if(!attrp) {
511  std::stringstream errstr;
512  errstr << "Invalid attribute configuration" << rTr.FileLine();
513  throw Exception("vDevice::DoReadConfiguration", errstr.str(), 550);
514  }
515 #endif
516  if(!attrp) return;
517  FD_DHV("vDevice::DoReadConfiguration(" << this << "): attribute type " << typeid(*attrp).name());
518  // loop tokens
519  std::string name;
520  std::string iotype;
521  while(!rTr.Eos(label)) {
522  Token token;
523  rTr.Peek(token);
524 
525  // snse and digest pre 2.16 format
526  if(token.IsString()) {
527  rTr.Get(token);
528  name=token.StringValue();
529  // read faudes attribute
530  attrp->Read(rTr,"",pContext);
531  // skip unknown faudes attributes
532  AttributeVoid::Skip(rTr);
533  // insert element with attribute
534  Idx index=mpConfiguration->Insert(name);
535  mpConfiguration->Attribute(index,*attrp);
536  continue;
537  }
538 
539  // read element section
540  if(token.IsBegin())
541  if(token.StringValue()=="Event") {
542  FD_DHV("vDevice(" << this << ")::DoReadConfiguration(..): " << token.Str() << "\"");
543  rTr.ReadBegin("Event",token);
544  name=token.AttributeStringValue("name");
545  iotype=token.AttributeStringValue("iotype");
546  // input event
547  if(iotype=="input")
548  attrp->ReadInput(rTr);
549  // output event
550  if(iotype=="output")
551  attrp->ReadOutput(rTr);
552  // valid
553  if((iotype=="input") || (iotype=="output")) {
554  // insert element with attribute
555  Idx index=mpConfiguration->Insert(name);
556  mpConfiguration->Attribute(index,*attrp);
557  rTr.ReadEnd("Event");
558  continue;
559  }
560  }
561  // cannot process token
562  delete attrp;
563  std::stringstream errstr;
564  errstr << "Invalid token of type " << token.Type() << " at " << rTr.FileLine();
565  throw Exception("vDevice::DoReadConfiguration", errstr.str(), 50);
566  }
567  rTr.ReadEnd(label);
568  delete attrp;
569 }
570 
571 //DoReadPreface(rTr,rLabel,pContext)
572 void vDevice::DoReadPreface(TokenReader& rTr, const std::string& rLabel, const Type* pContext){
573  (void) pContext; (void) rLabel; (void) rTr;
574  // virtual interface for token-input: device specific parameters
575  FD_DHV("vDevice("<<mName<<")::DoReadPreface()");
576 
577  // sense and digest pre 2.16 format
578  Token token;
579  rTr.Peek(token);
580  if(token.IsString()) {
581  mName = rTr.ReadString();
582  mTimeScale = rTr.ReadInteger();
583  return;
584  }
585 
586  // loop my members
587  while(true) {
588  Token token;
589  rTr.Peek(token);
590  // time scale
591  if(token.IsBegin())
592  if(token.StringValue()=="TimeScale") {
593  rTr.ReadBegin("TimeScale", token);
594  mTimeScale=token.AttributeIntegerValue("value");
595  rTr.ReadEnd("TimeScale");
596  continue;
597  }
598  // break on unknown
599  break;
600  }
601 }
602 
603 // Configure(Idx,AttributeDeviceEvent&)
604 void vDevice::Configure(Idx event, const AttributeDeviceEvent& attr){
605  //inserts an attributed event and compiles internal data structure
606  FD_DHV("vDevice(" << mName << ")::Configure(event)");
607  Stop();
608  // test type
609  if(typeid(attr)!=typeid(mpConfiguration->Attribute())) {
610  std::stringstream errstr;
611  errstr << "Cannot cast attribute to device event attribute";
612  throw Exception("vDevice::Configure", errstr.str(), 550);
613  }
614  // record
615  mpConfiguration->Insert(event);
616  mpConfiguration->Attribute(event,attr);
617  // setup internal data structure
618  Compile();
619 }
620 
621 // Configure(EventSet)
622 void vDevice::Configure(const EventSet& rPhysicalEvents){
623  FD_DHV("vDevice(" << mName << ")::Configure(alphabet)");
624  Stop();
625  // test type
626  if(typeid(rPhysicalEvents.Attribute())!=typeid(mpConfiguration->Attribute())) {
627  std::stringstream errstr;
628  errstr << "Cannot cast attribute to device event attribute";
629  throw Exception("vDevice::Configure", errstr.str(), 550);
630  }
631  // record events
632  for(EventSet::Iterator eit=rPhysicalEvents.Begin(); eit!=rPhysicalEvents.End(); eit++) {
633  const AttributeVoid attr = rPhysicalEvents.Attribute(*eit);
634  mpConfiguration->Insert(*eit);
635  mpConfiguration->Attribute(*eit,attr); // why does this do the job???
636  }
637  // setup internal data structure
638  Compile();
639 }
640 
641 //Compile()
642 void vDevice::Compile(void){
643  FD_DHV("vDevice(" << mName << ")::Compile()");
644  // Compile() implies Stop()
645  Stop();
646  // clear input- and output-set
647  mInputs.Clear();
648  mOutputs.Clear();
649  // loop over events and set outputs and inputs
650  mInputs.Clear();
651  mOutputs.Clear();
652  for(EventSet::Iterator eit=mpConfiguration->Begin(); eit!=mpConfiguration->End(); eit++) {
654  AttributeDeviceEvent* dattr = dynamic_cast< AttributeDeviceEvent* >(attr);
655  if(!dattr) {
656  std::stringstream errstr;
657  errstr << "Cannot cast attribute to device event attribute";
658  throw Exception("vDevice()::Configure", errstr.str(), 550);
659  }
660  if(dattr->IsInput()) mInputs.Insert(*eit);
661  if(dattr->IsOutput()) mOutputs.Insert(*eit);
662  }
663 }
664 
665 //UseCondition(faudes_mutex_t*)
666 void vDevice::UseCondition(faudes_mutex_t* wmutex, faudes_cond_t* wcond) {
667  // tell device which condition variable to use
668  FD_DHV("vDevice(" << mName << ")::UseCondition()");
669  // set cond/mutex for wait inputs
670  if(wmutex) pWaitMutex=wmutex;
671  if(wcond) pWaitCondition=wcond;
672 }
673 
674 //UseBuffer(mutex, buffer)
675 void vDevice::UseBuffer(faudes_mutex_t* bmutex, std::deque<Idx>* bbuffer) {
676  // Tell the device which buffer to use
677  FD_DHV("vDevice(" << mName << ")::UseBuffer()");
678  //set input buffer and buffer-mutex and
679  if(bmutex) pBufferMutex=bmutex;
680  if(bbuffer) pInputBuffer=bbuffer;
681 }
682 
683 // Outputs()
684 const EventSet& vDevice::Outputs(void) const {
685  return mOutputs;
686 }
687 
688 // Inputs()
689 const EventSet& vDevice::Inputs(void) const {
690  return mInputs;
691 }
692 
693 //FtuToSystemTime(int)
694 faudes_systime_t vDevice::FtuToSystemTime(tpTime::Type duration){
695  // convert faudes-time to sys.time)
696  FD_DHV("vDevice("<<mName<<")::FtuToSystemTime(" << duration << "): using scale " << mTimeScale);
697  //prepare result
698  faudes_systime_t res;
699  //get current system-time
700  faudes_systime_t now;
701  faudes_gettimeofday(&now);
702  //convert duration to real time msec
703  long int durationMsec = mTimeScale*duration;
704  //convert duration from msec (long int) to nsec (sys.time)
705  faudes_systime_t delta;
706  delta.tv_sec = durationMsec/1000;
707  delta.tv_nsec = ( durationMsec - (delta.tv_sec*1000) ) *1000000;
708  //specify the absolut point of time
709  faudes_sumsystime(now,delta,&res);
710  // done
711  return res;
712 }
713 
714 // FtuToMs(tpTime::Type)
715 long int vDevice::FtuToMs(tpTime::Type faudes_time){
716  //convert faudes-time to realtime in ms
717  FD_DHV("vDevice("<<mName<<")::FtuToMs() ");
718  // avoid buffer-overflow while trying to convert an
719  // "infinite" periode of time
720  if(faudes_time>= tpTime::Max/ (mTimeScale+1)) return tpTime::Max;
721  // return real time in ms
722  return mTimeScale*faudes_time;
723 }
724 
725 // MsToFtu(long int)
726 tpTime::Type vDevice::MsToFtu(long int real_time){
727  //Convert real time in ms to faudes-time
728 
729  FD_DHV("vDevice(" << mName << ")::MsToFtu()");
730  return (long int)((1.0/mTimeScale)*real_time/1000*1000);
731 }
732 
733 //CurrentTime(void)
735  //return current faudes-time
736  FD_DHV("vDevice("<<mName<<")::CurrentTime() ");
737  //get current system-time
738  faudes_systime_t now;
739  faudes_gettimeofday(&now);
740  // compute the time elapsed since backgroundthread-startup
741  faudes_systime_t diff;
742  faudes_diffsystime(now,mTimeZero,&diff);
743  // convert physical time to faudes-time
744  return (long int) ((1000.0/mTimeScale) * (diff.tv_sec + diff.tv_nsec*1e-9));
745 }
746 
747 //CurrentTime(now)
749  // set current faudes-time
750  FD_DHV("vDevice(" << mName <<")::CurrentTime("<<tpTime::Str(now) <<")");
752 }
753 
754 //CurrentTimeMs()
755 long int vDevice::CurrentTimeMs(void) {
756  //return current real-time in ms
757  FD_DHV("vDevice("<<mName<<")::CurrentTimeMs() ");
758  //get current system-time
759  faudes_systime_t now;
760  faudes_gettimeofday(&now);
761  // compute the time elapsed since backgroundthread-startup
762  faudes_systime_t diffTime;
763  faudes_diffsystime(now,mTimeZero,&diffTime);
764  // convert current physical time to msecs
765  return 1000*diffTime.tv_sec + diffTime.tv_nsec/1000000;
766 }
767 
768 
769 //CurrentTimeMs(long int)
770 void vDevice::CurrentTimeMs(long int nowms){
771  // set current real-time in ms
772  FD_DHV("vDevice("<<mName<<")::CurrentTimeMs(nowms) ");
773  // set for now =0
774  faudes_systime_t now;
775  faudes_gettimeofday(&now);
776  // adjust to now
777  faudes_systime_t delta;
778  delta.tv_sec = nowms/1000;
779  delta.tv_nsec = 1000000*(nowms%1000);
780  // do adjust
781  faudes_diffsystime(now,delta,&mTimeZero);
782  // report
783  /*
784  time_t systime;
785  time(&systime);
786  struct tm* timeinfo;
787  timeinfo= localtime(&systime);
788  char strbuf[80];
789  strftime(strbuf,80,"%X",timeinfo);
790  */
791 }
792 
793 
794 // WaitInputs(tpTime::Type)
796  //wait a specified time for input events to occur
797 
798  FD_DHV("vDevice("<<mName<<")::WaitInputs("<< duration << ")");
799 
800  // adjust arguments TODO
801  if(duration> 3600*24) { duration= 3600*24;};
802 
803  // if this is a nontrivial wait, flush outputs
804  if(duration>0) FlushOutputs();
805 
806  // wait mutex gets released while waiting
807  faudes_mutex_lock(pWaitMutex);
808 
809  // get preliminary result
810  bool sr=InputReady();
811 
812  // actually wait only if there are no input yet
813  if(!sr && duration>0) {
814 
815 #ifdef FAUDES_DEBUG_IOPERF
816  // performance time stamp
817  faudes_systime_t now;
818  faudes_gettimeofday(&now);
820 #endif
821 
822  //convert duration in systemtime
823  faudes_systime_t condtime = vDevice::FtuToSystemTime(duration);
824  //wait for report from background thread about on available events
825  FD_DHV("vDevice("<<mName<<")::WaitInputs("<< duration << "): waiting for condition");
826  faudes_cond_timedwait(pWaitCondition, pWaitMutex, &condtime);
827  FD_DHV("vDevice("<<mName<<")::WaitInputs("<< duration << "): release at "<< CurrentTime());
828  // update result
829  sr=InputReady();
830 
831 #ifdef FAUDES_DEBUG_IOPERF
832  // performance time stamp
833  faudes_gettimeofday(&now);
842 #endif
843 
844  }
845 
846  // release wait mutex
847  faudes_mutex_unlock(pWaitMutex);
848 
849 
850  return sr;
851 }
852 
853 
854 // WaitInputsMs(long int)
855 bool vDevice::WaitInputsMs(long int duration) {
856  //wait a specified time for input events to occur
857 
858  FD_DHV("vDevice("<<mName<<")::WaitInputsMs("<< duration << ")");
859 
860  // adjust arguments TODO
861  if(duration> 30*3600*24) { duration= 30*3600*24;};
862 
863  // if this is a nontrivial wait, flush outputs
864  if(duration>0) FlushOutputs();
865 
866  // wait mutex gets released while waiting
867  faudes_mutex_lock(pWaitMutex);
868 
869  // get preliminary result
870  bool sr=InputReady();
871  // actually wait onnly if there are no input yet
872  if(!sr && duration>0) {
873 
874 #ifdef FAUDES_DEBUG_IOPERF
875  // performance time stamp
876  faudes_systime_t now;
877  faudes_gettimeofday(&now);
879 #endif
880 
881  //convert duration in nsec spec
882  faudes_systime_t condtime;
883  faudes_msdelay(duration,&condtime);
884  //wait for report from background thread on available events
885  faudes_cond_timedwait(pWaitCondition, pWaitMutex, &condtime);
886  // update result
887  sr=InputReady();
888 
889 #ifdef FAUDES_DEBUG_IOPERF
890  // performance time stamp
891  faudes_gettimeofday(&now);
900 #endif
901 
902  }
903 
904  // released wait mutex
905  faudes_mutex_unlock(pWaitMutex);
906 
907  return sr;
908 }
909 
910 // FlushOutputs(void)
912 }
913 
914 // ResetRequest()
916  bool res=false;
917  faudes_mutex_lock(pBufferMutex);
918  res=mResetRequest;
919  mResetRequest=false;
920  faudes_mutex_unlock(pBufferMutex);
921  return res;
922 }
923 
924 //ReadInputs()
926  //reads input-buffer and returns first occured events by index
927 
928  FD_DHV("vDevice("<<mName<<")::ReadInput()");
929  // prepare result, invalid
930  Idx res=0;
931 
932  // take oldest entry
933  faudes_mutex_lock(pBufferMutex);
934  if(!pInputBuffer->empty()) {
935  res=pInputBuffer->front();
936  pInputBuffer->pop_front();
937  }
938  faudes_mutex_unlock(pBufferMutex);
939  FD_DHV("vDevice("<<mName<<")::ReadInput(): found: " << res);
940  return res;
941 }
942 
943 
944 //PeekInputs()
946  //reads input-buffer and returns first occured events by index
947  // does not remove the event from the buffer
948 
949  FD_DHV("vDevice("<<mName<<")::PeekInput()");
950  // prepare result, invalid
951  Idx res=0;
952 
953  // take oldest entry
954  faudes_mutex_lock(pBufferMutex);
955  if(!pInputBuffer->empty()) {
956  res=pInputBuffer->front();
957  }
958  faudes_mutex_unlock(pBufferMutex);
959 
960  FD_DHV("vDevice("<<mName<<")::PeekInput(): found: " << res);
961  return res;
962 }
963 
964 
965 //InputReady()
967  // returns true if a input-event occured
968 
969  FD_DHV("vDevice("<<mName<<")::ReadInput()");
970  //prepare result
971  bool res;
972  //read buffer
973  faudes_mutex_lock(pBufferMutex);
974  res= !mInputBuffer.empty();
975  faudes_mutex_unlock(pBufferMutex);
976 
977  return res;
978 }
979 
980 
981 // timing analysis
983 #ifdef FAUDES_DEBUG_IOPERF
984 
985  FD_DHV("vDevice::Performance(" << Name() << "): " << mPerformanceBeginIterator << " " << mPerformanceEndIterator);
986 
987  // have samples
988  SampledDensityFunction busyduration;
989  busyduration.Dim(50);
990  busyduration.Clear();
991  busyduration.Name("performance " + Name() + " (busy duration in usecs)");
992 
993  // inspect time stamps
994  for(int i = mPerformanceBeginIterator; ;i++){
995  if(i>= FAUDES_DEBUG_IOPERF_SAMPLES) i=0;
996  int ip = i+1;
997  if(ip>= FAUDES_DEBUG_IOPERF_SAMPLES) ip =0;
998  if(ip==mPerformanceEndIterator) break;
999  faudes_systime_t busy;
1001  busyduration.Sample(busy.tv_sec*1000000 + busy.tv_nsec/1000);
1002  }
1003 
1004  // compile
1005  busyduration.Compile();
1006 
1007  // done
1008  return busyduration;
1009 
1010 #else
1011 
1012  FD_DHV("vDevice::Performance(" << Name() << "): not enabled");
1013  SampledDensityFunction busyduration;
1014  busyduration.Name("performance monitoring not enabled");
1015  return busyduration;
1016 
1017 #endif
1018 }
1019 
1020 // WritePerformance
1022 #ifdef FAUDES_DEBUG_IOPERF
1023  SampledDensityFunction busyduration=Performance();
1024  // token output
1025  busyduration.Write();
1026  // pretty print
1027  std::cout << busyduration.Str() << std::endl;
1028 #endif
1029 }
1030 
1031 // ClearPerformance
1033 
1034 #ifdef FAUDES_DEBUG_IOPERF
1037 #endif
1038 
1039 }
1040 
1041 } // name space
1042 

libFAUDES 2.26g --- 2015.08.17 --- c++ api documentaion by doxygen