Compare commits

...

14 Commits

9 changed files with 236 additions and 42 deletions

BIN
UML/event.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

55
UML/event.puml Normal file
View File

@@ -0,0 +1,55 @@
@startuml
participant Behavior as b
participant Dispatcher as d
entity Event as e
participant EventQueue as eq
queue "EventQueue::queue_" as q
== Create an Event ==
|||
?->> b ++ : GEN
b -> e ** : new
b -> b --++ : pushEvent
e -> b : getBehavior
b --> e ++: setBehavior
e --> b --
b -> d ++ : getDispatcher
d --> b
b -> d -- : pushEvent
d ->? -- : push
|||
|||
== Push Event ==
|||
?->> d ++: pushEvent
d -> eq--++: push
eq -> q ++
q --> eq
eq -> q -- : pushEndQueue
|||
|||
== Dispatch ==
|||
?->> d ++: executeOnce
d -> q : getFront
q -> e ++
e --> q
q --> d : event
d -> q : pop
deactivate q
d -> d --++ : dispatchEvent
d -> b ++ : getBehavior
b --> d
d -> b -- : process
b -> b--: processEvent
destroy e
@enduml

BIN
UML/timeAlgorithme.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

27
UML/timeAlgorithme.puml Normal file
View File

@@ -0,0 +1,27 @@
@startuml
start
:newTime = 0
totalTime = 0
isEnd = it == list.end()
lastTime = 0;
#tomato:if (!isEnd) then (not end)
#tomato:totalTime += it.getRelTicks();
endif
while ( !isEnd && (totalTime <= newTime) ) is (goForward)
:isEnd = (++it == list.end());
:lastTime = totalTime;
#tomato:if (!isEnd) then (not end)
#tomato:totalTime += it.getRelTicks();
endif
endwhile
#tomato:if (!isEnd) then (not end)
#tomato:subRelTicks(newTime- lastTime);
endif
:it.setRelTicks(newTime - lastTime);
:insert(it, newTimeout);
@enduml

BIN
UML/timeout.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

62
UML/timeout.puml Normal file
View File

@@ -0,0 +1,62 @@
@startuml
participant "Behavior::StateMachine" as sm
participant Dispatcher as d
participant TimeoutManager as tm
entity "Event::Timeout" as t
queue "TimeoutManager::timeouts_" as timeouts
autoactivate off
|||
|||
== Schedule timeout ==
|||
sm -> sm++ : scheduleTimeout
sm -> d ++: getDispatcher
d --> sm --: dispatcher
sm -> d --++ : scheduleTimeout
d -> tm ++: getTimeoutManager
tm --> d --: timeoutManager
d -> tm --++ : scheduleTimeout
tm -> t ** : new
t --> tm
tm -> timeouts --++: insert
|||
|||
== Decrement timeout (and dispatch) ==
|||
loop every tickInterval
?->> tm ++: tick
tm -> timeouts : getFront
timeouts -> t ++
t --> timeouts
timeouts --> tm : timeout
tm -> t --: decrement
end
|||
note left t
When timeout is 0,
dispatch event
end note
t -> timeouts : pop
deactivate timeouts
t ->? --: pushEvent
|||
|||
== Unschedule timeout ==
|||
sm -> sm++ : unscheduleTimeout
sm -> d ++: getDispatcher
d --> sm --: dispatcher
sm -> d --++ : unscheduleTimeout
d -> tm ++: getTimeoutManager
tm --> d --: timeoutManager
d -> tm --++ : unscheduleTimeout
tm -> timeouts --: erase
timeouts -> t !!
@enduml

View File

@@ -7,30 +7,18 @@
- Demonstrate the right functioning of the XF by comparing and documenting the output created by the tests running on the *Embedded System* - Demonstrate the right functioning of the XF by comparing and documenting the output created by the tests running on the *Embedded System*
# Time Algorithm # Time Algorithm
``` mermaid
flowchart TD
insert[it.subRelTick\ninsert]
A(Start)--> B[relTime = 0]
B --> C{relTime < desireTime}
C --> |Yes| D[it++]
D --> E{ End ? }
E --> |No| F[it.getRelTick]
F --> C
E --> |Yes| insert
```
```flow
st=>start: Start:>http://google.com[blank]
``` <img src="./UML/timeAlgorithme.png">
```sequence # Sequence Diagrams
Andrew -> China : Says Hello ## Timeout
``` <img src="./UML/timeout.png">
## Event
<img src="./UML/event.png">
# Tests # Tests
## Test 1 ## Test 1
@@ -43,7 +31,7 @@ The Test Factory (TestFactory01) instantiates 2 objects:
<details> <details>
<summary>QT result ✅</summary> <summary>QT result ✅</summary>
![result.PNG](test-bench%2Ftest1%2Fide-qtcreator-test1-idf%2Fresult.PNG) <img src="./test-bench/test1/ide-qtcreator-test1-idf/result.PNG">
This test is successfully passed This test is successfully passed
@@ -51,7 +39,7 @@ This test is successfully passed
<details> <details>
<summary>STM result ✅</summary> <summary>STM result ✅</summary>
![result.png](test-bench%2Ftest1%2Fide-cubeide-test1-idf%2Fresult.png) <img src="./test-bench/test1/ide-cubeide-test1-idf/result.png">
</details> </details>
@@ -63,7 +51,7 @@ Weather or not the state machine should be deleted is handled with the 'deleteOn
<details> <details>
<summary>QT result ✅</summary> <summary>QT result ✅</summary>
![result.PNG](test-bench%2Ftest2%2Fide-qtcreator-test2-idf%2Fresult.PNG) <img src="./test-bench/test2/ide-qtcreator-test2-idf/result.PNG">
This test is successfully passed This test is successfully passed
@@ -71,7 +59,7 @@ This test is successfully passed
<details> <details>
<summary>STM result ✅</summary> <summary>STM result ✅</summary>
![result.png](test-bench%2Ftest2%2Fide-cubeide-test2-idf%2Fresult.png) <img src="./test-bench/test2/ide-cubeide-test2-idf/result.png">
</details> </details>
@@ -81,7 +69,7 @@ This test checks basic event handling in state machines. In this example the Sta
<details> <details>
<summary>QT result ✅</summary> <summary>QT result ✅</summary>
![result.PNG](test-bench%2Ftest3%2Fide-qtcreator-test3-idf%2Fresult.PNG) <img src="./test-bench/test3/ide-qtcreator-test3-idf/result.PNG">
This test is successfully passed This test is successfully passed
@@ -89,7 +77,7 @@ This test is successfully passed
<details> <details>
<summary>STM result ✅</summary> <summary>STM result ✅</summary>
![result.png](test-bench%2Ftest3%2Fide-cubeide-test3-idf%2Fresult.png) <img src="./test-bench/test3/ide-cubeide-test3-idf/result.png">
</details> </details>
@@ -99,7 +87,7 @@ Tests if timeouts are correctly cancelled. When leaving a state with a transitio
<details> <details>
<summary>QT result ✅</summary> <summary>QT result ✅</summary>
![result.PNG](test-bench%2Ftest4%2Fide-qtcreator-test4-idf%2Fresult.PNG) <img src="./test-bench/test4/ide-qtcreator-test4-idf/result.PNG">
This test is successfully passed This test is successfully passed
@@ -107,7 +95,7 @@ This test is successfully passed
<details> <details>
<summary>STM result ✅</summary> <summary>STM result ✅</summary>
![result.png](test-bench%2Ftest4%2Fide-cubeide-test4-idf%2Fresult.png) <img src="./test-bench/test4/ide-cubeide-test4-idf/result.png">
</details> </details>
@@ -117,7 +105,7 @@ With this test multiple timeouts are added to the XFTimeoutManager list at the s
<details> <details>
<summary>QT result ✅</summary> <summary>QT result ✅</summary>
![result.PNG](test-bench%2Ftest5%2Fide-qtcreator-test5-idf%2Fresult.PNG) <img src="./test-bench/test5/ide-qtcreator-test5-idf/result.PNG">
This test is successfully passed This test is successfully passed
@@ -125,7 +113,7 @@ This test is successfully passed
<details> <details>
<summary>STM result ✅</summary> <summary>STM result ✅</summary>
![result.png](test-bench%2Ftest5%2Fide-cubeide-test5-idf%2Fresult.png) <img src="./test-bench/test5/ide-cubeide-test5-idf/result.png">
</details> </details>

View File

@@ -16,6 +16,12 @@ void XFBehavior::startBehavior() {
GEN(XFInitialEvent()); GEN(XFInitialEvent());
} }
/**
* @brief Pushes the given event to the dispatcher.
*
* If the event has no behavior assigned, the behavior of this object is assigned.
* @param pEvent Event to push to the dispatcher.
*/
void XFBehavior::pushEvent(XFEvent *pEvent) { void XFBehavior::pushEvent(XFEvent *pEvent) {
if(pEvent->getBehavior()==nullptr) { if(pEvent->getBehavior()==nullptr) {
pEvent->setBehavior(this); pEvent->setBehavior(this);
@@ -39,6 +45,13 @@ interface::XFDispatcher *XFBehavior::getDispatcher() {
return interface::XFDispatcher::getInstance(); return interface::XFDispatcher::getInstance();
} }
/**
* @brief Returns a reference to the actually processed timeout.
*
* Will work only if the current event is of type IXFEvent::Timeout.
*
* @return Pointer to the currently processed timeout or nullptr if the current event is not a timeout.
*/
const XFTimeout *XFBehavior::getCurrentTimeout() { const XFTimeout *XFBehavior::getCurrentTimeout() {
if(pCurrentEvent_->getEventType() == XFEvent::Timeout) { if(pCurrentEvent_->getEventType() == XFEvent::Timeout) {
return (XFTimeout*) this->pCurrentEvent_; return (XFTimeout*) this->pCurrentEvent_;
@@ -51,13 +64,33 @@ void XFBehavior::setCurrentEvent(const XFEvent *pEvent) {
this->pCurrentEvent_ = pEvent; this->pCurrentEvent_ = pEvent;
} }
/**
* @brief Processes the given event.
*
* The dispatcher calls this method every time a new event
* or timeout arrives. The process method stores the actual
* event using the #_pCurrentEvent and then calls
* processEvent().
*
* In case you intend to call process() inside your state machine you
* are doing something wrong! Call GEN() or pushEvent() instead!
*
* @param pEvent Event to process
* @return if the behavior is terminated (basically a boolean)
*/
XFBehavior::TerminateBehavior XFBehavior::process(const XFEvent *pEvent) { XFBehavior::TerminateBehavior XFBehavior::process(const XFEvent *pEvent) {
this->setCurrentEvent(pEvent); this->setCurrentEvent(pEvent);
// Get status of the event processing
XFEventStatus status = XFEventStatus::Unknown; XFEventStatus status = XFEventStatus::Unknown;
status = this->processEvent(); status = this->processEvent();
// Check if event was consumed and if it should be deleted
if(status == XFEventStatus::Consumed && pEvent->deleteAfterConsume()) { if(status == XFEventStatus::Consumed && pEvent->deleteAfterConsume()) {
delete pEvent; delete pEvent;
} }
// Check if the behavior is terminated and return the result
XFBehavior::TerminateBehavior terminateBehavior = false; XFBehavior::TerminateBehavior terminateBehavior = false;
if(status == XFEventStatus::Terminate) { if(status == XFEventStatus::Terminate) {
terminateBehavior = true; terminateBehavior = true;

View File

@@ -34,8 +34,28 @@ XFTimeoutManager::~XFTimeoutManager() {
void XFTimeoutManager::addTimeout(XFTimeout *pNewTimeout) { void XFTimeoutManager::addTimeout(XFTimeout *pNewTimeout) {
const int newTime = pNewTimeout->getInterval();
int totalTime = 0;
bool isEnd = true;
int lastTime = 0;
this->pMutex_->lock(); this->pMutex_->lock();
this->timeouts_.push_back(pNewTimeout); TimeoutList::iterator it = this->timeouts_.begin();
isEnd = (it == this->timeouts_.end());
if(!isEnd) totalTime += (*it)->getRelTicks();
while(!isEnd && (totalTime <= newTime)) {
isEnd = (++it == this->timeouts_.end());
lastTime = totalTime;
if(!isEnd) totalTime += (*it)->getRelTicks();
}
if(!isEnd) (*it)->substractFromRelTicks(newTime-lastTime);
pNewTimeout->setRelTicks(newTime-lastTime);
this->timeouts_.insert(it, pNewTimeout);
this->pMutex_->unlock(); this->pMutex_->unlock();
} }
@@ -70,22 +90,31 @@ void XFTimeoutManager::unscheduleTimeout(int32_t timeoutId, interface::XFBehavio
} }
void XFTimeoutManager::tick() { void XFTimeoutManager::tick() {
//Trace::out("[DEBUG] - Tick");
if(!this->timeouts_.empty()) { bool isEmpty = this->timeouts_.empty();
TimeoutList::iterator it; int rTime;
if(!isEmpty) {
this->pMutex_->lock(); this->pMutex_->lock();
for(it=this->timeouts_.begin(); it != this->timeouts_.end(); it++) {
if((*it)->getRelTicks() > 0) { XFTimeout* timeout = this->timeouts_.front();
(*it)->substractFromRelTicks(this->tickInterval_); timeout->substractFromRelTicks(tickInterval_);
} else { rTime = timeout->getRelTicks();
XFEvent* ev = *(it);
XFDispatcher::getInstance()->pushEvent(ev); while (!isEmpty && (rTime <= 0) ) {
it = this->timeouts_.erase(it);
it--; XFDispatcher::getInstance()->pushEvent(timeout);
} this->timeouts_.pop_front();
timeout = this->timeouts_.front();
isEmpty = this->timeouts_.empty();
if(!isEmpty) rTime = timeout->getRelTicks();
} }
this->pMutex_->unlock(); this->pMutex_->unlock();
} }
} }