Skip to content

Commit

Permalink
update comp_tree
Browse files Browse the repository at this point in the history
  • Loading branch information
quix committed Apr 6, 2009
1 parent 2ff2c90 commit 5591e71
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 48 deletions.
52 changes: 25 additions & 27 deletions lib/rake/comp_tree/algorithm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def loop_with(leave, again)

def compute_multithreaded(root, num_threads)
#trace "Computing #{root.name} with #{num_threads} threads"
result = nil
finished = nil
tree_mutex = Mutex.new
node_finished_condition = ConditionVariable.new
thread_wake_condition = ConditionVariable.new
Expand All @@ -36,7 +36,7 @@ def compute_multithreaded(root, num_threads)
loop_with(:leave, :again) {
node = tree_mutex.synchronize {
#trace "Thread #{thread_index} acquired tree lock; begin search"
if result
if finished
#trace "Thread #{thread_index} detected finish"
num_threads_in_use -= 1
throw :leave
Expand All @@ -57,33 +57,39 @@ def compute_multithreaded(root, num_threads)
}

#trace "Thread #{thread_index} computing node"
node_result = compute_node(node)
#debug {
# node.trace_compute
#}
node.compute
#trace "Thread #{thread_index} node computed; waiting for tree lock"

tree_mutex.synchronize {
#trace "Thread #{thread_index} acquired tree lock"
#debug {
# name = "#{node.name}" + ((node == root) ? " (ROOT NODE)" : "")
# initial = "Thread #{thread_index} compute result for #{name}: "
# status = node_result.is_a?(Exception) ? "error" : "success"
# status = node.computed.is_a?(Exception) ? "error" : "success"
# trace initial + status
# trace "Thread #{thread_index} node result: #{node_result}"
# trace "Thread #{thread_index} node result: #{node.result}"
#}

node.result = node_result

if node.computed.is_a? Exception
#
# An error occurred; we are done.
#
finished = node.computed
elsif node == root
#
# Root node was computed; we are done.
#
finished = true
end

#
# remove locks for this node (shared lock and own lock)
#
node.unlock

if node == root or node_result.is_a? Exception
#
# Root node was computed or error occurred; we are done.
#
result = node_result
end

#
# Tell the main thread that another node was computed.
#
Expand All @@ -105,7 +111,7 @@ def compute_multithreaded(root, num_threads)
#trace "Main: waking threads"
thread_wake_condition.broadcast

if result
if finished
#trace "Main: detected finish."
break
end
Expand All @@ -128,17 +134,17 @@ def compute_multithreaded(root, num_threads)
}

#trace "Main: computation done."
if result.is_a? Exception
raise result
if finished.is_a? Exception
raise finished
else
result
root.result
end
end

def find_node(node)
# --- only called inside shared tree mutex
#trace "Looking for a node, starting with #{node.name}"
if node.result
if node.computed
#
# already computed
#
Expand All @@ -162,13 +168,5 @@ def find_node(node)
nil
end
end

def compute_node(node)
begin
node.compute
rescue Exception => e
e
end
end
end
end
17 changes: 7 additions & 10 deletions lib/rake/comp_tree/driver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,6 @@ def initialize(opts = nil)
# width*height
# }
#
# NOTE: You must return a non-nil value to signal the computation
# is complete. If nil is returned, the node will be recomputed.
#
def define(*args, &block)
parent_name = args.first
children_names = args[1..-1]
Expand Down Expand Up @@ -144,13 +141,13 @@ def compute(name, opts)
raise ArgumentError, "threads is #{threads}"
end

root.result or (
if threads == 1
root.result = root.compute_now
else
compute_multithreaded(root, threads)
end
)
if root.computed
root.result
elsif threads == 1
root.result = root.compute_now
else
compute_multithreaded(root, threads)
end
end
end
end
31 changes: 22 additions & 9 deletions lib/rake/comp_tree/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Node
attr_accessor :children #:nodoc:
attr_accessor :function #:nodoc:
attr_accessor :result #:nodoc:
attr_accessor :computed #:nodoc:
attr_accessor :shared_lock #:nodoc:

#
Expand All @@ -23,6 +24,7 @@ def initialize(name) #:nodoc:
@mutex = Mutex.new
@children = []
@parents = []
@function = nil
reset_self
end

Expand All @@ -33,6 +35,7 @@ def reset_self #:nodoc:
@shared_lock = 0
@children_results = nil
@result = nil
@computed = nil
end

#
Expand Down Expand Up @@ -81,14 +84,18 @@ def compute_now #:nodoc:
# If all children have been computed, return their results;
# otherwise return nil.
#
# Do not assign to @children_results since own lock is not
# necessarily aquired.
#
def find_children_results #:nodoc:
if @children_results
@children_results
else
@children_results or (
@children.map { |child|
child.result or return nil
unless child.computed
return nil
end
child.result
}
end
)
end

def children_results=(value) #:nodoc:
Expand All @@ -99,7 +106,7 @@ def children_results=(value) #:nodoc:
# debug {
# # --- own mutex
# trace "Computing #{@name}"
# raise AssertionFailedError if @result
# raise AssertionFailedError if @computed
# raise AssertionFailedError unless @mutex.locked?
# raise AssertionFailedError unless @children_results
# }
Expand All @@ -110,11 +117,17 @@ def children_results=(value) #:nodoc:
# already acquired.
#
def compute #:nodoc:
unless defined?(@function) and @function
raise NoFunctionError,
begin
unless @function
raise NoFunctionError,
"No function was defined for node '#{@name.inspect}'"
end
@result = @function.call(*@children_results)
@computed = true
rescue Exception => e
@computed = e
end
@function.call(*@children_results)
@result
end

def try_lock #:nodoc:
Expand Down
3 changes: 1 addition & 2 deletions lib/rake/parallel.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ def invoke_parallel(root_task_name) # :nodoc:
children_names = prereqs.map { |child| child.name }
driver.define(task_name, *children_names) {
task.execute(task_args)
true
}
}

Expand All @@ -29,7 +28,7 @@ def invoke_parallel(root_task_name) # :nodoc:
#
root_node.each_downward { |node|
unless node.function
node.result = true
node.computed = true
end
}

Expand Down

0 comments on commit 5591e71

Please sign in to comment.