diff options
| author | Casey Dahlin <cdahlin@redhat.com> | 2008-10-02 16:44:10 -0400 |
|---|---|---|
| committer | Casey Dahlin <cdahlin@redhat.com> | 2008-10-02 16:44:10 -0400 |
| commit | cd308a554c228409f2077f577bd97882a00f6e32 (patch) | |
| tree | e369a102f9b46fe2b8e30292dcb7e563f2046b2a | |
| parent | 101d8be71ce5e5b6e73158e8c16352ef2f0b61ef (diff) | |
| download | upstate-cd308a554c228409f2077f577bd97882a00f6e32.tar.gz upstate-cd308a554c228409f2077f577bd97882a00f6e32.tar.xz upstate-cd308a554c228409f2077f577bd97882a00f6e32.zip | |
Add depsolve functionality
The depsolve and depsolve_all methods have been created to find and create state
objects when their deps become available. Also, the hash method has been
redefined for State and == is now a hash comparison.
| -rw-r--r-- | state.rb | 38 |
1 files changed, 36 insertions, 2 deletions
@@ -111,7 +111,7 @@ class State # Determine if two State objects are equivalent def ==(other) - other.is_a? self.class and other.params == @params + self.hash == other.hash end # Match this State object to patterns or other State objects @@ -120,6 +120,20 @@ class State return self == other end + # Our ID is a function of our class and deps + def hash + (self.class.hash ** 2 + @deps.hash) % 0x4000000000000000 + end + + # A state is rooted in a set of states if any state in the set which it _may_ + # depend on, it _does_ depend on, and if all of its depended states are rooted + # in the set. + def rooted_in(set) + @deps.inject(true){ |x,y| x and y.rooted_in set } and \ + self.class.depends.map{ |x| set.select{ |y| x === y } } \ + .inject{ |x, y| x+y }.to_set.subset? @deps + end + # Create a new type of state. +name+ is capitalized and postfixed with "State" # to create the new state class name. +depends+ is a series of StatePattern # Objects. This method is not defined in subclasses of State. @@ -132,7 +146,7 @@ class State newtype.rising_edge = Proc.new{} newtype.falling_edge = Proc.new{} newtype.instance_eval do - undef :new_type, :process_event, :gc, :epsilate + undef :new_type, :process_event, :gc, :depsolve_all end @@state_types.add newtype newtype @@ -158,6 +172,26 @@ class State nil end + # Look at the list of active states and see how the deps of this state could + # be met + def State.depsolve + active_states = @@states.select{ |x| x.active } + candidates = @depends.map{ |d| active_states.select{ |s| d.match s } } + return nil if candidates.include? [] + candidates[0].product(*candidates[1..-1]).map{ |x| x.to_set } \ + .select{ |x| x.inject(true){ |st, y| st and y.rooted_in x } } \ + .reject do |dset| + active_states.select{ |x| x.is_a? self and x.deps == dset }.size > 0 + end.each{ |x| self.new x } + end + + # Depsolve all state classes. This method is not defined in subclasses of + # State. + def State.depsolve_all + @@state_types.each{ |x| x.depsolve } + nil + end + private # Set this state to true def rise |
