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 Copy(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// DoCopy(other)
45 FD_DX("ParallelExecutor(" << this << ")::DoCopy(other)");
48 Compile();
49}
50
51// DoMove(other)
53 FD_DX("ParallelExecutor(" << this << ")::DoMove(other)");
54 mExecutors=std::move(rOther.mExecutors);
55 mExecutorNames=std::move(rOther.mExecutorNames);
56 Compile();
57}
58
59//UpdateParallelTimedState()
63 for(Iterator xit=Begin(); xit!=End(); xit++){
64 mCurrentParallelTimedState.State.push_back(xit->CurrentTimedState().State);
65 mCurrentParallelTimedState.Clock.push_back(xit->CurrentTimedState().ClockValue);
66 }
67}
68
69// Compile()
71 iterator xit;
72 FD_DX("ParallelExecutor(" << this << ")::Compile(): with #" << Size() << " generators");
73 // reset executors, incl compile
74 for(xit=mExecutors.begin(); xit!=mExecutors.end(); xit++)
75 xit->Reset();
76 // update state
78 // compute alphabet
80 mAlphabet.Name("Alphabet");
81 for(xit=mExecutors.begin(); xit!=mExecutors.end(); xit++)
82 mAlphabet.InsertSet(xit->Generator().Alphabet());
83 // reset other members
87 mEValid=false;
88 FD_DX("ParallelExecutor(" << this << ")::Compile(): done");
89}
90
91// Reset()
93 FD_DX("ParallelExecutor(" << this << ")::Reset()");
94 // compile includes reset
95 Compile();
96}
97
98// Insert(rFileName)
99void ParallelExecutor::Insert(const std::string& rFileName) {
100 FD_DX("ParallelExecutor(" << this << ")::Insert(" << rFileName << ")" );
101 TokenReader tr(rFileName);
102 // create executor and read generator
103 mExecutors.push_back(Executor());
104 mExecutorNames.push_back(rFileName);
105 // read generator
106 mExecutors.back().Read(tr);
107 FD_DX("ParallelExecutor(" << this << ")::Insert(" << rFileName
108 << "): found " << mExecutors.back().Name());
109 // compile (incl check determinism)
110 Compile();
111}
112
113// Insert(rGen)
115 FD_DX("ParallelExecutor(" << this << ")::Insert(rGen): " << rGen.Name() << " at #" << Size());
116 mExecutors.push_back(Executor(rGen));
117 mExecutorNames.push_back("");
118 // compile (incl check determinism)
119 Compile();
120}
121
122// Clear()
124 FD_DX("ParallelExecutor(" << this << ")::Clear()");
125 mExecutors.clear();
126 mExecutorNames.clear();
127 Compile();
128}
129
130// Size()
132 return (Idx) mExecutors.size();
133}
134
135
136
137//DoWrite(rTr,rLabel)
138void ParallelExecutor::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
139 (void) pContext;
140 std::string label=rLabel;
141 if(label=="") label = "Executor";
142 rTw.WriteBegin(label);
144 rTw.WriteEnd(label);
145}
146
147// DoXWrite()
148/*
149void ParallelExecutor::DoXWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
150 (void) pContext;
151 // Set up outer tag
152 std::string label=rLabel;
153 std::string ftype=TypeName();
154 if(label=="") label="Executor";
155 Token btag;
156 btag.SetBegin(label);
157 if(Name()!=label && Name()!="") btag.InsAttributeString("name",Name());
158 if(ftype!=label && ftype!="") btag.InsAttributeString("ftype",ftype);
159 FD_DG("vGenerator(" << this << ")::DoXWrite(..): section " << btag.StringValue() << " #" << Size());
160 rTw.Write(btag);
161 DoWriteGenerators(rTw);
162 rTw.WriteEnd(label);
163}
164*/
165
166//DoWriteGenerators(rTr,rLabel)
168 rTw.WriteBegin("Generators");
169 for(Idx i=0; i<Size(); i++) {
170 // write filename
171 if(mExecutorNames.at(i)!="") {
172 rTw.WriteString(mExecutorNames.at(i));
173 }
174 // write generator
175 if(mExecutorNames.at(i)=="") {
176 mExecutors.at(i).Write(rTw);
177 }
178 }
179 rTw.WriteEnd("Generators");
180}
181
182//DoRead(rTr,rLabel)
183void ParallelExecutor::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
184 (void) pContext;
185 // report
186 FD_DX("ParallelExecutor(" << this << ")::DoRead(tr, " << rLabel << ")");
187 // get my section
188 std::string label=rLabel;
189 if(label=="") label = "Executor";
190 // read section
191 rTr.ReadBegin(label);
192 // read generators
193 DoReadGenerators(rTr);
194 // done
195 rTr.ReadEnd(label);
196 // reset
197 Reset();
198}
199
200
201//DoReadGenerators(rTr,rLabel)
203 // get relevant directory
204 std::string dirname="";
205 if(rTr.SourceMode()==TokenReader::File)
206 dirname=ExtractDirectory(rTr.FileName());
207 // report
208 FD_DX("ParallelExecutor(" << this << ")::DoReadGenerators(tr): dirname " << dirname);
209 // read section
210 rTr.ReadBegin("Generators");
211 Token token;
212 while(!rTr.Eos("Generators")) {
213 rTr.Peek(token);
214 // is it a file name?
215 if(token.Type()==Token::String) {
216 Insert(PrependPath(dirname,token.StringValue()));
217 rTr.Get(token);
218 continue;
219 }
220 // is it a generator?
221 if(token.Type()==Token::Begin)
222 if(token.StringValue()=="Generator") {
223 TimedGenerator gen;
224 gen.Read(rTr);
225 Insert(gen);
226 continue;
227 }
228 // else report error
229 std::stringstream errstr;
230 errstr << "Invalid token" << rTr.FileLine();
231 throw Exception("ParallelExecutor::DoReadGenerators", errstr.str(), 502);
232 }
233 rTr.ReadEnd("Generators");
234}
235
236// Alphabet()
238 return mAlphabet;
239}
240
241// ComputeEnabled() fake const
243 ParallelExecutor* fakeconst = const_cast<ParallelExecutor*>(this);
244 fakeconst->ComputeEnabledNonConst();
245}
246
247// ComputeEnabled()
249 iterator xit;
250 // compute members (may remove this)
251 FD_DX("ParallelExecutor(" << this << ")::ComputeEnabled(): members");
252 for(xit=mExecutors.begin(); xit != mExecutors.end(); xit++)
253 xit->IsDeadlocked();
254 // compute etime
255 FD_DX("ParallelExecutor(" << this << ")::ComputeEnabled(): time");
257 for(xit=mExecutors.begin(); xit != mExecutors.end(); xit++)
258 mETime.Intersect(xit->EnabledTime());
259 // compute e/d events
260 FD_DX("ParallelExecutor(" << this << ")::ComputeEnabled(): e/d events");
261 mDEvents.Name("DisabledEvents");
262 mDEvents.Clear();
263 for(xit=mExecutors.begin(); xit != mExecutors.end(); xit++)
264 mDEvents.InsertSet(xit->DisabledEvents());
266 mEEvents.Name("EnabledEvents");
268 // compute einterval // TODO: this is conservative
269 FD_DX("ParallelExecutor(" << this << ")::ComputeEnabled(): interval");
271 for(xit=mExecutors.begin(); xit != mExecutors.end(); xit++)
272 mEInterval.Intersect(xit->EnabledInterval());
273 // done
274 mEValid=true;
275}
276
277// EnabledTime(void)
279 if(!mEValid) ComputeEnabled();
280 return mETime;
281
282}
283
284// EnabledEvents(void)
286 if(!mEValid) ComputeEnabled();
287 return mEEvents;
288}
289
290// DisabledEvents(void)
292 if(!mEValid) ComputeEnabled();
293 return mDEvents;
294}
295
296// EnabledInterval(void)
298 if(!mEValid) ComputeEnabled();
299 return mEInterval;
300}
301
302// EnabledEventInterval(event)
304 TimeInterval retInterval;
305 retInterval.SetPositive();
306 Iterator xit;
307 for(xit=Begin(); xit != End(); xit++){
308 retInterval.Intersect(xit->EnabledEventTime(event));
309 }
310 FD_DX("ParalelExecutor(" << this << ")::EnabledEventTime(" << event << "):"<< retInterval.Str());
311 return retInterval;
312}
313
314// EnabledGuardInterval(event)
316 TimeInterval retInterval;
317 retInterval.SetPositive();
318 Iterator xit;
319 for(xit=Begin(); xit != End(); xit++){
320 retInterval.Intersect(xit->EnabledGuardTime(event));
321 }
322 FD_DX("ParalelExecutor(" << this << ")::EnabledGuardTime(" << event << "):"<< retInterval.Str());
323 return retInterval;
324}
325
326//GetCurrentStateVec
330
331// get current state
335
336// set current state
338 FD_DX("ParalelExecutor(" << this << ")::CurrentParallelState(ptstate): set " << PTSStr(ptstate));
339 // prepare
340 if(ptstate.State.size()!=Size()) return false;
341 if(ptstate.Clock.size()!=Size()) return false;
342 bool res=true;
344 // loop and set for all executors
345 int i=0;
346 for(iterator xit=mExecutors.begin(); xit!=mExecutors.end(); xit++, i++){
347 TimedState tstate;
348 tstate.State=ptstate.State[i];
349 tstate.ClockValue=ptstate.Clock[i];
350 res = res && xit->CurrentTimedState(tstate);
351 }
352 // reject
353 if(!res) {
355 return false;
356 }
357 // reset time (dont call the virtual fncts here)
360 // fix state rep
362 // invalidate
363 mEValid=false;
364 mRecentEvent=0;
365 FD_DX("ParalelExecutor(" << this << ")::CurrentParallelState(ptstate): done");
366 return true;
367}
368
369
370
371// ExecuteTime(time)
373 if(mCurrentTime>=Time::Max()) return false;
374 if(time==0) return true;
375 if(!mEValid) ComputeEnabled();
376 if(!mETime.In(time) && !((time==Time::Max()) && mETime.UBinf()) ) {
377 FD_DX("ParalelExecutor(" << this << ")::ExecuteTime(time): execution of " << time
378 << " conflicts with enabled status " );
379 return false;
380 }
381 // progress current time
382 mCurrentTime += time;
383 // fix infinity
384 if(time==Time::Max()) mCurrentTime=Time::Max();
385 // progress members
386 bool success=true;
387 for(iterator xit=mExecutors.begin(); xit != mExecutors.end(); xit++)
388 success &= xit->ExecuteTime(time);
389 // update state
391 // indicate invalid (conservative)
392 mEValid=false;
393 return success;
394}
395
396// ExecuteEvent(event)
398 if(!mEValid) ComputeEnabled();
399 if(!mEEvents.Exists(event)) {
400 FD_DX("ParallelExecutor(" << this << ")::ExecuteEvent(): execution of event " << EStr(event)
401 << " conflicts with enabled status " );
402 return false;
403 }
404 // progress members
405 bool success=true;
406 for(iterator xit=mExecutors.begin(); xit != mExecutors.end(); xit++)
407 if(xit->Generator().ExistsEvent(event))
408 success &= xit->ExecuteEvent(event);
409 if(!success) {
410 // should throw exception
411 FD_DX("ParallelExecutor(" << this << ")::ExecuteEvent(): execution of event " << EStr(event)
412 << " conflicts with internal state data " );
413 return false;
414 }
415 // progress current time
416 mCurrentStep += 1;
417 // update state
419 // record event
420 mRecentEvent=event;
421 // invalidate
422 mEValid=false;
423 return true;
424}
425
426// CurrentTime(time)
428 mCurrentTime=time;
429 for(iterator xit=mExecutors.begin(); xit != mExecutors.end(); xit++)
430 xit->CurrentTime(time);
431 mEValid=false;
432}
433
434// CurrentTime()
438
439// CurrentStep(step)
441 mCurrentStep=step;
442 for(iterator xit=mExecutors.begin(); xit != mExecutors.end(); xit++)
443 xit->CurrentStep(0);
444 mEValid=false;
445}
446
447// CurrentStep()
449 return mCurrentStep;
450}
451
452// IsDeadlocked()
454 if(!mEValid) ComputeEnabled();
455 if(!mEEvents.Empty()) return false;
456 if(!(mETime.UB()<=0)) return false;
457 return true;
458}
459
460// PTSStr(ptstate)
461std::string ParallelExecutor::PTSStr(const ParallelTimedState& ptstate) const {
462 if(Size()!=ptstate.State.size()) return("(undef)");
463 std::stringstream res;
464 res << "(state ";
465 for(unsigned int i=0; i< Size(); i++){
466 res << mExecutors[i].Generator().SStr(ptstate.State[i]);
467 if(i+1<Size()) res << " x ";
468 }
469 res << ") (clocks (";
470 for(unsigned int i=0; i< Size(); i++){
471 const Executor* execp=&mExecutors[i];
472 ClockSet::Iterator cit;
473 for(cit=execp->Generator().ClocksBegin();cit!=execp->Generator().ClocksEnd();cit++){
474 if(cit!=execp->Generator().ClocksBegin()) res << " ";
475 res << CStr(*cit) << "=";
476 std::map<Idx,Time::Type>::const_iterator cvit=ptstate.Clock[i].find(*cit);
477 if(cvit!=ptstate.Clock[i].end()) res << cvit->second;
478 else res << "undef";
479 }
480 res<<")";
481 if(i+1<Size()) res << " x (";
482 }
483 res << ")";
484 return res.str();
485}
486
487// PSStr(pstate)
488std::string ParallelExecutor::PSStr(const ParallelState& pstate) const {
489 if(Size()!=pstate.size()) return("(undef)");
490 std::stringstream res;
491 res << "(state ";
492 for(unsigned int i=0; i< Size(); i++){
493 res << mExecutors[i].Generator().SStr(pstate[i]);
494 if(i+1<Size()) res << " x ";
495 }
496 res << ")";
497 return res.str();
498}
499
500// TEStr(tevent)
501std::string ParallelExecutor::TEStr(const TimedEvent& tevent) const {
502 if(Size()==0) return "(undef)";
503 return Begin()->TEStr(tevent);
504}
505
506// EStr(event)
507std::string ParallelExecutor::EStr(Idx event) const {
508 if(Size()==0) return "(undef)";
509 return Begin()->EStr(event);
510}
511
512// CStr(clock)
513std::string ParallelExecutor::CStr(Idx clock) const {
514 if(Size()==0) return "(undef)";
515 return Begin()->CStr(clock);
516}
517
518// CurrentParallelTimedStateStr()
522
523// CurrentParallelTimedStateStr()
527
528//ActiveEventSet
530 EventSet retEventSet=Alphabet();
531 Iterator xit;
532 int i;
533 for(i=0, xit=Begin(); xit!=End(); xit++, i++) {
534 retEventSet.EraseSet( xit->Generator().Alphabet() - xit->Generator().ActiveEventSet(stateVec[i]));
535 }
536 return retEventSet;
537}
538
539//Active(Idx)
543
544//Active(Idx, ParallelState)
545bool ParallelExecutor::Active(Idx ev, const ParallelState& stateVec) const {
546 Iterator xit;
547 int i;
548 for(xit=Begin(), i=0; xit!=End(); ++xit, i++){
549 if(xit->Generator().Alphabet().Exists(ev))
550 if(xit->Generator().TransRelBegin(stateVec[i],ev)
551 == xit->Generator().TransRelEnd(stateVec[i],ev))
552 return false;
553 }
554 return true;
555}
556
557
558//DoWrite(rTr,rLabel,pContext)
559void ParallelExecutor::ParallelTimedState::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
560 // allow for two versions only
561 std::string label=rLabel;
562 if(label!="DiscreteState")
563 if(label!="TimedState")
564 label="TimedState";
565 FD_DC("ParallelExecutor::ParallelTimedState::DoWrite(): section " << rLabel << " context " << pContext);
566 // figure context
567 const ParallelExecutor* exe=dynamic_cast<const ParallelExecutor*>(pContext);
568 if(exe) if(exe->Size()!=State.size()) exe=0;
569 if(exe) if(exe->Size()!=Clock.size()) exe=0;
570 // do write
571 if(rLabel=="TimedState") rTw.WriteBegin("TimedState");
572 // discrete state
573 rTw.WriteBegin("DiscreteState");
574 for(unsigned int i=0; i< State.size(); i++) {
575 std::string name="";
576 if(exe) name=exe->At(i).StateName(State.at(i));
577 if(name!="") rTw.WriteString(name);
578 else rTw.WriteInteger(State.at(i));
579 };
580 rTw.WriteEnd("DiscreteState");
581 // figure whether to write clocks
582 bool doclocks=false;
583 if(rLabel=="TimedState")
584 for(unsigned int i=0; i< Clock.size(); i++)
585 if(Clock.at(i).size()>0) doclocks=true;
586 // write clocks
587 if(doclocks) {
588 rTw.WriteBegin("ClockMaps");
589 for(unsigned int i=0; i< Clock.size(); i++) {
590 rTw.WriteBegin("ClockMap");
591 std::map<Idx,Time::Type>::const_iterator cit;
592 for(cit=Clock.at(i).begin(); cit!=Clock.at(i).end(); cit++) {
593 std::string name="";
594 if(exe) name=exe->At(i).Generator().ClockName(cit->first);
595 if(name!="") rTw.WriteString(name);
596 else rTw.WriteInteger(cit->first);
597 rTw.WriteInteger(cit->second);
598 }
599 rTw.WriteEnd("ClockMap");
600 }
601 rTw.WriteEnd("ClockMaps");
602 }
603 // do write end
604 if(rLabel=="TimedState") rTw.WriteEnd("TimedState");
605}
606
607//DoRead(rTr,rLabel,pContext)
608 void ParallelExecutor::ParallelTimedState::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
609 (void) rLabel; (void) pContext; (void) rTr;
610 FD_DC("ParallelExecutor::ParallelTimedState::DoRead()");
611}
612
613
614} // namespace faudes
615
616
#define FD_DC(message)
#define FAUDES_TYPE_IMPLEMENTATION(ftype, ctype, cbase)
Definition cfl_types.h:1017
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 DoMove(ParallelExecutor &rSrc)
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
TimeInterval EnabledEventTime(Idx event) const
void DoCopy(const ParallelExecutor &rSrc)
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 & Copy(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.34d --- 2026.03.11 --- c++ api documentaion by doxygen