| Subject: |
|
[Q] Ruby version of Qhsm from PSiCC (first edition) |
| Name: |
|
Chuck Remes |
| Date Posted: |
|
Jul 13, 08 - 10:34 AM |
| Email: |
|
cremes.devlist@mac.com |
| Message: |
|
As a programming exercise to better understand Hierarchical state machines, I coded up the Qhsm and QEvent classes from the first edition book in Ruby. Reimplementing this code in a dynamic language was actually pretty easy and educational.
However, I do have some questions that I'm hoping someone on this board can clarify. I have the dynamic transition method functioning. The original C, while efficient, was difficult to understand so I did some refactoring and rearranging to make it easier to follow. Again, this is for learning and not for squeezing the absolute best performance from it (impossible to do with a pokey language like Ruby anyway).
I'm now ready to write the tranSetup method which caches the transition sequence from source/state to target. I cannot do static storage for each transition like shown in the book. I have developed another methodology for accomplishing this task (which I'll explain below) but I'm actually confused about how to associate the cached sequence with the transition.
Should I cache each sequence based on state and target? Or do I need to cache based on source, state and target? Obviously these questions highlight my less than perfect understanding of how this should all work together.
Regardless of the answer to the above questions, here's the method for caching the sequence. Allocate a class level Hash for the HSM. The hash will identify each sequence with a key that is the concatenation of the state and destination and will reference an array containing the transition's steps. Each array will contain a hash with two keys representing each step in the sequence. It would look something like this (from the example given in chapter 4.2):
# cache = { :s11_s11 =>
# [
# {:state => :s11, :signal => :exit_signal}, {:state => :s1, :signal => :exit_signal },
# {:state => :s1, :signal => :entry_signal}, {:state => :s1, :signal => :init_signal}, {:state => :s11, :signal => :entry_signal}
# ]
# }
Obviously this is extremely space inefficient, but that doesn't matter to me.
To replay the sequence, the code will look something like this:
# cache[get_key(@state, target)].each do |step|
# trigger(step[:state], step[:signal])
# end
Miro, if you are interested in this ruby code, it is fairly clean and well-documented. I would be happy to provide it to you. |
|
Replies:
|
|
|
|
|