Skip to content

Commit de145c5

Browse files
authored
Refactor: use compile time type state pattern (#17083)
This PR implements the state machines using the type state pattern at compile time (via generic types) instead of a runtime state variable. There is no runtime check to see what state we are in, instead we transition to the new state when it's necessary. This has some nice performance improvements for some of the state machines, e.g.: ```diff - ArbitraryVariableMachine: Throughput: 744.92 MB/s + ArbitraryVariableMachine: Throughput: 1.21 GB/s ``` We also don't have to store the current state because each machine runs to completion. It's during execution that we can move to a new state if necessary. Unfortunately the diff is a tiny bit annoying to read, but essentially this is what happened: ### The `enum` is split up in it's individual states as structs: ```rs enum State { A, B, C, } ``` Becomes: ```rs struct A; struct B; struct C; ``` ### Generics The current machine will receive a generic `State` that we can default to the `IdleState`. Then we use `PhantomData` to "use" the type because the generic type is otherwise not used as a concrete value, it's just a marker. ```rs struct MyMachine {} ``` Becomes: ```rs struct MyMachine<State = Idle> { _state: std::marker::PhantomData<State> } ``` ### Split Next, the `next` function used to match on the current state, but now each match arm is moved to a dedicated implementation instead: ```rs impl Machine for MyMachine { fn next(&mut self) -> MachineState { match self.state { State::A => { /* … */ }, State::B => { /* … */ }, State::C => { /* … */ }, } } } ``` Becomes: ```rs impl Machine for MyMachine<A> { fn next(&mut self) -> MachineState { /* … */ } } impl Machine for MyMachine<B> { fn next(&mut self) -> MachineState { /* … */ } } impl Machine for MyMachine<C> { fn next(&mut self) -> MachineState { /* … */ } } ``` It's a bit more verbose, but now each state is implemented in its own block. This also removes 2 levels of nesting which is a nice benefit.
1 parent cc3e852 commit de145c5

File tree

4 files changed

+886
-817
lines changed

4 files changed

+886
-817
lines changed

0 commit comments

Comments
 (0)