class CompTree::Driver

Driver is the main interface to the computation tree. It is responsible for defining nodes and running computations.

Attributes

nodes[R]

Name-to-node hash.

Public Instance Methods

check_circular(name) click to toggle source

name – unique node identifier (for example a symbol).

Check for a cyclic graph below the given node. If found, returns the names of the nodes (in order) which form a loop. Otherwise returns nil.

# File lib/comp_tree/driver.rb, line 79
def check_circular(name)
  helper = Proc.new { |root, chain|
    if chain.include? root
      return chain + [root]
    end
    @nodes[root].children.each { |child|
      helper.call(child.name, chain + [root])
    }
  }
  helper.call(name, [])
  nil
end
compute(name, max_threads) click to toggle source

name – unique node identifier (for example a symbol).

max_threads – maximum number of threads, or 0 to indicate no limit.

Compute the tree below name and return the result.

If a node's computation raises an exception, the exception will be transferred to the caller of compute(). The tree will be left in a dirty state so that individual nodes may be examined. It is your responsibility to call reset() before attempting the computation again, otherwise the result will be undefined.

# File lib/comp_tree/driver.rb, line 106
def compute(name, max_threads)
  begin
    max_threads = max_threads.to_int
  rescue NoMethodError
    raise TypeError, "can't convert #{max_threads.class} into Integer"
  end
  if max_threads < 0
    raise RangeError, "max threads must be nonnegative"
  end

  root = @nodes[name] or raise NoNodeError.new(name)
  if root.computed
    root.result
  elsif max_threads == 1
    root.compute_now
  else
    Algorithm.compute_parallel(root, max_threads == 0 ? nil : max_threads)
  end
end
define(name, *child_names, &block) click to toggle source

name – unique node identifier (for example a symbol).

child_names – unique node identifiers of children.

Define a computation node.

During a computation, the results of the child nodes are passed to the block. The block returns the result of this node's computation.

In the following example, a computation node named :area is defined which depends on the nodes named :width and :height.

driver.define(:area, :width, :height) { |w, h|
  w*h
}
# File lib/comp_tree/driver.rb, line 39
def define(name, *child_names, &block)
  #
  # retrieve or create node
  #
  node = @nodes[name] ||= @node_class.new(name)
  raise RedefinitionError.new(node.name) if node.function
  node.function = block

  #
  # retrieve or create children
  #
  children = child_names.map { |child_name|
    @nodes[child_name] ||= @node_class.new(child_name)
  }

  #
  # link
  #
  node.children = children
  children.each { |child| child.parents << node }
  
  node
end
reset(name) click to toggle source

name – unique node identifier (for example a symbol).

Mark this node and all its children as uncomputed.

# File lib/comp_tree/driver.rb, line 68
def reset(name)
  @nodes[name].reset
end