-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstatemachine.c
45 lines (41 loc) · 1.28 KB
/
statemachine.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include "statemachine.h"
#include <string.h>
void StateMachineInit(StateMachine_t *a_sm, SmRawState_t a_start_state,
void *a_context)
{
SM_ASSERT(a_sm != NULL);
SM_ASSERT(a_start_state != NULL);
memset(a_sm, 0, sizeof(StateMachine_t));
a_sm->m_curr_state.m_state = a_start_state;
a_sm->m_context = a_context;
}
bool StateMachineRun(StateMachine_t *a_sm)
{
SM_ASSERT(a_sm != NULL);
SmRawState_t curr = a_sm->m_curr_state.m_state;
SM_ASSERT(curr != NULL);
a_sm->m_next_state = NULL;
SmState_t next = curr(a_sm);
if (next.m_state == SmYieldSentinel)
{
// Stay in the same state if the client yielded.
next.m_state = curr;
}
else
{
// Clients MAY NOT transition to the current state, they MUST yield.
SM_ASSERT(next.m_state != curr);
// This is NULL if the state body reached SM_EXIT() without first
// calling SM_YIELD() or SM_TRANSITION(), which is disallowed.
SM_ASSERT(next.m_state != NULL);
}
a_sm->m_prev_state = curr;
a_sm->m_curr_state = next;
return (curr != next.m_state);
}
SmState_t SmYieldSentinel(StateMachine_t *a_sm)
{
(void)a_sm;
SM_ASSERT(0); // Should never get here.
return (SmState_t){.m_state = NULL};
}