class CompTree::Driver

  1. lib/comp_tree/driver.rb
Parent: CompTree

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

Methods

Public Reader

  1. nodes

Public Instance

  1. define
  2. reset
  3. check_circular
  4. compute

Attributes

nodes [R]

Name-to-node hash.

Public Instance methods

define (name, *child_names, &block)

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
}
[show source]
    # File lib/comp_tree/driver.rb, line 39
39:     def define(name, *child_names, &block)
40:       #
41:       # retrieve or create node
42:       #
43:       node = @nodes[name] ||= @node_class.new(name)
44:       raise RedefinitionError.new(node.name) if node.function
45:       node.function = block
46: 
47:       #
48:       # retrieve or create children
49:       #
50:       children = child_names.map { |child_name|
51:         @nodes[child_name] ||= @node_class.new(child_name)
52:       }
53: 
54:       #
55:       # link
56:       #
57:       node.children = children
58:       children.each { |child| child.parents << node }
59:       
60:       node
61:     end
reset (name)

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

Mark this node and all its children as uncomputed.

[show source]
    # File lib/comp_tree/driver.rb, line 68
68:     def reset(name)
69:       @nodes[name].reset
70:     end
check_circular (name)

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.

[show source]
    # File lib/comp_tree/driver.rb, line 79
79:     def check_circular(name)
80:       helper = Proc.new { |root, chain|
81:         if chain.include? root
82:           return chain + [root]
83:         end
84:         @nodes[root].children.each { |child|
85:           helper.call(child.name, chain + [root])
86:         }
87:       }
88:       helper.call(name, [])
89:       nil
90:     end
compute (name, max_threads)

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.

[show source]
     # File lib/comp_tree/driver.rb, line 106
106:     def compute(name, max_threads)
107:       begin
108:         max_threads = max_threads.to_int
109:       rescue NoMethodError
110:         raise TypeError, "can't convert #{max_threads.class} into Integer"
111:       end
112:       if max_threads < 0
113:         raise RangeError, "max threads must be nonnegative"
114:       end
115: 
116:       root = @nodes[name] or raise NoNodeError.new(name)
117:       if root.computed
118:         root.result
119:       elsif max_threads == 1
120:         root.compute_now
121:       else
122:         Algorithm.compute_parallel(root, max_threads == 0 ? nil : max_threads)
123:       end
124:     end