Skip to content

Commit ec5fd24

Browse files
committed
Seems working, taking snapshot. Many refactorings
1 parent 84dc7d8 commit ec5fd24

File tree

13 files changed

+663
-318
lines changed

13 files changed

+663
-318
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,8 @@ example-ping-pong/ping_sm.o
99
example-ping-pong/ping_test.o
1010
example-ping-pong/ping_test
1111
dist
12+
demo-project/engineer_demo
13+
demo-project/engineer_demo.o
14+
demo-project/engineer_sm.o
15+
demo-project/engineer_test
16+
demo-project/engineer_test.o

demo-project/SConscript

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
env = Environment()
2+
3+
LIBS =''
4+
5+
common_libs = ['gtest_main', 'gtest', 'pthread']
6+
env.Append( LIBS = common_libs )
7+
env.Append( CPPPATH = ['../'])
8+
9+
env.Append(CCFLAGS=['-fsanitize=address,undefined',
10+
'-fno-omit-frame-pointer'],
11+
LINKFLAGS='-fsanitize=address,undefined')
12+
13+
env.Program('engineer_test', ['engineer_sm.cpp', 'engineer_test.cpp'],
14+
LIBS, LIBPATH='/opt/gtest/lib:/usr/local/lib', CXXFLAGS="-std=c++17")
15+
16+
env.Program('engineer_demo', ['engineer_sm.cpp', 'engineer_demo.cpp'],
17+
LIBS, LIBPATH='/opt/gtest/lib:/usr/local/lib', CXXFLAGS="-std=c++17")
18+

demo-project/engineer.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,26 @@ const engineerMachine = Machine({
1313
exit: 'morningRoutine',
1414
on: {
1515
'TIMER': { target: 'working', actions: ['startHungryTimer', 'startTiredTimer'] },
16-
'TIRED': { target: 'sleeping' }
1716
}
1817
},
1918
working: {
20-
entry: ['checkEmail', 'startHungryTimer' ],
19+
entry: ['checkEmail', 'startHungryTimer', 'checkIfItsWeekend' ],
2120
on: {
2221
'HUNGRY': { target: 'eating', actions: ['checkEmail']},
23-
'TIRED': { target: 'sleeping' }
22+
'TIRED': { target: 'sleeping' },
23+
'ENOUGH': { target: 'weekend' }
2424
},
2525
},
2626
eating: {
2727
entry: 'startShortTimer',
28-
exit: [ 'checkEmail', 'startHungryTimer', 'startTiredTimer' ],
28+
exit: [ 'checkEmail', 'startHungryTimer' ],
2929
on: {
3030
'TIMER': { target: 'working', actions: ['startHungryTimer'] },
3131
'TIRED': { target: 'sleeping' }
3232
}
33+
},
34+
weekend: {
35+
type: 'final',
3336
}
3437
}
3538
});

demo-project/engineer_demo.cpp

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,26 @@ struct EngineerSpec {
2727
using EventTimerPayload = std::nullptr_t;
2828
using EventHungryPayload = std::nullptr_t;
2929
using EventTiredPayload = std::nullptr_t;
30+
using EventEnoughPayload = std::nullptr_t;
3031

3132
/**
3233
* This block is for transition actions.
3334
*/
34-
static void startHungryTimer (EngineerSM<EngineerSpec>* sm, EventTimerPayload* payload) {
35+
static void startHungryTimer (EngineerSM<EngineerSpec>* sm, std::shared_ptr<EventTimerPayload> payload) {
3536
std::clog << "Start HungryTimer from timer event" << std::endl;
3637
startTimer([sm] {
3738
std::clog << "Ok, I'm hungry" << std::endl;
3839
sm->postEventHungry(std::nullptr_t());
39-
}, 100);
40+
}, 1000);
4041
}
41-
static void startTiredTimer (EngineerSM<EngineerSpec>* sm, EventTimerPayload* payload) {
42+
static void startTiredTimer (EngineerSM<EngineerSpec>* sm, std::shared_ptr<EventTimerPayload> payload) {
4243
std::clog << "Start TiredTimer from timer event" << std::endl;
4344
startTimer([sm] {
4445
std::clog << "Ok, I'm tired" << std::endl;
4546
sm->postEventTired(std::nullptr_t());
46-
}, 1000);
47+
}, 2000);
4748
}
48-
static void checkEmail (EngineerSM<EngineerSpec>* sm, EventHungryPayload* payload) {
49+
static void checkEmail (EngineerSM<EngineerSpec>* sm, std::shared_ptr<EventHungryPayload> payload) {
4950
std::clog << "Checking Email, while being hugry! ok..." << std::endl;
5051
}
5152

@@ -57,25 +58,40 @@ struct EngineerSpec {
5758
startTimer([sm] {
5859
std::clog << "Hey wake up" << std::endl;
5960
sm->postEventTimer(std::nullptr_t());
60-
}, 1000);
61+
}, 2000);
6162
}
6263
static void checkEmail (EngineerSM<EngineerSpec>* sm) {
6364
std::clog << "Checking Email, hmmm..." << std::endl;
6465
}
66+
67+
static void checkIfItsWeekend (EngineerSM<EngineerSpec>* sm) {
68+
bool post = false;
69+
sm->accessContextLocked([&post] (StateMachineContext& userContext) {
70+
if (userContext.wakeUpCount >= 6) {
71+
std::clog << "Wow it's weekend!" << std::endl;
72+
post = true;
73+
}
74+
});
75+
if (post) {
76+
// To avoid deadlock this should be invoked outside of the accessContextLocked() method.
77+
sm->postEventEnough(std::nullptr_t());
78+
}
79+
}
80+
6581
static void startHungryTimer (EngineerSM<EngineerSpec>* sm) {
6682
std::clog << "Start HungryTimer" << std::endl;
6783
startTimer([sm] {
6884
std::clog << "Ok, I'm hungry" << std::endl;
6985
sm->postEventHungry(std::nullptr_t());
70-
}, 100);
86+
}, 800);
7187
}
7288

7389
static void startShortTimer (EngineerSM<EngineerSpec>* sm) {
7490
std::clog << "Start short Timer" << std::endl;
7591
startTimer([sm] {
7692
std::clog << "Hey, timer is ringing." << std::endl;
7793
sm->postEventTimer(std::nullptr_t());
78-
}, 10);
94+
}, 100);
7995
}
8096

8197
static void morningRoutine (EngineerSM<EngineerSpec>* sm) {
@@ -101,13 +117,11 @@ int main(int argc, char** argv) {
101117
// Kick off the state machine with a timer event...
102118
stateMachine.postEventTimer(std::nullptr_t());
103119

104-
int wakeUpCount = 0; // We end the week after waking up 7 times.
105-
while (wakeUpCount < 7) {
106-
stateMachine.accessContextLocked([&wakeUpCount] (engineer_demo::EngineerContext& userContext) {
107-
wakeUpCount = userContext.wakeUpCount;
108-
});
120+
while (!stateMachine.isTerminated()) {
109121
std::this_thread::sleep_for(std::chrono::milliseconds(100));
110-
stateMachine.postEventTimer(std::nullptr_t());
111122
}
123+
std::clog << "State machine is terminated" << std::endl;
124+
// Let outstanding timers to expire, simplified approach for the demo.
125+
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
112126
return 0;
113127
}

demo-project/engineer_sm.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ std::string EngineerSMStateToString(EngineerSMState state) {
1717
return "EngineerSMState::working";
1818
case EngineerSMState::eating:
1919
return "EngineerSMState::eating";
20+
case EngineerSMState::weekend:
21+
return "EngineerSMState::weekend";
2022
default:
2123
return "ERROR";
2224
}
@@ -33,6 +35,7 @@ bool isValidEngineerSMState(EngineerSMState state) {
3335
if (state == EngineerSMState::sleeping) { return true; }
3436
if (state == EngineerSMState::working) { return true; }
3537
if (state == EngineerSMState::eating) { return true; }
38+
if (state == EngineerSMState::weekend) { return true; }
3639
return false;
3740
}
3841

@@ -42,10 +45,12 @@ std::string EngineerSMEventToString(EngineerSMEvent event) {
4245
return "UNDEFINED";
4346
case EngineerSMEvent::TIMER:
4447
return "EngineerSMEvent::TIMER";
45-
case EngineerSMEvent::TIRED:
46-
return "EngineerSMEvent::TIRED";
4748
case EngineerSMEvent::HUNGRY:
4849
return "EngineerSMEvent::HUNGRY";
50+
case EngineerSMEvent::TIRED:
51+
return "EngineerSMEvent::TIRED";
52+
case EngineerSMEvent::ENOUGH:
53+
return "EngineerSMEvent::ENOUGH";
4954
default:
5055
return "ERROR";
5156
}
@@ -54,8 +59,9 @@ std::string EngineerSMEventToString(EngineerSMEvent event) {
5459
bool isValidEngineerSMEvent(EngineerSMEvent event) {
5560
if (event == EngineerSMEvent::UNDEFINED_OR_ERROR_EVENT) { return true; }
5661
if (event == EngineerSMEvent::TIMER) { return true; }
57-
if (event == EngineerSMEvent::TIRED) { return true; }
5862
if (event == EngineerSMEvent::HUNGRY) { return true; }
63+
if (event == EngineerSMEvent::TIRED) { return true; }
64+
if (event == EngineerSMEvent::ENOUGH) { return true; }
5965
return false;
6066
}
6167

@@ -92,8 +98,6 @@ EngineerSMValidTransitionsFromSleepingState() {
9298
static const auto* transitions = new const std::vector<EngineerSMTransitionToStatesPair> {
9399
{ EngineerSMEvent::TIMER, {
94100
EngineerSMState::working } },
95-
{ EngineerSMEvent::TIRED, {
96-
EngineerSMState::sleeping } },
97101
};
98102
return *transitions;
99103
}
@@ -106,6 +110,8 @@ EngineerSMValidTransitionsFromWorkingState() {
106110
EngineerSMState::eating } },
107111
{ EngineerSMEvent::TIRED, {
108112
EngineerSMState::sleeping } },
113+
{ EngineerSMEvent::ENOUGH, {
114+
EngineerSMState::weekend } },
109115
};
110116
return *transitions;
111117
}
@@ -122,6 +128,14 @@ EngineerSMValidTransitionsFromEatingState() {
122128
return *transitions;
123129
}
124130

131+
// static
132+
const std::vector<EngineerSMTransitionToStatesPair>&
133+
EngineerSMValidTransitionsFromWeekendState() {
134+
static const auto* transitions = new const std::vector<EngineerSMTransitionToStatesPair> {
135+
};
136+
return *transitions;
137+
}
138+
125139

126140

127141
} // namespace engineer_demo

0 commit comments

Comments
 (0)