sp_pexecutor.cpp
Go to the documentation of this file.
1/** @file sp_pexecutor.cpp Executor for multiple synchronized timed generators */
2
3/*
4 FAU Discrete Event Systems Library (libFAUDES)
5
6 Copyright (C) 2007, 2008, 2024 Thomas Moor
7 Copyright (C) 2007 Ruediger Berndt
8 Exclusive copyright is granted to Klaus Schmidt
9
10*/
11
12
13#include "sp_pexecutor.h"
14
15namespace faudes {
16
17
18// std faudes type
19FAUDES_TYPE_IMPLEMENTATION(ParallelExecutor,ParallelExecutor,Type)
20
21// ParallelExecutor(void)
23 FD_DX("ParallelExecutor(" << this << ")::ParallelExecutor()");
24}
25
26// ParallelExecutor(other)
28 FD_DX("ParallelExecutor(" << this << ")::ParallelExecutor(other)");
29 Assign(rOther);
30}
31
32// ParallelExecutor(rFileName)
33ParallelExecutor::ParallelExecutor(const std::string& rFileName) : Type() {
34 FD_DX("ParallelExecutor(" << this << ")::ParallelExecutor(" << rFileName << ")");
35 Read(rFileName);
36}
37
38// ParallelExecutor(void)
40 FD_DX("ParallelExecutor(" << this << ")::~ParallelExecutor()");
41}
42
43// DoAssign(other)
45 FD_DX("ParallelExecutor(" << this << ")::DoAssign(other)");
48 Compile();
49}
50
51//UpdateParallelTimedState()
55 for(Iterator xit=Begin(); xit!=End(); xit++){
56 mCurrentParallelTimedState.State.push_back(xit->CurrentTimedState().State);
57 mCurrentParallelTimedState.Clock.push_back(xit->CurrentTimedState().ClockValue);
58 }
59}
60
61// Compile()
63 iterator xit;
64 FD_DX("ParallelExecutor(" << this << ")::Compile(): with #" << Size() << " generators");
65 // reset executors, incl compile
66 for(xit=mExecutors.begin(); xit!=mExecutors.end(); xit++)
67 xit->Reset();
68 // update state
70 // compute alphabet
72 mAlphabet.Name("Alphabet");
73 for(xit=mExecutors.begin(); xit!=mExecutors.end(); xit++)
74 mAlphabet.InsertSet(xit->Generator().Alphabet());
75 // reset other members
79 mEValid=false;
80 FD_DX("ParallelExecutor(" << this << ")::Compile(): done");
81}
82
83// Reset()
85 FD_DX("ParallelExecutor(" << this << ")::Reset()");
86 // compile includes reset
87 Compile();
88}
89
90// Insert(rFileName)
91void ParallelExecutor::Insert(const std::string& rFileName) {
92 FD_DX("ParallelExecutor(" << this << ")::Insert(" << rFileName << ")" );
93 TokenReader tr(rFileName);
94 // create executor and read generator
95 mExecutors.push_back(Executor());
96 mExecutorNames.push_back(rFileName);
97 // read generator
98 mExecutors.back().Read(tr);
99 FD_DX("ParallelExecutor(" << this << ")::Insert(" << rFileName
100 << "): found " << mExecutors.back().Name());
101 // compile (incl check determinism)
102 Compile();
103}
104
105// Insert(rGen)
107 FD_DX("ParallelExecutor(" << this << ")::Insert(rGen): " << rGen.Name() << " at #" << Size());
108 mExecutors.push_back(Executor(rGen));
109 mExecutorNames.push_back("");
110 // compile (incl check determinism)
111 Compile();
112}
113
114// Clear()
116 FD_DX("ParallelExecutor(" << this << ")::Clear()");
117 mExecutors.clear();
118 mExecutorNames.clear();
119 Compile();
120}
121
122// Size()
124 return (Idx) mExecutors.size();
125}
126
127
128
129//DoWrite(rTr,rLabel)
130void ParallelExecutor::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
131 (void) pContext;
132 std::string label=rLabel;
133 if(label=="") label = "Executor";
134 rTw.WriteBegin(label);
136 rTw.WriteEnd(label);
137}
138
139// DoXWrite()
140/*
141void ParallelExecutor::DoXWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
142 (void) pContext;
143 // Set up outer tag
144 std::string label=rLabel;
145 std::string ftype=TypeName();
146 if(label=="") label="Executor";
147 Token btag;
148 btag.SetBegin(label);
149 if(Name()!=label && Name()!="") btag.InsAttributeString("name",Name());
150 if(ftype!=label && ftype!="") btag.InsAttributeString("ftype",ftype);
151 FD_DG("vGenerator(" << this << ")::DoXWrite(..): section " << btag.StringValue() << " #" << Size());
152 rTw.Write(btag);
153 DoWriteGenerators(rTw);
154 rTw.WriteEnd(label);
155}
156*/
157
158//DoWriteGenerators(rTr,rLabel)
160 rTw.WriteBegin("Generators");
161 for(Idx i=0; i<Size(); i++) {
162 // write filename
163 if(mExecutorNames.at(i)!="") {
164 rTw.WriteString(mExecutorNames.at(i));
165 }
166 // write generator
167 if(mExecutorNames.at(i)=="") {
168 mExecutors.at(i).Write(rTw);
169 }
170 }
171 rTw.WriteEnd("Generators");
172}
173
174//DoRead(rTr,rLabel)
175void ParallelExecutor::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
176 (void) pContext;
177 // report
178 FD_DX("ParallelExecutor(" << this << ")::DoRead(tr, " << rLabel << ")");
179 // get my section
180 std::string label=rLabel;
181 if(label=="") label = "Executor";
182 // read section
183 rTr.ReadBegin(label);
184 // read generators
185 DoReadGenerators(rTr);
186 // done
187 rTr.ReadEnd(label);
188 // reset
189 Reset();
190}
191
192
193//DoReadGenerators(rTr,rLabel)
195 // get relevant directory
196 std::string dirname="";
197 if(rTr.SourceMode()==TokenReader::File)
198 dirname=ExtractDirectory(rTr.FileName());
199 // report
200 FD_DX("ParallelExecutor(" << this << ")::DoReadGenerators(tr): dirname " << dirname);
201 // read section
202 rTr.ReadBegin("Generators");
203 Token token;
204 while(!rTr.Eos("Generators")) {
205 rTr.Peek(token);
206 // is it a file name?
207 if(token.Type()==Token::String) {
208 Insert(PrependPath(dirname,token.StringValue()));
209 rTr.Get(token);
210 continue;
211 }
212 // is it a generator?
213 if(token.Type()==Token::Begin)
214 if(token.StringValue()=="Generator") {
215 TimedGenerator gen;
216 gen.Read(rTr);
217 Insert(gen);
218 continue;
219 }
220 // else report error
221 std::stringstream errstr;
222 errstr << "Invalid token" << rTr.FileLine();
223 throw Exception("ParallelExecutor::DoReadGenerators", errstr.str(), 502);
224 }
225 rTr.ReadEnd("Generators");
226}
227
228// Alphabet()
230 return mAlphabet;
231}
232
233// ComputeEnabled() fake const
235 ParallelExecutor* fakeconst = const_cast<ParallelExecutor*>(this);
236 fakeconst->ComputeEnabledNonConst();
237}
238
239// ComputeEnabled()
241 iterator xit;
242 // compute members (may remove this)
243 FD_DX("ParallelExecutor(" << this << ")::ComputeEnabled(): members");
244 for(xit=mExecutors.begin(); xit != mExecutors.end(); xit++)
245 xit->IsDeadlocked();
246 // compute etime
247 FD_DX("ParallelExecutor(" << this << ")::ComputeEnabled(): time");
249 for(xit=mExecutors.begin(); xit != mExecutors.end(); xit++)
250 mETime.Intersect(xit->EnabledTime());
251 // compute e/d events
252 FD_DX("ParallelExecutor(" << this << ")::ComputeEnabled(): e/d events");
253 mDEvents.Name("DisabledEvents");
254 mDEvents.Clear();
255 for(xit=mExecutors.begin(); xit != mExecutors.end(); xit++)
256 mDEvents.InsertSet(xit->DisabledEvents());
258 mEEvents.Name("EnabledEvents");
260 // compute einterval // TODO: this is conservative
261 FD_DX("ParallelExecutor(" << this << ")::ComputeEnabled(): interval");
263 for(xit=mExecutors.begin(); xit != mExecutors.end(); xit++)
264 mEInterval.Intersect(xit->EnabledInterval());
265 // done
266 mEValid=true;
267}
268
269// EnabledTime(void)
271 if(!mEValid) ComputeEnabled();
272 return mETime;
273
274}
275
276// EnabledEvents(void)
278 if(!mEValid) ComputeEnabled();
279 return mEEvents;
280}
281
282// DisabledEvents(void)
284 if(!mEValid) ComputeEnabled();
285 return mDEvents;
286}
287
288// EnabledInterval(void)
290 if(!mEValid) ComputeEnabled();
291 return mEInterval;
292}
293
294// EnabledEventInterval(event)
296 TimeInterval retInterval;
297 retInterval.SetPositive();
298 Iterator xit;
299 for(xit=Begin(); xit != End(); xit++){
300 retInterval.Intersect(xit->EnabledEventTime(event));
301 }
302 FD_DX("ParalelExecutor(" << this << ")::EnabledEventTime(" << event << "):"<< retInterval.Str());
303 return retInterval;
304}
305
306// EnabledGuardInterval(event)
308 TimeInterval retInterval;
309 retInterval.SetPositive();
310 Iterator xit;
311 for(xit=Begin(); xit != End(); xit++){
312 retInterval.Intersect(xit->EnabledGuardTime(event));
313 }
314 FD_DX("ParalelExecutor(" << this << ")::EnabledGuardTime(" << event << "):"<< retInterval.Str());
315 return retInterval;
316}
317
318//GetCurrentStateVec
322
323// get current state
327
328// set current state
330 FD_DX("ParalelExecutor(" << this << ")::CurrentParallelState(ptstate): set " << PTSStr(ptstate));
331 // prepare
332 if(ptstate.State.size()!=Size()) return false;
333 if(ptstate.Clock.size()!=Size()) return false;
334 bool res=true;
336 // loop and set for all executors
337 int i=0;
338 for(iterator xit=mExecutors.begin(); xit!=mExecutors.end(); xit++, i++){
339 TimedState tstate;
340 tstate.State=ptstate.State[i];
341 tstate.ClockValue=ptstate.Clock[i];
342 res = res && xit->CurrentTimedState(tstate);
343 }
344 // reject
345 if(!res) {
347 return false;
348 }
349 // reset time (dont call the virtual fncts here)
352 // fix state rep
354 // invalidate
355 mEValid=false;
356 mRecentEvent=0;
357 FD_DX("ParalelExecutor(" << this << ")::CurrentParallelState(ptstate): done");
358 return true;
359}
360
361
362
363// ExecuteTime(time)
365 if(mCurrentTime>=Time::Max()) return false;
366 if(time==0) return true;
367 if(!mEValid) ComputeEnabled();
368 if(!mETime.In(time) && !((time==Time::Max()) && mETime.UBinf()) ) {
369 FD_DX("ParalelExecutor(" << this << ")::ExecuteTime(time): execution of " << time
370 << " conflicts with enabled status " );
371 return false;
372 }
373 // progress current time
374 mCurrentTime += time;
375 // fix infinity
376 if(time==Time::Max()) mCurrentTime=Time::Max();
377 // progress members
378 bool success=true;
379 for(iterator xit=mExecutors.begin(); xit != mExecutors.end(); xit++)
380 success &= xit->ExecuteTime(time);
381 // update state
383 // indicate invalid (conservative)
384 mEValid=false;
385 return success;
386}
387
388// ExecuteEvent(event)
390 if(!mEValid) ComputeEnabled();
391 if(!mEEvents.Exists(event)) {
392 FD_DX("ParallelExecutor(" << this << ")::ExecuteEvent(): execution of event " << EStr(event)
393 << " conflicts with enabled status " );
394 return false;
395 }
396 // progress members
397 bool success=true;
398 for(iterator xit=mExecutors.begin(); xit != mExecutors.end(); xit++)
399 if(xit->Generator().ExistsEvent(event))
400 success &= xit->ExecuteEvent(event);
401 if(!success) {
402 // should throw exception
403 FD_DX("ParallelExecutor(" << this << ")::ExecuteEvent(): execution of event " << EStr(event)
404 << " conflicts with internal state data " );
405 return false;
406 }
407 // progress current time
408 mCurrentStep += 1;
409 // update state
411 // record event
412 mRecentEvent=event;
413 // invalidate
414 mEValid=false;
415 return true;
416}
417
418// CurrentTime(time)
420 mCurrentTime=time;
421 for(iterator xit=mExecutors.begin(); xit != mExecutors.end(); xit++)
422 xit->CurrentTime(time);
423 mEValid=false;
424}
425
426// CurrentTime()
430
431// CurrentStep(step)
433 mCurrentStep=step;
434 for(iterator xit=mExecutors.begin(); xit != mExecutors.end(); xit++)
435 xit->CurrentStep(0);
436 mEValid=false;
437}
438
439// CurrentStep()
441 return mCurrentStep;
442}
443
444// IsDeadlocked()
446 if(!mEValid) ComputeEnabled();
447 if(!mEEvents.Empty()) return false;
448 if(!(mETime.UB()<=0)) return false;
449 return true;
450}
451
452// PTSStr(ptstate)
453std::string ParallelExecutor::PTSStr(const ParallelTimedState& ptstate) const {
454 if(Size()!=ptstate.State.size()) return("(undef)");
455 std::stringstream res;
456 res << "(state ";
457 for(unsigned int i=0; i< Size(); i++){
458 res << mExecutors[i].Generator().SStr(ptstate.State[i]);
459 if(i+1<Size()) res << " x ";
460 }
461 res << ") (clocks (";
462 for(unsigned int i=0; i< Size(); i++){
463 const Executor* execp=&mExecutors[i];
464 ClockSet::Iterator cit;
465 for(cit=execp->Generator().ClocksBegin();cit!=execp->Generator().ClocksEnd();cit++){
466 if(cit!=execp->Generator().ClocksBegin()) res << " ";
467 res << CStr(*cit) << "=";
468 std::map<Idx,Time::Type>::const_iterator cvit=ptstate.Clock[i].find(*cit);
469 if(cvit!=ptstate.Clock[i].end()) res << cvit->second;
470 else res << "undef";
471 }
472 res<<")";
473 if(i+1<Size()) res << " x (";
474 }
475 res << ")";
476 return res.str();
477}
478
479// PSStr(pstate)
480std::string ParallelExecutor::PSStr(const ParallelState& pstate) const {
481 if(Size()!=pstate.size()) return("(undef)");
482 std::stringstream res;
483 res << "(state ";
484 for(unsigned int i=0; i< Size(); i++){
485 res << mExecutors[i].Generator().SStr(pstate[i]);
486 if(i+1<Size()) res << " x ";
487 }
488 res << ")";
489 return res.str();
490}
491
492// TEStr(tevent)
493std::string ParallelExecutor::TEStr(const TimedEvent& tevent) const {
494 if(Size()==0) return "(undef)";
495 return Begin()->TEStr(tevent);
496}
497
498// EStr(event)
499std::string ParallelExecutor::EStr(Idx event) const {
500 if(Size()==0) return "(undef)";
501 return Begin()->EStr(event);
502}
503
504// CStr(clock)
505std::string ParallelExecutor::CStr(Idx clock) const {
506 if(Size()==0) return "(undef)";
507 return Begin()->CStr(clock);
508}
509
510// CurrentParallelTimedStateStr()
514
515// CurrentParallelTimedStateStr()
519
520//ActiveEventSet
522 EventSet retEventSet=Alphabet();
523 Iterator xit;
524 int i;
525 for(i=0, xit=Begin(); xit!=End(); xit++, i++) {
526 retEventSet.EraseSet( xit->Generator().Alphabet() - xit->Generator().ActiveEventSet(stateVec[i]));
527 }
528 return retEventSet;
529}
530
531//Active(Idx)
535
536//Active(Idx, ParallelState)
537bool ParallelExecutor::Active(Idx ev, const ParallelState& stateVec) const {
538 Iterator xit;
539 int i;
540 for(xit=Begin(), i=0; xit!=End(); ++xit, i++){
541 if(xit->Generator().Alphabet().Exists(ev))
542 if(xit->Generator().TransRelBegin(stateVec[i],ev)
543 == xit->Generator().TransRelEnd(stateVec[i],ev))
544 return false;
545 }
546 return true;
547}
548
549
550//DoWrite(rTr,rLabel,pContext)
551void ParallelExecutor::ParallelTimedState::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
552 // allow for two versions only
553 std::string label=rLabel;
554 if(label!="DiscreteState")
555 if(label!="TimedState")
556 label="TimedState";
557 FD_DC("ParallelExecutor::ParallelTimedState::DoWrite(): section " << rLabel << " context " << pContext);
558 // figure context
559 const ParallelExecutor* exe=dynamic_cast<const ParallelExecutor*>(pContext);
560 if(exe) if(exe->Size()!=State.size()) exe=0;
561 if(exe) if(exe->Size()!=Clock.size()) exe=0;
562 // do write
563 if(rLabel=="TimedState") rTw.WriteBegin("TimedState");
564 // discrete state
565 rTw.WriteBegin("DiscreteState");
566 for(unsigned int i=0; i< State.size(); i++) {
567 std::string name="";
568 if(exe) name=exe->At(i).StateName(State.at(i));
569 if(name!="") rTw.WriteString(name);
570 else rTw.WriteInteger(State.at(i));
571 };
572 rTw.WriteEnd("DiscreteState");
573 // figure whether to write clocks
574 bool doclocks=false;
575 if(rLabel=="TimedState")
576 for(unsigned int i=0; i< Clock.size(); i++)
577 if(Clock.at(i).size()>0) doclocks=true;
578 // write clocks
579 if(doclocks) {
580 rTw.WriteBegin("ClockMaps");
581 for(unsigned int i=0; i< Clock.size(); i++) {
582 rTw.WriteBegin("ClockMap");
583 std::map<Idx,Time::Type>::const_iterator cit;
584 for(cit=Clock.at(i).begin(); cit!=Clock.at(i).end(); cit++) {
585 std::string name="";
586 if(exe) name=exe->At(i).Generator().ClockName(cit->first);
587 if(name!="") rTw.WriteString(name);
588 else rTw.WriteInteger(cit->first);
589 rTw.WriteInteger(cit->second);
590 }
591 rTw.WriteEnd("ClockMap");
592 }
593 rTw.WriteEnd("ClockMaps");
594 }
595 // do write end
596 if(rLabel=="TimedState") rTw.WriteEnd("TimedState");
597}
598
599//DoRead(rTr,rLabel,pContext)
600 void ParallelExecutor::ParallelTimedState::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
601 (void) rLabel; (void) pContext; (void) rTr;
602 FD_DC("ParallelExecutor::ParallelTimedState::DoRead()");
603}
604
605
606} // namespace faudes
607
608
#define FD_DC(message)
#define FAUDES_TYPE_IMPLEMENTATION(ftype, ctype, cbase)
Definition cfl_types.h:958
void Generator(const TimedGenerator &rGen)
std::string StateName(Idx idx) const
const std::string & Name(void) const
bool Exists(const Idx &rIndex) const
virtual void InsertSet(const NameSet &rOtherSet)
void EraseSet(const NameSet &rOtherSet)
virtual void DoWrite(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
virtual void DoRead(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
std::string TEStr(const TimedEvent &tevent) const
virtual void DoWrite(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
std::vector< Executor >::iterator iterator
Time::Type CurrentTime(void) const
std::string PSStr(const ParallelState &pstate) const
const EventSet & EnabledEvents() const
const ParallelState & CurrentParallelState(void) const
void ComputeEnabled(void) const
virtual bool ExecuteTime(Time::Type duration)
virtual void DoRead(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
EventSet ActiveEventSet(const ParallelState &stateVec) const
const ParallelTimedState & CurrentParallelTimedState(void) const
int CurrentStep(void) const
std::string PTSStr(const ParallelTimedState &ptstate) const
void Insert(const std::string &rFileName)
std::vector< Executor >::const_iterator Iterator
bool Active(Idx ev, const ParallelState &stateVec) const
ParallelTimedState mCurrentParallelTimedState
std::vector< Idx > ParallelState
const TimeInterval & EnabledInterval() const
const EventSet & DisabledEvents() const
Iterator Begin(void) const
std::string CurrentParallelTimedStateStr(void) const
virtual void DoWriteGenerators(TokenWriter &rTw) const
const Executor & At(int i) const
std::vector< Executor > mExecutors
const TimeInterval & EnabledTime() const
TimeInterval EnabledGuardTime(Idx event) const
virtual void Clear(void)
virtual bool ExecuteEvent(Idx event)
void UpdateParallelTimedState(void)
virtual ~ParallelExecutor(void)
std::vector< std::string > mExecutorNames
virtual void Reset(void)
std::string EStr(Idx event) const
std::string CurrentParallelStateStr(void) const
virtual void DoReadGenerators(TokenReader &rTr)
Iterator End(void) const
const EventSet & Alphabet(void) const
std::string CStr(Idx clock) const
void DoAssign(const ParallelExecutor &rSrc)
TimeInterval EnabledEventTime(Idx event) const
bool UBinf(void) const
bool In(Time::Type time) const
std::string Str(void) const
void UB(Time::Type time)
void Intersect(const TimeInterval &rOtherInterval)
static Type Max(void)
std::string FileLine(void) const
bool Eos(const std::string &rLabel)
void ReadEnd(const std::string &rLabel)
void ReadBegin(const std::string &rLabel)
bool Get(Token &token)
bool Peek(Token &token)
std::string FileName(void) const
Mode SourceMode(void) const
void WriteString(const std::string &rString)
void WriteEnd(const std::string &rLabel)
void WriteInteger(Idx index)
void WriteBegin(const std::string &rLabel)
const std::string & StringValue(void) const
@ Begin
<label> (begin of section)
Definition cfl_token.h:84
@ String
any string, space separated or quoted, must start with a letter
Definition cfl_token.h:86
TokenType Type(void) const
void Read(const std::string &rFileName, const std::string &rLabel="", const Type *pContext=0)
virtual Type & Assign(const Type &rSrc)
Definition cfl_types.cpp:82
bool Empty(void) const
virtual void Clear(void)
uint32_t Idx
std::string ExtractDirectory(const std::string &rFullPath)
std::string PrependPath(const std::string &rLeft, const std::string &rRight)
#define FD_DX(message)
Definition sp_executor.h:27
std::map< Idx, Time::Type > ClockValue

libFAUDES 2.33k --- 2025.09.16 --- c++ api documentaion by doxygen