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 DoAssign(rOtherAttr);
67}
68
69// Destructor
74
75// pseudo statics
77 static AttributeVoid* avoid=new AttributeVoid();
78 return avoid;
79}
80
81// Clear
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)
101void 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)
108void 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.IsBegin()) return;
119 // read output/input
120 if(token.StringValue()=="Output" || token.StringValue()=="Actuator") {
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 = Time::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
176#endif
177
178 // track devices
179 AllDevices().insert(this);
180
181}
182
183// pseudo static members
184std::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
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
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.IsBegin()) {
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)
248vDevice* 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
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 // report
276 FD_DH("vDevice::StopAll(): done");
277}
278
279
280// Start(void)
281void vDevice::Start(void) {
282 // only start if currently down
283 if(mState!=Down) return;
284
285 FD_DHV("vDevice(" << mName << ")::Start()");
286 if(!mpConfiguration) {
287 std::stringstream errstr;
288 errstr << "cannot start device when not configured";
289 throw Exception("vDevice()::Start()", errstr.str(), 550);
290 }
291 // optimistic default in base class
292 mState=Up;
293 // Start implies Reset
294 Reset();
295}
296
297
298// Stop()
299void vDevice::Stop(void) {
300 // stop implies Reset
301 Reset();
302 // only stop if up or starting up
303 if(mState!=Up && mState!=StartUp) return;
304 FD_DHV("vDevice(" << mName << ")::Stop()");
305 // indicate success
306 mState=Down;
307}
308
309
310// Reset()
311void vDevice::Reset(void){
312 //delete dynamic data
313 FD_DHV("vDevice(" << mName <<")::Reset()");
314 //reset time and delete dynamic data
315 CurrentTime(0);
316 // reset input buffer
317 faudes_mutex_lock(pBufferMutex);
318 pInputBuffer->clear();
319 mResetRequest=false;
320 faudes_mutex_unlock(pBufferMutex);
321}
322
323
324// Clear()
325void vDevice::Clear(void) {
326 //delete static data
327 FD_DHV("vDevice("<< mName <<")::Clear()");
328 //implies stop
329 Stop();
330 //clear exisiting data
332 mOutputs.Clear();
333 mInputs.Clear();
334 // sensible defaults
335 mTimeScale=1000;
336}
337
338
339// Name(rName)
340void vDevice::Name(const std::string& rName) {
341 FD_DHV("vDevice(" << mName << ")::Name(\"" << rName << "\")");
342 mName = rName;
343}
344
345// Name()
346const std::string& vDevice::Name(void) const {
347 FD_DHV("vDevice(" << mName << ")::Name()");
348 return mName;
349}
350
351
352//StatusString()
353std::string vDevice::StatusString(void) {
354 //status string, informal (should prepare mutex)
355
356 FD_DHV("vDevice(" << mName << ")::Name()");
357 //prepare result
358 std::string res;
359 //get curretn device state
360 DeviceState currentState=Status();
361 switch(currentState) {
362 case Down: res="down"; break;
363 case StartUp: res="starting up"; break;
364 case Up: res="up and running"; break;
365 case ShutDown: res="shutting down"; break;
366 }
367
368 return res;
369}
370
371
372//DoWrite(rTr,rLabel,pContext)
373void vDevice::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
374 (void) pContext; (void) rTw;
375 FD_DHV("vDevice("<<mName<<")::DoWrite()");
376 // Set up defaults
377 std::string label=rLabel;
378 std::string ftype=TypeName();
379 // Write begin
380 if(label=="") label=TypeName();
381 if(label=="") label = mDefaultLabel;
382 Token btag;
383 btag.SetBegin(label);
384 if(Name()!=label) btag.InsAttributeString("name",Name());
385 if(ftype!=label && ftype!="") btag.InsAttributeString("ftype",ftype);
386 rTw << btag;
387 // dispatch
388 DoWritePreface(rTw,"",pContext);
389 DoWriteConfiguration(rTw,"",pContext);
390 // end of my section
391 rTw.WriteEnd(label);
392}
393
394//DoWritePreface(rTw,rLabel,pContext)
395void vDevice::DoWritePreface(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
396 (void) pContext; (void) rTw;
397 // virtual interface for token-output: device specific parameters
398 FD_DHV("vDevice("<<mName<<")::DoWritePreface()");
399 // write faudes-time scaling-factor
400 Token atoken;
401 atoken.SetEmpty("TimeScale");
402 atoken.InsAttributeInteger("value",mTimeScale);
403 rTw<<atoken;
404}
405
406
407//DoWriteConfiguration(rTw,rLabel,pContext)
408void vDevice::DoWriteConfiguration(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
409 (void) pContext; (void) rTw;
410 // virtual interface for for token-output: event configuration
411 FD_DHV("vDevice("<<mName<<")::DoWriteConfiguration()");
412 // figure section, write begin
413 std::string label=rLabel;
414 if(label == "") label = "EventConfiguration";
415 rTw.WriteBegin(label);
416 // loop events
417 for (EventSet::Iterator it = mpConfiguration->Begin(); it != mpConfiguration->End(); ++it) {
418 Token etoken;
419 const AttributeVoid& attr=mpConfiguration->Attribute(*it);
420 const AttributeDeviceEvent* attrp = dynamic_cast<const AttributeDeviceEvent*>(&attr);
421#ifdef FAUDES_DEBUG_CODE
422 if(!attrp) {
423 std::stringstream errstr;
424 errstr << "Invalid attribute configuration";
425 throw Exception("vDevice::DoWriteConfiguration", errstr.str(), 550);
426 }
427#endif
428 if(!attrp) continue;
429 // figure whether we have an effetively default attribute
430 // note: we should have a smart token writer to figure empty sections automatically
431 bool def=false;
432 if(attrp->IsInput())
433 if(attrp->Inputp()->IsDefault()) def=true;
434 if(attrp->IsOutput())
435 if(attrp->Outputp()->IsDefault()) def=true;
436 // case a: no attribute value
437 if(def) {
438 etoken.SetEmpty("Event");
440 if(attrp->IsInput()) etoken.InsAttributeString("iotype","input");
441 if(attrp->IsOutput()) etoken.InsAttributeString("iotype","output");
442 rTw << etoken;
443 }
444 // case b: incl attribute value
445 if(!def) {
446 etoken.SetBegin("Event");
448 if(attrp->IsInput()) etoken.InsAttributeString("iotype",std::string("input"));
449 if(attrp->IsOutput()) etoken.InsAttributeString("iotype","output");
450 rTw << etoken;
451 attrp->Write(rTw,"",pContext);
452 etoken.SetEnd("Event");
453 rTw << etoken;
454 }
455 }
456 // loop done
457 rTw.WriteEnd(label);
458
459
460 // write event-configuration
461 //if(mpConfiguration) mpConfiguration->XWrite(rTw,label);
462}
463
464//DoRead(rTr,rLabel,pContext)
465void vDevice::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
466 (void) pContext; (void) rLabel; (void) rTr;
467 // virtual interface for token-input: dispatcher
468 FD_DHV("vDevice("<<mName<<")::DoRead()");
469 Clear();
470 // set default label if no label specified (configure in type constructor)
471 std::string label = rLabel;
472 if(label=="") label = mDefaultLabel;
473 // read my section
474 Token btag;
475 rTr.ReadBegin(label,btag);
476 // extract name
477 Name(label);
478 if(btag.ExistsAttributeString("name"))
479 Name(btag.AttributeStringValue("name"));
480 // call DoReadConfiguration and DoReadPreface
481 DoReadPreface(rTr,"",pContext);
482 DoReadConfiguration(rTr,"",pContext);
483 // end of my section
484 rTr.ReadEnd(label);
485 // organize internal data structures
486 Compile();
487}
488
489//DoReadConfiguration(rTr,rLabel,pContext)
490void vDevice::DoReadConfiguration(TokenReader& rTr,const std::string& rLabel, const Type* pContext){
491 // bail out on bad configuration
492 if(!mpConfiguration) return;
493 // set default label if no label specified
494 std::string label=rLabel;
495 if(label=="") label="EventConfiguration";
496 // set name
497 mpConfiguration->Name(label);
498 // test for begin
499 /*
500 Token token;
501 rTr.Peek(token);
502 if(!token.IsBegin()) return;
503 if(token.StringValue()!=label) return;
504 */
505 // read begin
506 rTr.ReadBegin(label);
507 FD_DHV("vDevice("<<mName<<")::DoReadConfiguration()");
508 // prepare attribute
510 AttributeDeviceEvent* attrp = dynamic_cast<AttributeDeviceEvent*>(vattrp);
511#ifdef FAUDES_DEBUG_CODE
512 if(!attrp) {
513 std::stringstream errstr;
514 errstr << "Invalid attribute configuration" << rTr.FileLine();
515 throw Exception("vDevice::DoReadConfiguration", errstr.str(), 550);
516 }
517#endif
518 if(!attrp) return;
519 FD_DHV("vDevice::DoReadConfiguration(" << this << "): attribute type " << typeid(*attrp).name());
520 // loop tokens
521 std::string name;
522 std::string iotype;
523 while(!rTr.Eos(label)) {
524 Token token;
525 rTr.Peek(token);
526
527 // snse and digest pre 2.16 format
528 if(token.IsString()) {
529 rTr.Get(token);
530 name=token.StringValue();
531 // read faudes attribute
532 attrp->Read(rTr,"",pContext);
533 // skip unknown faudes attributes
535 // insert element with attribute
536 Idx index=mpConfiguration->Insert(name);
537 mpConfiguration->Attribute(index,*attrp);
538 continue;
539 }
540
541 // read element section
542 if(token.IsBegin())
543 if(token.StringValue()=="Event") {
544 FD_DHV("vDevice(" << this << ")::DoReadConfiguration(..): " << token.Str() << "\"");
545 rTr.ReadBegin("Event",token);
546 name=token.AttributeStringValue("name");
547 iotype=token.AttributeStringValue("iotype");
548 // input event
549 if(iotype=="input")
550 attrp->ReadInput(rTr);
551 // output event
552 if(iotype=="output")
553 attrp->ReadOutput(rTr);
554 // valid
555 if((iotype=="input") || (iotype=="output")) {
556 // insert element with attribute
557 Idx index=mpConfiguration->Insert(name);
558 mpConfiguration->Attribute(index,*attrp);
559 rTr.ReadEnd("Event");
560 continue;
561 }
562 }
563 // cannot process token
564 delete attrp;
565 std::stringstream errstr;
566 errstr << "Invalid token of type " << token.Type() << " at " << rTr.FileLine();
567 throw Exception("vDevice::DoReadConfiguration", errstr.str(), 50);
568 }
569 rTr.ReadEnd(label);
570 delete attrp;
571}
572
573//DoReadPreface(rTr,rLabel,pContext)
574void vDevice::DoReadPreface(TokenReader& rTr, const std::string& rLabel, const Type* pContext){
575 (void) pContext; (void) rLabel; (void) rTr;
576 // virtual interface for token-input: device specific parameters
577 FD_DHV("vDevice("<<mName<<")::DoReadPreface()");
578
579 // sense and digest pre 2.16 format
580 Token token;
581 rTr.Peek(token);
582 if(token.IsString()) {
583 mName = rTr.ReadString();
584 mTimeScale = rTr.ReadInteger();
585 return;
586 }
587
588 // loop my members
589 while(true) {
590 Token token;
591 rTr.Peek(token);
592 // time scale
593 if(token.IsBegin())
594 if(token.StringValue()=="TimeScale") {
595 rTr.ReadBegin("TimeScale", token);
596 mTimeScale=token.AttributeIntegerValue("value");
597 rTr.ReadEnd("TimeScale");
598 continue;
599 }
600 // break on unknown
601 break;
602 }
603}
604
605// Configure(Idx,AttributeDeviceEvent&)
607 //inserts an attributed event and compiles internal data structure
608 FD_DHV("vDevice(" << mName << ")::Configure(event)");
609 Stop();
610 // test type
612 if(typeid(attr)!=typeid(*cap)) {
613 std::stringstream errstr;
614 errstr << "Cannot cast attribute to device event attribute";
615 throw Exception("vDevice::Configure", errstr.str(), 550);
616 }
617 // record
618 mpConfiguration->Insert(event);
619 mpConfiguration->Attribute(event,attr);
620 // setup internal data structure
621 Compile();
622}
623
624// Configure(EventSet)
625void vDevice::Configure(const EventSet& rPhysicalEvents){
626 FD_DHV("vDevice(" << mName << ")::Configure(alphabet)");
627 Stop();
628 // test type
630 const AttributeVoid* oap = rPhysicalEvents.AttributeType();
631 if(typeid(*oap)!=typeid(*cap)) {
632 std::stringstream errstr;
633 errstr << "Cannot cast attribute to device event attribute";
634 throw Exception("vDevice::Configure", errstr.str(), 550);
635 }
636 // record events
637 for(EventSet::Iterator eit=rPhysicalEvents.Begin(); eit!=rPhysicalEvents.End(); eit++) {
638 const AttributeVoid attr = rPhysicalEvents.Attribute(*eit);
639 mpConfiguration->Insert(*eit);
640 mpConfiguration->Attribute(*eit,attr); // why does this do the job???
641 }
642 // setup internal data structure
643 Compile();
644}
645
646//Compile()
648 FD_DHV("vDevice(" << mName << ")::Compile()");
649 // Compile() implies Stop()
650 Stop();
651 // clear input- and output-set
652 mInputs.Clear();
653 mOutputs.Clear();
654 // loop over events and set outputs and inputs
655 mInputs.Clear();
656 mOutputs.Clear();
657 for(EventSet::Iterator eit=mpConfiguration->Begin(); eit!=mpConfiguration->End(); eit++) {
659 AttributeDeviceEvent* dattr = dynamic_cast< AttributeDeviceEvent* >(attr);
660 if(!dattr) {
661 std::stringstream errstr;
662 errstr << "Cannot cast attribute to device event attribute";
663 throw Exception("vDevice()::Configure", errstr.str(), 550);
664 }
665 if(dattr->IsInput()) mInputs.Insert(*eit);
666 if(dattr->IsOutput()) mOutputs.Insert(*eit);
667 }
668}
669
670//UseCondition(faudes_mutex_t*)
671void vDevice::UseCondition(faudes_mutex_t* wmutex, faudes_cond_t* wcond) {
672 // tell device which condition variable to use
673 FD_DHV("vDevice(" << mName << ")::UseCondition()");
674 // set cond/mutex for wait inputs
675 if(wmutex) pWaitMutex=wmutex;
676 if(wcond) pWaitCondition=wcond;
677}
678
679//UseBuffer(mutex, buffer)
680void vDevice::UseBuffer(faudes_mutex_t* bmutex, std::deque<Idx>* bbuffer) {
681 // Tell the device which buffer to use
682 FD_DHV("vDevice(" << mName << ")::UseBuffer()");
683 //set input buffer and buffer-mutex and
684 if(bmutex) pBufferMutex=bmutex;
685 if(bbuffer) pInputBuffer=bbuffer;
686}
687
688// Outputs()
689const EventSet& vDevice::Outputs(void) const {
690 return mOutputs;
691}
692
693// Inputs()
694const EventSet& vDevice::Inputs(void) const {
695 return mInputs;
696}
697
698//FtuToSystemTime(int)
699faudes_systime_t vDevice::FtuToSystemTime(Time::Type duration){
700 // convert faudes-time to sys.time)
701 FD_DHV("vDevice("<<mName<<")::FtuToSystemTime(" << duration << "): using scale " << mTimeScale);
702 //prepare result
703 faudes_systime_t res;
704 //get current system-time
705 faudes_systime_t now;
706 faudes_gettimeofday(&now);
707 //convert duration to real time msec
708 long int durationMsec = mTimeScale*duration;
709 //convert duration from msec (long int) to nsec (sys.time)
710 faudes_systime_t delta;
711 delta.tv_sec = durationMsec/1000;
712 delta.tv_nsec = ( durationMsec - (delta.tv_sec*1000) ) *1000000;
713 //specify the absolut point of time
714 faudes_sumsystime(now,delta,&res);
715 // done
716 return res;
717}
718
719// FtuToMs(Time::Type)
720long int vDevice::FtuToMs(Time::Type faudes_time){
721 //convert faudes-time to realtime in ms
722 FD_DHV("vDevice("<<mName<<")::FtuToMs() ");
723 // avoid buffer-overflow while trying to convert an
724 // "infinite" periode of time
725 if(faudes_time>= Time::Max()/ (mTimeScale+1)) return Time::Max();
726 // return real time in ms
727 return mTimeScale*faudes_time;
728}
729
730// MsToFtu(long int)
731Time::Type vDevice::MsToFtu(long int real_time){
732 //Convert real time in ms to faudes-time
733
734 FD_DHV("vDevice(" << mName << ")::MsToFtu()");
735 return (long int)((1.0/mTimeScale)*real_time/1000*1000);
736}
737
738//CurrentTime(void)
740 //return current faudes-time
741 FD_DHV("vDevice("<<mName<<")::CurrentTime() ");
742 //get current system-time
743 faudes_systime_t now;
744 faudes_gettimeofday(&now);
745 // compute the time elapsed since backgroundthread-startup
746 faudes_systime_t diff;
747 faudes_diffsystime(now,mTimeZero,&diff);
748 // convert physical time to faudes-time
749 return (long int) ((1000.0/mTimeScale) * (diff.tv_sec + diff.tv_nsec*1e-9));
750}
751
752//CurrentTime(now)
754 // set current faudes-time
755 FD_DHV("vDevice(" << mName <<")::CurrentTime("<<Time::Str(now) <<")");
757}
758
759//CurrentTimeMs()
761 //return current real-time in ms
762 FD_DHV("vDevice("<<mName<<")::CurrentTimeMs() ");
763 //get current system-time
764 faudes_systime_t now;
765 faudes_gettimeofday(&now);
766 // compute the time elapsed since backgroundthread-startup
767 faudes_systime_t diffTime;
768 faudes_diffsystime(now,mTimeZero,&diffTime);
769 // convert current physical time to msecs
770 return 1000*diffTime.tv_sec + diffTime.tv_nsec/1000000;
771}
772
773
774//CurrentTimeMs(long int)
775void vDevice::CurrentTimeMs(long int nowms){
776 // set current real-time in ms
777 FD_DHV("vDevice("<<mName<<")::CurrentTimeMs(nowms) ");
778 // set for now =0
779 faudes_systime_t now;
780 faudes_gettimeofday(&now);
781 // adjust to now
782 faudes_systime_t delta;
783 delta.tv_sec = nowms/1000;
784 delta.tv_nsec = 1000000*(nowms%1000);
785 // do adjust
786 faudes_diffsystime(now,delta,&mTimeZero);
787 // report
788 /*
789 time_t systime;
790 time(&systime);
791 struct tm* timeinfo;
792 timeinfo= localtime(&systime);
793 char strbuf[80];
794 strftime(strbuf,80,"%X",timeinfo);
795 */
796}
797
798
799// WaitInputs(Time::Type)
801 //wait a specified time for input events to occur
802
803 FD_DHV("vDevice("<<mName<<")::WaitInputs("<< duration << ")");
804
805 // adjust arguments TODO
806 if(duration> 3600*24) { duration= 3600*24;};
807
808 // if this is a nontrivial wait, flush outputs
809 if(duration>0) FlushOutputs();
810
811 // wait mutex gets released while waiting
812 faudes_mutex_lock(pWaitMutex);
813
814 // get preliminary result
815 bool sr=InputReady();
816
817 // actually wait only if there are no input yet
818 if(!sr && duration>0) {
819
820#ifdef FAUDES_DEBUG_IOPERF
821 // performance time stamp
822 faudes_systime_t now;
823 faudes_gettimeofday(&now);
825#endif
826
827 //convert duration in systemtime
828 faudes_systime_t condtime = vDevice::FtuToSystemTime(duration);
829 //wait for report from background thread about on available events
830 FD_DHV("vDevice("<<mName<<")::WaitInputs("<< duration << "): waiting for condition");
831 faudes_cond_timedwait(pWaitCondition, pWaitMutex, &condtime);
832 FD_DHV("vDevice("<<mName<<")::WaitInputs("<< duration << "): release at "<< CurrentTime());
833 // update result
834 sr=InputReady();
835
836#ifdef FAUDES_DEBUG_IOPERF
837 // performance time stamp
838 faudes_gettimeofday(&now);
847#endif
848
849 }
850
851 // release wait mutex
852 faudes_mutex_unlock(pWaitMutex);
853
854
855 return sr;
856}
857
858
859// WaitInputsMs(long int)
860bool vDevice::WaitInputsMs(long int duration) {
861 //wait a specified time for input events to occur
862
863 FD_DHV("vDevice("<<mName<<")::WaitInputsMs("<< duration << ")");
864
865 // adjust arguments TODO
866 if(duration> 30*3600*24) { duration= 30*3600*24;};
867
868 // if this is a nontrivial wait, flush outputs
869 if(duration>0) FlushOutputs();
870
871 // wait mutex gets released while waiting
872 faudes_mutex_lock(pWaitMutex);
873
874 // get preliminary result
875 bool sr=InputReady();
876 // actually wait onnly if there are no input yet
877 if(!sr && duration>0) {
878
879#ifdef FAUDES_DEBUG_IOPERF
880 // performance time stamp
881 faudes_systime_t now;
882 faudes_gettimeofday(&now);
884#endif
885
886 //convert duration in nsec spec
887 faudes_systime_t condtime;
888 faudes_msdelay(duration,&condtime);
889 //wait for report from background thread on available events
890 faudes_cond_timedwait(pWaitCondition, pWaitMutex, &condtime);
891 // update result
892 sr=InputReady();
893
894#ifdef FAUDES_DEBUG_IOPERF
895 // performance time stamp
896 faudes_gettimeofday(&now);
905#endif
906
907 }
908
909 // released wait mutex
910 faudes_mutex_unlock(pWaitMutex);
911
912 return sr;
913}
914
915// FlushOutputs(void)
917}
918
919// ResetRequest()
921 bool res=false;
922 faudes_mutex_lock(pBufferMutex);
923 res=mResetRequest;
924 mResetRequest=false;
925 faudes_mutex_unlock(pBufferMutex);
926 return res;
927}
928
929//ReadInputs()
931 //reads input-buffer and returns first occured events by index
932
933 FD_DHV("vDevice("<<mName<<")::ReadInput()");
934 // prepare result, invalid
935 Idx res=0;
936
937 // take oldest entry
938 faudes_mutex_lock(pBufferMutex);
939 if(!pInputBuffer->empty()) {
940 res=pInputBuffer->front();
941 pInputBuffer->pop_front();
942 }
943 faudes_mutex_unlock(pBufferMutex);
944 FD_DHV("vDevice("<<mName<<")::ReadInput(): found: " << res);
945 return res;
946}
947
948
949//PeekInputs()
951 //reads input-buffer and returns first occured events by index
952 // does not remove the event from the buffer
953
954 FD_DHV("vDevice("<<mName<<")::PeekInput()");
955 // prepare result, invalid
956 Idx res=0;
957
958 // take oldest entry
959 faudes_mutex_lock(pBufferMutex);
960 if(!pInputBuffer->empty()) {
961 res=pInputBuffer->front();
962 }
963 faudes_mutex_unlock(pBufferMutex);
964
965 FD_DHV("vDevice("<<mName<<")::PeekInput(): found: " << res);
966 return res;
967}
968
969
970//InputReady()
972 // returns true if a input-event occured
973
974 FD_DHV("vDevice("<<mName<<")::ReadInput()");
975 //prepare result
976 bool res;
977 //read buffer
978 faudes_mutex_lock(pBufferMutex);
979 res= !mInputBuffer.empty();
980 faudes_mutex_unlock(pBufferMutex);
981
982 return res;
983}
984
985
986// timing analysis
988#ifdef FAUDES_DEBUG_IOPERF
989
990 FD_DHV("vDevice::Performance(" << Name() << "): " << mPerformanceBeginIterator << " " << mPerformanceEndIterator);
991
992 // have samples
993 SampledDensityFunction busyduration;
994 busyduration.Dim(50);
995 busyduration.Clear();
996 busyduration.Name("performance " + Name() + " (busy duration in usecs)");
997
998 // inspect time stamps
999 for(int i = mPerformanceBeginIterator; ;i++){
1000 if(i>= FAUDES_DEBUG_IOPERF_SAMPLES) i=0;
1001 int ip = i+1;
1002 if(ip>= FAUDES_DEBUG_IOPERF_SAMPLES) ip =0;
1003 if(ip==mPerformanceEndIterator) break;
1004 faudes_systime_t busy;
1006 busyduration.Sample(busy.tv_sec*1000000 + busy.tv_nsec/1000);
1007 }
1008
1009 // compile
1010 busyduration.Compile();
1011
1012 // done
1013 return busyduration;
1014
1015#else
1016
1017 FD_DHV("vDevice::Performance(" << Name() << "): not enabled");
1018 SampledDensityFunction busyduration;
1019 busyduration.Name("performance monitoring not enabled");
1020 return busyduration;
1021
1022#endif
1023}
1024
1025// WritePerformance
1027#ifdef FAUDES_DEBUG_IOPERF
1028 SampledDensityFunction busyduration=Performance();
1029 // token output
1030 busyduration.Write();
1031 // pretty print
1032 std::cout << busyduration.Str() << std::endl;
1033#endif
1034}
1035
1036// ClearPerformance
1038
1039#ifdef FAUDES_DEBUG_IOPERF
1042#endif
1043
1044}
1045
1046} // name space
1047
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:958
static void Skip(TokenReader &rTr)
virtual bool IsDefault(void) const
Definition cfl_types.h:1075
const AttributeVoid * pOutputPrototype
const AttributeVoid * Outputp(void) const
virtual void Output(const AttributeVoid &rOutputAttribute)
const AttributeVoid * Inputp(void) const
virtual void DoRead(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
void DoAssign(const AttributeDeviceEvent &rSrcAttr)
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
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.33k --- 2025.09.16 --- c++ api documentaion by doxygen