IntrOS
Loading...
Searching...
No Matches
osstatemachine.h
1/******************************************************************************
2
3 @file IntrOS: osstatemachine.h
4 @author Rajmund Szymanski
5 @date 18.11.2025
6 @brief This file contains definitions for IntrOS.
7
8 ******************************************************************************
9
10 Copyright (c) 2018-2022 Rajmund Szymanski. All rights reserved.
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to
14 deal in the Software without restriction, including without limitation the
15 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16 sell copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included
20 in all copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 IN THE SOFTWARE.
29
30 ******************************************************************************/
31
32#ifndef __INTROS_HSM_H
33#define __INTROS_HSM_H
34
35#include "oskernel.h"
36#include "osclock.h"
37#include "oseventqueue.h"
38
44
45/* -------------------------------------------------------------------------- */
46
47enum
48{
49 hsmALL = 0,// the state action applies to all events
50 hsmStop, // stop the state machine
51 hsmExit, // exit from the state during transition
52 hsmEntry, // entry to the state during transition
53 hsmInit, // init the state after transition
54 hsmUser, // values less than hsmUser are reserved for the system
55};
56
60
61typedef struct __hsm_state hsm_state_t;
62
66
67typedef struct __hsm_action hsm_action_t;
68
72
73typedef struct __hsm hsm_t;
74
78
79typedef void hsm_handler_t(hsm_t *, unsigned);
80
84
85struct __hsm_state
86{
87 hsm_state_t * parent;
88 hsm_action_t * queue;
89};
90
91typedef struct __hsm_state hsm_state_id [];
92
111
112struct __hsm_action
113{
114 hsm_state_t * owner;
115 unsigned event;
116 hsm_state_t * target;
117 hsm_handler_t * handler;
118 hsm_action_t * next;
119};
120
121typedef struct __hsm_action hsm_action_id [];
122
126
127struct __hsm
128{
129 evq_t evq;
130 hsm_state_t * state;
131 hsm_action_t * action;
132 tsk_t * tsk;
133};
134
135typedef struct __hsm hsm_id [];
136
137/******************************************************************************
138 *
139 * Name : _HSM_STATE_INIT
140 *
141 * Description : create and initialize an hsm state object
142 *
143 * Parameters
144 * parent : pointer to parent state in the hsm tree (NULL for root)
145 *
146 * Return : hsm state object
147 *
148 * Note : for internal use
149 *
150 ******************************************************************************/
151
152#define _HSM_STATE_INIT( _parent ) \
153 { _parent, NULL }
154
159 * @param parent pointer to parent state in the hsm tree (NULL for root)
160 */
161
162#define OS_HSM_STATE( state, parent ) \
163 hsm_state_t state[] = { _HSM_STATE_INIT( parent ) }
164
165
166#define static_HSM_STATE( state, parent ) \
167 static hsm_state_t state[] = { _HSM_STATE_INIT( parent ) }
168
177 */
178
179#ifndef __cplusplus
180#define HSM_STATE_INIT( parent ) \
181 _HSM_STATE_INIT( parent )
182#endif
183
192 */
193
194#ifndef __cplusplus
195#define HSM_STATE_CREATE( parent ) \
196 { HSM_STATE_INIT ( parent ) }
197
198#define HSM_STATE_NEW \
199 HSM_STATE_CREATE
200#endif
201
202/******************************************************************************
203 *
204 * Name : _HSM_ACTION_INIT
205 *
206 * Description : create and initialize an hsm action object
207 *
208 * Parameters
209 * owner : action owner
210 * event : event value
211 * target : pointer to transition target state (NULL, if no transition)
212 * handler : event handler
213 *
214 * Return : hsm action object
215 *
216 * Note : for internal use
217 *
218 ******************************************************************************/
219
220#define _HSM_ACTION_INIT( _owner, _event, _target, _handler ) \
221 { _owner, _event, _target, _handler, NULL }
222
230 * @param handler event handler
231 */
232
233#define OS_HSM_ACTION( action, owner, event, target, handler ) \
234 hsm_action_t action[] = { _HSM_ACTION_INIT( owner, event, target, handler ) }
235
236
237#define static_HSM_ACTION( action, owner, event, target, handler ) \
238 static hsm_action_t action[] = { _HSM_ACTION_INIT( owner, event, target, handler ) }
239
251 */
252
253#ifndef __cplusplus
254#define HSM_ACTION_INIT( owner, event, target, handler ) \
255 _HSM_ACTION_INIT( owner, event, target, handler )
256#endif
257
269 */
270
271#ifndef __cplusplus
272#define HSM_ACTION_CREATE( owner, event, target, handler ) \
273 { HSM_ACTION_INIT ( owner, event, target, handler ) }
274
275#define HSM_ACTION_NEW \
276 HSM_ACTION_CREATE
277#endif
278
279/******************************************************************************
280 *
281 * Name : _HSM_INIT
282 *
283 * Description : create and initialize an hsm object
284 *
285 * Parameters
286 * limit : size of an hsm event queue (max number of stored events)
287 * data : hsm event queue data buffer
288 *
289 * Return : hsm object
290 *
291 * Note : for internal use
292 *
293 ******************************************************************************/
294
295#define _HSM_INIT( _limit, _data ) \
296 { _EVQ_INIT( _limit, _data ), NULL, NULL, NULL }
297
302 * @param limit size of an hsm event queue (max number of stored events)
303 */
304
305#define OS_HSM( hsm, limit ) \
306 static unsigned hsm##__buf[limit]; \
307 hsm_t hsm[] = { _HSM_INIT( limit, hsm##__buf ) }
308
310#define static_HSM( hsm, limit ) \
311 static unsigned hsm##__buf[limit]; \
312 static hsm_t hsm[] = { _HSM_INIT( limit, hsm##__buf ) }
313
322 */
323
324#ifndef __cplusplus
325#define HSM_INIT( limit ) \
326 _HSM_INIT( limit, _EVQ_DATA( limit ) )
327#endif
328
337 */
338
339#ifndef __cplusplus
340#define HSM_CREATE( limit ) \
341 { HSM_INIT ( limit ) }
342
343#define HSM_NEW \
344 HSM_CREATE
345#endif
346
347#ifdef __cplusplus
348extern "C" {
349#endif
350
357
358void hsm_initState( hsm_state_t *state, hsm_state_t *parent );
359
369
370void hsm_initAction( hsm_action_t *action, hsm_state_t *owner, unsigned event, hsm_state_t *target, hsm_handler_t *handler );
371
379
380void hsm_init( hsm_t *hsm, void *data, size_t bufsize );
381
387
388void hsm_link( hsm_action_t *action );
389
397
398void hsm_start( hsm_t *hsm, tsk_t *tsk, hsm_state_t *initState );
400#if OS_ATOMICS
402void hsm_startAsync( hsm_t *hsm, tsk_t *tsk, hsm_state_t *initState );
403#endif
404
413
414void hsm_reset( hsm_t *hsm );
417__STATIC_INLINE
418void hsm_kill( hsm_t *hsm ) { hsm_reset(hsm); }
419
432
433int hsm_give( hsm_t *hsm, unsigned event );
435#if OS_ATOMICS
437int hsm_giveAsync( hsm_t *hsm, unsigned event );
438#endif
439
454
455int hsm_sendFor( hsm_t *hsm, unsigned event, cnt_t delay );
456
469
470int hsm_sendUntil( hsm_t *hsm, unsigned event, cnt_t time );
471
484
485__STATIC_INLINE
486int hsm_send( hsm_t *hsm, unsigned event ) { return hsm_sendFor(hsm, event, INFINITE); }
488#if OS_ATOMICS
490int hsm_sendAsync( hsm_t *hsm, unsigned event );
491#endif
492
500
501void hsm_push( hsm_t *hsm, unsigned event );
502
510
511hsm_state_t *hsm_getState( hsm_t *hsm );
512
513#ifdef __cplusplus
514}
515#endif
516
517/* -------------------------------------------------------------------------- */
518
519#if defined(__cplusplus) && (__cplusplus >= 201402L)
520
521#include <iterator>
522#include <vector>
523
524namespace intros {
525
527 * @brief create and initialize an hsm state object
528 */
529
530struct State : public __hsm_state
533 constexpr
534 State(): __hsm_state _HSM_STATE_INIT( nullptr) {}
535 template<class S> constexpr
537 State( S& _parent ): __hsm_state _HSM_STATE_INIT(&_parent) {}
538
540 State( State&& _src ): __hsm_state(_src)
541 {
542 assert(_src.queue == nullptr);
543 }
544
545 State( const State& ) = delete;
546 State& operator=( State&& ) = delete;
547 State& operator=( const State& ) = delete;
548};
549
550template<unsigned> struct StateMachineT; // forward declaration
551
553 * @brief create and initialize an hsm action object
554 */
555
556struct Action : public __hsm_action
558 template<class S> constexpr
560 Action( S& _owner, unsigned _event, hsm_handler_t *_handler = nullptr ): __hsm_action _HSM_ACTION_INIT(&_owner, _event, nullptr, _handler) {}
561 template<class S> constexpr
563 Action( S& _owner, unsigned _event, S& _target, hsm_handler_t *_handler = nullptr ): __hsm_action _HSM_ACTION_INIT(&_owner, _event, &_target, _handler) {}
564#if __cplusplus >= 201402L
565 template<class S, class F> constexpr
567 Action( S& _owner, unsigned _event, F&& _handler ): __hsm_action _HSM_ACTION_INIT(&_owner, _event, nullptr, handler_), handler{_handler} {}
568 template<class S, class F> constexpr
570 Action( S& _owner, unsigned _event, S& _target, F&& _handler ): __hsm_action _HSM_ACTION_INIT(&_owner, _event, &_target, handler_), handler{_handler} {}
571#endif
572
574 Action( Action&& ) = default;
576 Action( const Action& ) = default;
577 Action& operator=( Action&& ) = delete;
578 Action& operator=( const Action& ) = delete;
579
580#if __cplusplus >= 201402L
581 static
582 void handler_( hsm_t *_hsm, unsigned _event ) { static_cast<Action*>(_hsm->action)->handler(_hsm, _event); }
583 std::function<void( hsm_t *, unsigned )> handler;
584#endif
585
586 private:
587
588 void link() { hsm_link(this); }
589
590 template<unsigned>
591 friend struct StateMachineT;
592};
593
599 */
600
601template<unsigned limit_ = 1>
602struct StateMachineT : public __hsm
603{
605 StateMachineT(): __hsm _HSM_INIT(limit_, data_), tab_{} {}
607 StateMachineT( const std::vector<Action>& _tab ): __hsm _HSM_INIT(limit_, data_), tab_{_tab} {}
608
610 StateMachineT( StateMachineT&& _src ): __hsm _HSM_INIT(limit_, data_), tab_(std::move(_src.tab_))
611 {
612 assert(_src.state == nullptr && _src.evq.count == 0 && _src.evq.obj.queue == nullptr);
613 (void) _src;
614 }
615
616 StateMachineT( const StateMachineT& ) = delete;
617 StateMachineT& operator=( StateMachineT&& ) = delete;
618 StateMachineT& operator=( const StateMachineT& ) = delete;
621 template<class S, typename... A>
622 void add ( S& _owner, unsigned _event, A&&... _args ) { tab_.emplace_back(_owner, _event, std::forward<A>(_args)...); }
623 /// add the actions to the table of the state machine
624 void add ( const std::vector<Action>& _tab ) { std::copy(std::begin(_tab), std::end(_tab), std::back_inserter(tab_)); }
625
626 void start ( tsk_t& _task, hsm_state_t& _init ) { for (auto& _action: tab_) _action.link();
627 hsm_start (this, &_task, &_init); }
628 void reset () { hsm_reset (this); }
629 void kill () { hsm_kill (this); }
630 int give ( unsigned _event ) { return hsm_give (this, _event); }
631 template<typename T>
632 int sendFor ( unsigned _event, const T& _delay ) { return hsm_sendFor (this, _event, Clock::count(_delay)); }
633 template<typename T>
634 int sendUntil ( unsigned _event, const T& _time ) { return hsm_sendUntil(this, _event, Clock::until(_time)); }
635 int send ( unsigned _event ) { return hsm_send (this, _event); }
636 void push ( unsigned _event ) { hsm_push (this, _event); }
637 hsm_state_t * getState () { return hsm_getState (this); }
638#if OS_ATOMICS
639
640 void startAsync( tsk_t& _task, hsm_state_t& _init ) { for (auto& _action: tab_) _action.link();
641 hsm_startAsync(this, &_task, &_init); }
642 int giveAsync ( unsigned _event ) { return hsm_giveAsync (this, _event); }
643 int sendAsync ( unsigned _event ) { return hsm_sendAsync (this, _event); }
644#endif
645
646 private:
647
648 unsigned data_[limit_];
649 std::vector<Action> tab_;
650};
651
652} // namespace
653#endif//__cplusplus
654
655/* -------------------------------------------------------------------------- */
656
658
659#endif//__INTROS_HSM_H
#define INFINITE
infinite waiting
Definition osbase.h:250
char data[]
message data
Definition osmessagequeue.h:54
int hsm_give(hsm_t *hsm, unsigned event)
try to transfer event data to the hsm event queue, don't wait if the hsm event queue is full
int hsm_giveAsync(hsm_t *hsm, unsigned event)
Async alias of hsm_give().
void hsm_kill(hsm_t *hsm)
alias of hsm_reset()
Definition osstatemachine.h:415
void hsm_reset(hsm_t *hsm)
reset the hsm object, stop the hsm event dispatcher and wake up all waiting tasks with 'E_STOPPED' ev...
int hsm_sendAsync(hsm_t *hsm, unsigned event)
Async alias of hsm_send().
void hsm_push(hsm_t *hsm, unsigned event)
transfer event data to the hsm event queue, remove the oldest event data if the hsm event queue is fu...
int hsm_send(hsm_t *hsm, unsigned event)
try to transfer event data to the hsm event queue, wait indefinitely while the hsm event queue is ful...
Definition osstatemachine.h:483
void hsm_startAsync(hsm_t *hsm, tsk_t *tsk, hsm_state_t *initState)
Async alias of hsm_start().
void hsm_link(hsm_action_t *action)
link hsm state action to the state action queue
int hsm_sendUntil(hsm_t *hsm, unsigned event, cnt_t time)
try to transfer event value to the hsm event queue, wait until given timepoint while the hsm event qu...
hsm_state_t * hsm_getState(hsm_t *hsm)
get current hsm state
int hsm_sendFor(hsm_t *hsm, unsigned event, cnt_t delay)
try to transfer event value to the hsm event queue, wait for given duration of time while the hsm eve...
void hsm_handler_t(hsm_t *, unsigned)
hierarchical state machine - event handler definition
Definition osstatemachine.h:79
void hsm_start(hsm_t *hsm, tsk_t *tsk, hsm_state_t *initState)
start hsm event dispatcher
void hsm_initAction(hsm_action_t *action, hsm_state_t *owner, unsigned event, hsm_state_t *target, hsm_handler_t *handler)
initialize hsm state action object
void hsm_init(hsm_t *hsm, void *data, size_t bufsize)
initialize hsm object
void hsm_initState(hsm_state_t *state, hsm_state_t *parent)
initialize hsm object
constexpr Action(S &_owner, unsigned _event, S &_target, hsm_handler_t *_handler=nullptr)
constructor, see the constructor parameters of the class
Definition osstatemachine.h:560
constexpr Action(S &_owner, unsigned _event, S &_target, F &&_handler)
constructor, see the constructor parameters of the class
Definition osstatemachine.h:567
constexpr Action(S &_owner, unsigned _event, hsm_handler_t *_handler=nullptr)
constructor, see the constructor parameters of the class
Definition osstatemachine.h:557
std::function< void(hsm_t *, unsigned)> handler
handler of the action (function object)
Definition osstatemachine.h:580
static constexpr rep until(const std::chrono::time_point< Clock, _Duration > &_time)
time point in ticks, rounded up to whole ticks (only a time point of this clock)
Definition osclock.h:109
static constexpr rep count(const std::chrono::duration< _Rep, _Period > &_delay)
delay in ticks, rounded up to whole ticks; negative delay: IMMEDIATE, delay out of range: INFINITE
Definition osclock.h:102
create and initialize a hierarchical state machine object
Definition osstatemachine.h:600
void startAsync(tsk_t &_task, hsm_state_t &_init)
link the actions of the table and start the state machine (hsm_startAsync())
Definition osstatemachine.h:637
void push(unsigned _event)
hsm_push()
Definition osstatemachine.h:633
void reset()
hsm_reset()
Definition osstatemachine.h:625
int sendFor(unsigned _event, const T &_delay)
hsm_sendFor()
Definition osstatemachine.h:629
int sendUntil(unsigned _event, const T &_time)
hsm_sendUntil()
Definition osstatemachine.h:631
hsm_state_t * getState()
hsm_getState()
Definition osstatemachine.h:634
int send(unsigned _event)
hsm_send()
Definition osstatemachine.h:632
int sendAsync(unsigned _event)
hsm_sendAsync()
Definition osstatemachine.h:640
void add(S &_owner, unsigned _event, A &&... _args)
add an action (parameters of the Action constructor) to the table of the state machine
Definition osstatemachine.h:619
void kill()
hsm_kill()
Definition osstatemachine.h:626
void start(tsk_t &_task, hsm_state_t &_init)
link the actions of the table and start the state machine (hsm_start())
Definition osstatemachine.h:623
StateMachineT(StateMachineT &&_src)
move constructor
Definition osstatemachine.h:607
int giveAsync(unsigned _event)
hsm_giveAsync()
Definition osstatemachine.h:639
StateMachineT()
constructor, see the constructor parameters of the class
Definition osstatemachine.h:602
int give(unsigned _event)
hsm_give()
Definition osstatemachine.h:627
create and initialize an hsm state object
Definition osstatemachine.h:528
constexpr State()
constructor, see the constructor parameters of the class
Definition osstatemachine.h:531
State(State &&_src)
move constructor
Definition osstatemachine.h:537
constexpr State(S &_parent)
constructor, see the constructor parameters of the class
Definition osstatemachine.h:534