Mstdlib-1.24.0
|
Typedefs | |
typedef struct M_state_machine | M_state_machine_t |
typedef struct M_state_machine_cleanup | M_state_machine_cleanup_t |
typedef void(* | M_state_machine_trace_cb) (M_state_machine_trace_t trace, M_uint64 mndescr, const char *mdescr, M_uint64 sndescr, const char *sdescr, const char *fdescr, M_uint64 id, M_state_machine_status_t status, M_bool run_sub, M_uint64 next_id, void *thunk) |
typedef M_state_machine_status_t(* | M_state_machine_state_cb) (void *data, M_uint64 *next) |
typedef M_state_machine_status_t(* | M_state_machine_cleanup_cb) (void *data, M_state_machine_cleanup_reason_t reason, M_uint64 *next) |
typedef M_bool(* | M_state_machine_pre_cb) (void *data, M_state_machine_status_t *status, M_uint64 *next) |
typedef M_state_machine_status_t(* | M_state_machine_post_cb) (void *data, M_state_machine_status_t sub_status, M_uint64 *next) |
Non-linear state machine for running a sequence of states.
Normally the state machine will run using a linear or linear hybrid method. When adding states to the state machine the order is preserved. By default the next state is the next state added. A state can change/set the next state id. Using the next state is simply a convenience for using the state machine in a linear manner. So a state can set an id to transition to or it can rely on the next state in the ordered state list to be called next. This behavior can be disabled and the state machine will run as a pure non-linear state machine where a transition id is required to be set by a state.
States are given an integral id. The id must be unique and is used so a state can specify which state to transition to. No id can use the number zero (0); it is reserved for internal use.
Each state can have an optional cleanup state machine. The cleanup will be called when the error or done status are returned by run. All status that ran (including the one that generated the error) will have their cleanup state machine run. The state must have fully completed before it is eligible for its cleanup to run. A machine that has only returned M_STATE_MACHINE_STATUS_WAIT is not eligible for its cleanup to run. A state that is a sub state machine is eligible for cleanup if it is entered (pre does not return M_FALSE).
Cleanup is run in reverse order that the states were run in. For example states A - E were run and E returns done. Cleanup for states will run E - A. Due to the state machine supporting non-linear sequences it is possible that a cleanup machines will be called multiple times.
Cleanup can be used in multiple ways. They can be resource clean up (particularly useful when the done_cleanup flag is used) that is run when the machine finishes. Or they can be used as error recovery such as performing an action if an error occurs (default use).
Cleanup should be specific to the state and should in some way be based on the state they're associated with. A final cleanup on success could be handled as a final state but should be handled outside of the state machine entirely. Such as being handled as part of cleaning up the void pointer of state data.
typedef struct M_state_machine M_state_machine_t |
typedef struct M_state_machine_cleanup M_state_machine_cleanup_t |
typedef void(* M_state_machine_trace_cb) (M_state_machine_trace_t trace, M_uint64 mndescr, const char *mdescr, M_uint64 sndescr, const char *sdescr, const char *fdescr, M_uint64 id, M_state_machine_status_t status, M_bool run_sub, M_uint64 next_id, void *thunk) |
Trace callback.
[in] | trace | Type of action traced. |
[in] | mndescr | Numeric state machine description code. |
[in] | mdescr | State machine description. |
[in] | sndescr | Numeric state description code. |
[in] | sdescr | State description. |
[in] | fdescr | Full description of the entire machine flow. |
[in] | id | Id of state. |
[in] | status | Return status. |
[in] | run_sub | Will the sub state machine be run. |
[in] | next_id | The next id the machine will move to. |
[in] | thunk | Thunk passed in when enabling the trace. |
typedef M_state_machine_status_t(* M_state_machine_state_cb) (void *data, M_uint64 *next) |
State callback.
This is what the state machine calls when entering a given state.
[in,out] | data | An opaque data type storing data that should be passed to the cb. |
[out] | next | The next id the state machine should transition to. When operating in linear or a hybrid manner this will be set to the next linear state. Changing this will change what state is next. |
typedef M_state_machine_status_t(* M_state_machine_cleanup_cb) (void *data, M_state_machine_cleanup_reason_t reason, M_uint64 *next) |
Cleanup state callback.
This is what a cleanup state machine calls when entering a given cleanup state.
[in,out] | data | An opaque data type storing data that should be passed to the cb. |
[in] | reason | The reason cleanup is being run. |
[out] | next | The next id the state machine should transition to. When operating in linear or a hybrid manner this will be set to the next linear state. Changing this will change what state is next. |
typedef M_bool(* M_state_machine_pre_cb) (void *data, M_state_machine_status_t *status, M_uint64 *next) |
Sub state machine pre (initialization) callback.
This will be called before starting a sub state machine.
[in,out] | data | An opaque data type storing data that should be passed to the cb. |
[out] | status | Used when not running the sub state machine. This is the status of the state. Defaults to M_STATE_MACHINE_STATUS_NEXT if not specified. |
[out] | next | Used when not running the sub state machine. If set the next id the state machine should transition to. When operating in linear or a hybrid manner this will be set to the next linear state. Changing this will change what state is next. |
typedef M_state_machine_status_t(* M_state_machine_post_cb) (void *data, M_state_machine_status_t sub_status, M_uint64 *next) |
Sub state machine post (de-initialization) callback.
The sub_status argument is the status returned by the sub state machine. Possible status:
The sub_status will next be M_STATE_MACHINE_STATUS_NEXT or similar. Thus, the sub_status should not be blindly returned from the post function as it will stop processing the parent state machine. If processing needs to continue the sub_status should be checked and M_STATE_MACHINE_STATUS_NEXT or similar should be returned. M_STATE_MACHINE_STATUS_DONE is the only successful sub_status that can be set, so patterns that check against M_STATE_MACHINE_STATUS_DONE should be used. For example:
[in,out] | data | An opaque data type storing data that should be passed to the cb. |
[out] | sub_status | The status of the last state in the sub state machine. |
[out] | next | The next id the state machine should transition to. When operating in linear or a hybrid manner this will be set to the next linear state. Changing this will change what state is next. |
Status of the state machine while running though states.
Options to control the behavior of the state machine.
Status of the state machine which caused the cleanup routines to trigger.
Tracing information.
M_state_machine_t * M_state_machine_create | ( | M_uint64 | ndescr, |
const char * | descr, | ||
M_uint32 | flags | ||
) |
Create a new state machine.
[in] | ndescr | A numeric description of the state machine. Can be 0. |
[in] | descr | A textual description of the state machine. Can be NULL. |
[in] | flags | M_state_machine_flags_t flags to control the behavior of the state machine. |
void M_state_machine_destroy | ( | M_state_machine_t * | m | ) |
Destroy a state machine.
This does not call the cleanup state machines associated with each state. State cleanups are only called when the state machine finishes running.
[in] | m | The state machine. |
M_state_machine_cleanup_t * M_state_machine_cleanup_create | ( | M_uint64 | ndescr, |
const char * | descr, | ||
M_uint32 | flags | ||
) |
Create a new cleanup state machine.
A cleanup state machine is very similar to a regular state machine and is only called when associated with a regular state machine state's cleanup parameter. This cannot be run directly but supports all options a regular state machine supports for execution.
When run error returns from a cleanup state machine will not be propagated back to the caller. To handle errors it is possible to have a cleanup state machine's state to have an associated cleanup state machine.
[in] | ndescr | A numeric description of the cleanup state machine. Can be 0. |
[in] | descr | A textual description of the cleanup state machine. Can be NULL. |
[in] | flags | M_state_machine_flags_t flags to control the behavior of the cleanup state machine. |
void M_state_machine_cleanup_destroy | ( | M_state_machine_cleanup_t * | m | ) |
Destroy a cleanup state machine.
[in] | m | The cleanup state machine. |
M_bool M_state_machine_insert_state | ( | M_state_machine_t * | m, |
M_uint64 | id, | ||
M_uint64 | ndescr, | ||
const char * | descr, | ||
M_state_machine_state_cb | func, | ||
M_state_machine_cleanup_t * | cleanup, | ||
M_list_u64_t * | next_ids | ||
) |
Add a state to the state machine.
[in,out] | m | The state machine. |
[in] | id | The id associated with this state. Must be unique. |
[in] | ndescr | A numeric description of the state. Can be 0. |
[in] | descr | A textual description of the state. Can be NULL. |
[in] | func | The state function to call. Cannot be NULL. |
[in] | cleanup | The cleanup state machine to call. Can be NULL if no cleanup is necessary for this state. |
[in] | next_ids | A list of valid transitions for this state. Can be NULL to denote all states are valid transitions. If not NULL the state machine takes ownership of next_ids. |
M_bool M_state_machine_insert_sub_state_machine | ( | M_state_machine_t * | m, |
M_uint64 | id, | ||
M_uint64 | ndescr, | ||
const char * | descr, | ||
const M_state_machine_t * | subm, | ||
M_state_machine_pre_cb | pre, | ||
M_state_machine_post_cb | post, | ||
M_state_machine_cleanup_t * | cleanup, | ||
M_list_u64_t * | next_ids | ||
) |
Add a state machine as a state to the state machine.
The state machine will duplicate the sub state machine and keep a copy.
The sub state machine will run though all states in the sub state machine. The state machine will return M_STATE_MACHINE_STATUS_WAIT from the sub state machine and resume the sub state machine when started again.
The sub state machine's final status will be passed to the post function if one is given. If a post function is not set, a status of M_STATE_MACHINE_STATUS_DONE will be returned as M_STATE_MACHINE_STATUS_NEXT. This is to prevent a M_STATE_MACHINE_STATUS_DONE from the sub state machine from accidentally stopping the calling state machine. If M_STATE_MACHINE_STATUS_DONE is needed as the result of the sub state machine's run then a post function is necessary.
[in,out] | m | The state machine. |
[in] | id | The id associated with this state. Must be unique. |
[in] | ndescr | A numeric description of the state. Can be 0. |
[in] | descr | A textual description of the state. Can be NULL. |
[in] | subm | The state machine that should be called from this one. Cannot be NULL. |
[in] | pre | A function to call before the sub state machine is started. Can be NULL. |
[in] | post | A function to call after the sub state machine is finished. Can be NULL. |
[in] | cleanup | The cleanup state machine to call. Can be NULL if no cleanup is necessary for this state. |
[in] | next_ids | A list of valid transitions for this state. Can be NULL to denote all states are valid transitions. If not NULL the state machine takes ownership of next_ids. |
M_bool M_state_machine_insert_state_interleaved | ( | M_state_machine_t * | m, |
M_uint64 | id, | ||
M_uint64 | ndescr, | ||
const char * | descr, | ||
M_state_machine_pre_cb | pre, | ||
M_state_machine_post_cb | post, | ||
M_state_machine_cleanup_t * | cleanup, | ||
M_list_u64_t * | next_ids | ||
) |
Add add a state to run interleaved sub state machines.
An interleaved state will have one or more sub state machines added to it. The sub state machines will be run interleaved as one returns wait the next will be started until it returns wait and so forth. Sub state machines process in a non liner order and do not match state counts between one another.
A single state machine that never returns wait will fully run before any others are. Interleaving relies on wait states. Typically, this is used for near concurrent processing for operations that may require waiting on external resources. For example, a system that receives, processes and sends data. A example flow: read -> process -> Interleave write and read -> process... This allows the read buffer to be filled while the write buffer is emptying. With a large amount of data read and write operations may need to wait for OS level network buffers.
States are run interleaved and not concurrently. They are run on the same thread. Locking of thunk resources is not necessary since only one state, regardless of sub state machine, will be running at any given time.
All running sub state machines will stop if an error is returned by any sub state machine. Unless the M_STATE_MACHINE_INTERNOABORT
flag is set which will alter this behavior.
[in,out] | m | The state machine. |
[in] | id | The id associated with this interleaved state. Must be unique. All interleaved sub state machines will attach to this id. |
[in] | ndescr | A numeric description of the state. Can be 0. |
[in] | descr | A textual description of the state. Can be NULL. |
[in] | pre | A function to call before the sub state machines are started. Can be NULL. |
[in] | post | A function to call after the sub state machines are finished. Can be NULL. Called when the last sub state machine is finished or they are aborted due to error. Will have an M_STATE_MACHINE_STATUS_ERROR_* if any of the sub state machines return an error status. If all sub state machines ran successfully will return M_STATE_MACHINE_STATUS_DONE . It is up to the caller to store information in the thunk argument passed to run if information about which (possibly multiple) sub state machines failed. |
[in] | cleanup | The cleanup state machine to call. Can be NULL if no cleanup is necessary for this state. |
[in] | next_ids | A list of valid transitions for this state. Can be NULL to denote all states are valid transitions. If not NULL the state machine takes ownership of next_ids. |
M_bool M_state_machine_insert_sub_state_machine_interleaved | ( | M_state_machine_t * | m, |
M_uint64 | id, | ||
const M_state_machine_t * | subm | ||
) |
Add a state machine as a state to the state machine for interleaved processing.
The state machine will duplicate the sub state machine and keep a copy.
[in,out] | m | The state machine. |
[in] | id | The id for the interleaved state as specified by M_state_machine_insert_state_interleaved . |
[in] | subm | The state machine that should be called from this one. Cannot be NULL. |
M_bool M_state_machine_remove_state | ( | M_state_machine_t * | m, |
M_uint64 | id | ||
) |
Remove a state from the state machine.
[in,out] | m | The state machine. |
[in] | id | The id of the state. |
M_bool M_state_machine_has_state | ( | const M_state_machine_t * | m, |
M_uint64 | id | ||
) |
Does the state machine contain the given state id.
[in] | m | The state machine. |
[in] | id | The id of the state. |
const M_list_u64_t * M_state_machine_list_states | ( | const M_state_machine_t * | m | ) |
List all state ids the state machine holds.
[in] | m | The state machine. |
M_bool M_state_machine_cleanup_insert_state | ( | M_state_machine_cleanup_t * | m, |
M_uint64 | id, | ||
M_uint64 | ndescr, | ||
const char * | descr, | ||
M_state_machine_cleanup_cb | func, | ||
M_state_machine_cleanup_t * | cleanup, | ||
M_list_u64_t * | next_ids | ||
) |
Add a cleanup state to a cleanup state machine.
[in,out] | m | The cleanup state machine. |
[in] | id | The id associated with this state. Must be unique. |
[in] | ndescr | A numeric description of the state. Can be 0. |
[in] | descr | A textual description of the state. Can be NULL. |
[in] | func | The state cleanup function to call. Cannot be NULL. |
[in] | cleanup | The cleanup state machine to call. Can be NULL if no cleanup is necessary for this state. |
[in] | next_ids | A list of valid transitions for this state. Can be NULL to denote all states are valid transitions. If not NULL the state machine takes ownership of next_ids. |
M_bool M_state_machine_cleanup_insert_cleanup_sub_state_machine | ( | M_state_machine_cleanup_t * | m, |
M_uint64 | id, | ||
M_uint64 | ndescr, | ||
const char * | descr, | ||
const M_state_machine_cleanup_t * | subm, | ||
M_state_machine_pre_cb | pre, | ||
M_state_machine_post_cb | post, | ||
M_state_machine_cleanup_t * | cleanup, | ||
M_list_u64_t * | next_ids | ||
) |
Add a cleanup state machine as a state to the cleanup state machine.
The state machine will duplicate the sub state machine and keep a copy.
The sub state machine will run though all states in the sub state machine. The state machine will return M_STATE_MACHINE_STATUS_WAIT from the sub state machine and resume the sub state machine when started again.
The sub state machine's final status will be passed to the post function if one is given. If a post function is not set, a status of M_STATE_MACHINE_STATUS_DONE will be returned as M_STATE_MACHINE_STATUS_NEXT. This is to prevent a M_STATE_MACHINE_STATUS_DONE from the sub state machine from accidentally stopping the calling state machine. If M_STATE_MACHINE_STATUS_DONE is needed as the result of the sub state machine's run then a post function is necessary.
[in,out] | m | The cleanup state machine. |
[in] | id | The id associated with this state. Must be unique. |
[in] | ndescr | A numeric description of the state. Can be 0. |
[in] | descr | A textual description of the state. Can be NULL. |
[in] | subm | The cleanup state machine that should be called from this one. Cannot be NULL. |
[in] | pre | A function to call before the sub state machine is started. Can be NULL. |
[in] | post | A function to call after the sub state machine is finished. Can be NULL. |
[in] | cleanup | The cleanup state machine to call. Can be NULL if no cleanup is necessary for this state. |
[in] | next_ids | A list of valid transitions for this state. Can be NULL to denote all states are valid transitions. If not NULL the state machine takes ownership of next_ids. |
M_bool M_state_machine_cleanup_insert_sub_state_machine | ( | M_state_machine_cleanup_t * | m, |
M_uint64 | id, | ||
M_uint64 | ndescr, | ||
const char * | descr, | ||
const M_state_machine_t * | subm, | ||
M_state_machine_pre_cb | pre, | ||
M_state_machine_post_cb | post, | ||
M_state_machine_cleanup_t * | cleanup, | ||
M_list_u64_t * | next_ids | ||
) |
Add a state machine as a state to the cleanup state machine.
The state machine will duplicate the sub state machine and keep a copy.
The sub state machine will run though all states in the sub state machine. The state machine will return M_STATE_MACHINE_STATUS_WAIT from the sub state machine and resume the sub state machine when started again.
The sub state machine's final status will be passed to the post function if one is given. If a post function is not set, a status of M_STATE_MACHINE_STATUS_DONE will be returned as M_STATE_MACHINE_STATUS_NEXT. This is to prevent a M_STATE_MACHINE_STATUS_DONE from the sub state machine from accidentally stopping the calling state machine. If M_STATE_MACHINE_STATUS_DONE is needed as the result of the sub state machine's run then a post function is necessary.
[in,out] | m | The cleanup state machine. |
[in] | id | The id associated with this state. Must be unique. |
[in] | ndescr | A numeric description of the state. Can be NULL. |
[in] | descr | A textual description of the state. Can be NULL. |
[in] | subm | The state machine that should be called from this one. Cannot be NULL. |
[in] | pre | A function to call before the sub state machine is started. Can be NULL. |
[in] | post | A function to call after the sub state machine is finished. Can be NULL. |
[in] | cleanup | The cleanup state machine to call. Can be NULL if no cleanup is necessary for this state. |
[in] | next_ids | A list of valid transitions for this state. Can be NULL to denote all states are valid transitions. If not NULL the state machine takes ownership of next_ids. |
M_bool M_state_machine_cleanup_remove_state | ( | M_state_machine_cleanup_t * | m, |
M_uint64 | id | ||
) |
Remove a state from the cleanup state machine.
[in,out] | m | The state machine. |
[in] | id | The id of the state. |
M_bool M_state_machine_cleanup_has_state | ( | const M_state_machine_cleanup_t * | m, |
M_uint64 | id | ||
) |
Does the cleanup state machine contain the given state id.
[in] | m | The cleanup state machine. |
[in] | id | The id of the state. |
const M_list_u64_t * M_state_machine_cleanup_list_states | ( | const M_state_machine_cleanup_t * | m | ) |
List all state ids the cleanup state machine holds.
[in] | m | The cleanup state machine. |
void M_state_machine_enable_trace | ( | M_state_machine_t * | m, |
M_state_machine_trace_cb | cb, | ||
void * | thunk | ||
) |
Enabling tracing of state machine flow.
[in] | m | The state machine. |
[in] | cb | Trace callback. |
[in] | thunk | Thunk to be passed to callback. |
void M_state_machine_cleanup_enable_trace | ( | M_state_machine_cleanup_t * | m, |
M_state_machine_trace_cb | cb, | ||
void * | thunk | ||
) |
Enabling tracing of cleanup state machine flow.
[in] | m | The cleanup state machine. |
[in] | cb | Trace callback. |
[in] | thunk | Thunk to be passed to callback. |
M_state_machine_status_t M_state_machine_run | ( | M_state_machine_t * | m, |
void * | data | ||
) |
Run the state machine.
This may need to be called multiple times. A state can run non-blocking (poll based) where the state can return a wait state. The wait state means it finished processing but has more to do.
On error the cleanup state machine for the state will be called. When returning from a sub state machine which had clean up run the post function which can override and ignore an error can stop the cleanup process. Thus cleanup can be stopped and the state machine can recover from the error that started the process.
[in,out] | m | The state machine to run. |
[in,out] | data | State specific data that can be used and or manipulated by each state. |
void M_state_machine_reset | ( | M_state_machine_t * | m, |
M_state_machine_cleanup_reason_t | reason | ||
) |
Rest a running state machine.
A condition outside of the state machine could determine it needs to restart while it was in a running state. Not specifically running but in the middle of a run; having returned from a wait state for example. This will reset the state machine's internal process state so that it can be started from the beginning again.
This will not run cleanup immediately if requested but instead sets the state machine to start cleanup on next run. The sub state machine post function will not allow overriding the cleanup result and prevents the state machine from stopping cleanup. M_state_machine_run MUST be called. Also, remember that cleanup state machines can call wait so it may be necessary to run multiple times.
[in,out] | m | The state machine. |
[in] | reason | Whether state cleanups should run. Cleanup callbacks told cleanup is due to the reason code. Use M_STATE_MACHINE_CLEANUP_REASON_NONE to prevent cleanup. |
M_uint64 M_state_machine_ndescr | ( | const M_state_machine_t * | m, |
M_bool | recurse | ||
) |
Get the numeric description of the state machine
[in] | m | The state machine. |
[in] | recurse | Recurs into each running sub state machine and return the description for the one running. |
const char * M_state_machine_descr | ( | const M_state_machine_t * | m, |
M_bool | recurse | ||
) |
Get the description of the state machine
[in] | m | The state machine. |
[in] | recurse | Recurse into each running sub state machine and return the description for the one running. |
const M_state_machine_t * M_state_machine_active_sub | ( | const M_state_machine_t * | m, |
M_bool | recurse | ||
) |
Get the active sub state machine that is currently running.
[in] | m | The state machine. |
[in] | recurse | Recurse into each running sub state machine and return the last one that is running. |
M_bool M_state_machine_active_state | ( | const M_state_machine_t * | m, |
M_uint64 * | id | ||
) |
Get state of the state machine.
This only returns information about the given state machine. It does not look into sub state machines if one is running.
[in] | m | The state machine. |
[out] | id | The id of the state currently being run. Optional pass NULL if only checking whether the state machine is running. |
M_uint64 M_state_machine_active_state_ndescr | ( | const M_state_machine_t * | m, |
M_bool | recurse | ||
) |
Get the numeric description for the currently running state.
[in] | m | The state machine. |
[in] | recurse | Recurse into each running sub state machine and return the description for the one running. |
const char * M_state_machine_active_state_descr | ( | const M_state_machine_t * | m, |
M_bool | recurse | ||
) |
Get the description text for the currently running state.
[in] | m | The state machine. |
[in] | recurse | Recurse into each running sub state machine and return the description for the one running. |
char * M_state_machine_descr_full | ( | const M_state_machine_t * | m, |
M_bool | show_id | ||
) |
Get a textual representation of state machine and it's current state.
[in] | m | The state machine. |
[in] | show_id | M_TRUE if the numeric representation of state ids should be included. |
M_state_machine_t * M_state_machine_duplicate | ( | const M_state_machine_t * | m | ) |
Duplicate an existing state machine.
[in] | m | State machine to duplicate. |