summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCasey Dahlin <cdahlin@redhat.com>2008-10-02 16:44:10 -0400
committerCasey Dahlin <cdahlin@redhat.com>2008-10-02 16:44:10 -0400
commitcd308a554c228409f2077f577bd97882a00f6e32 (patch)
treee369a102f9b46fe2b8e30292dcb7e563f2046b2a
parent101d8be71ce5e5b6e73158e8c16352ef2f0b61ef (diff)
downloadupstate-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.rb38
1 files changed, 36 insertions, 2 deletions
diff --git a/state.rb b/state.rb
index 73a9e5c..1db4c2c 100644
--- a/state.rb
+++ b/state.rb
@@ -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