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

libFAUDES 2.34d --- 2026.03.11 --- c++ api documentaion by doxygen