state-m
Summary
The library implements convenient state distribution and management mechanisms, facilitating collaborative work between components.
Features
- Separation of concerns, sources and readers of state changes hold different data structures.
- Duplicate filtering, by default, duplicate states do not trigger state changes, you can 'touch' on a tag if you really want this.
- State transition, supports type conversion of state.
- Stop the world (STW), supports stopping and resuming processing state change events at state-level.
- Merge events, you can merge several state readers into one.
- Split event, you can split one state reader into several.
- Timing control, supports waiting for all readers to complete their work.
- Timestamp, state change event have timestamp, you can know when it changed.
Usage
- Define 'Tag' enum to distinguish different state handles(sources and readers), all handles must use different tag values.
- Derive traits necessary: Clone, Debug, PartialEq, Eq, Hash.
- Use 'state_tag' attribute macro to decorate the 'Tag' enum.
- Add 'kv_assoc' attribute to all variants of the 'Tag' enum, use 'assoc' (mandatory) to associate corresponding state type, use 'label' (optional) if you want human readable labels when debuging the state machine.
;
- Implement 'HasStateMachine' trait for you data structure.
- Add state sources to your state machine.
- Add door or barriers to support stopping the world.
let unit = default;
// Not support stw.
unit.add_source.await?;
// Support stw by using a Door.
let door = new;
unit
.add_source
.await?;
// Close or open the door at your need.
door.close;
door.open;
// Support stw by using Barriers.
let barriers = new;
unit
.add_source
.await?;
// Add barriers, when the counter of Barriers larger than zero, the state processing stopped,
// when a barrier is dropped, the counter of Barriers subtract one, when the counter
// reaches zero, the state processing resumed.
let _barrier_1 = barriers.add_barrier;
let _barrier_2 = barriers.add_barrier;
- Add state readers to your state machine, to respond state changes from outer.
- If the origin state type is not what you need, you can extend the reader to convert the state type as you want.
- The state type must implements these traits: Clone, Debug, Default, PartialEq.
let unit_b = default;
unit_b.add_reader.await?;
unit_b
.add_reader
.await?;
unit_b
.add_reader
.await?;
- Source state changes as you want, use 'wait_' version of methods if you want to wait for all the responders to finish the work.
for i in 0..10
for i in 0..10
unit.touch.await?;
unit.wait_touch.await?;
- Remove state handle as needed
unit_b.del_handle;
- Watch state changes from several handles (source or reader), process them in queue without lock.
unit_b
.watch_1
.await?;
unit_b
.watch_2
.await?;
- Merge several readers into one.
let reader_2 = unit_b
.merge_reader_2
.await?;
- Split one reader into several readers.
let = unit_b
.split_reader_2
.await?;
- Debug the state machine as required.
info!;
| |
| |
| |