Managing object states for multi-threaded applications is hard. Especially, when this state can transition to another state depending on multiple events.
I started thinking about this problem when implementing SIP protocol solutions. A SIP INVITE server transaction would look like:
|INVITE
|pass INV to TU
INVITE V send 100 if TU won't in 200ms
send response+-----------+
+--------| |--------+101-199 from TU
| | Proceeding| |send response
+------->| |<-------+
| | Transport Err.
| | Inform TU
| |--------------->+
+-----------+ |
300-699 from TU | |2xx from TU |
send response | |send response |
| +------------------>+
| |
INVITE V Timer G fires |
send response+-----------+ send response |
+--------| |--------+ |
| | Completed | | |
+------->| |<-------+ |
+-----------+ |
| | |
ACK | | |
- | +------------------>+
| Timer H fires |
V or Transport Err.|
+-----------+ Inform TU |
| | |
| Confirmed | |
| | |
+-----------+ |
| |
|Timer I fires |
|- |
| |
V |
+-----------+ |
| | |
| Terminated|<---------------+
| |
+-----------+
If you don’t think of an easy approach to representing/coding these state machines, you will end up having something: difficult to write, error prone, difficult to test and impossible to trace. The main sign that you are doing it wrong is when your code is full of if/else, synchronized blocks and you had to debug for 2d to find out how the hell you ended up in such an unexpected state.
So, if you happen to have to manage complex state objects, you should take a look to my library. I just finished a new iteration to the code and. Much happier than ever with it: https://bitbucket.org/xferro/sicoris-statemachine . There's already a SNAPSHOT version available, so you can use it already.
Any feedback is more than welcome!
No comments:
Post a Comment