Class: CompTree::Driver

Inherits:
Object
  • Object
show all
Defined in:
lib/comp_tree/driver.rb

Overview

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Driver

See CompTree.build



11
12
13
14
# File 'lib/comp_tree/driver.rb', line 11

def initialize(opts = {})  #:nodoc:
  @node_class = opts[:node_class] || Node
  @nodes = Hash.new
end

Instance Attribute Details

#nodesObject (readonly)

Name-to-node hash.



19
20
21
# File 'lib/comp_tree/driver.rb', line 19

def nodes
  @nodes
end

Instance Method Details

#check_circular(name) ⇒ Object

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.



79
80
81
82
83
84
85
86
87
88
89
90
# 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) ⇒ Object

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.



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# 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) ⇒ Object

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
}

Raises:



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# 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) ⇒ Object

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

Mark this node and all its children as uncomputed.



68
69
70
# File 'lib/comp_tree/driver.rb', line 68

def reset(name)
  @nodes[name].reset
end