Class: Async::Node
- Inherits:
-
Object
- Object
- Async::Node
- Defined in:
- lib/async/node.rb
Overview
A node in a tree, used for implementing the task hierarchy.
Instance Attribute Summary collapse
-
#annotation ⇒ Object
readonly
A useful identifier for the current node.
-
#children ⇒ Object
readonly
Returns the value of attribute children.
- #head ⇒ Object
-
#parent ⇒ Object
Returns the value of attribute parent.
- #tail ⇒ Object
Instance Method Summary collapse
- #annotate(annotation) ⇒ Object
- #backtrace(*arguments) ⇒ Object
-
#children? ⇒ Boolean
Whether this node has any children.
-
#consume ⇒ Object
If the node has a parent, and is #finished?, then remove this node from the parent.
- #description ⇒ Object
-
#finished? ⇒ Boolean
Whether the node can be consumed (deleted) safely.
-
#initialize(parent = nil, annotation: nil, transient: false) ⇒ Node
constructor
Create a new node in the tree.
- #print_hierarchy(out = $stdout, backtrace: true) ⇒ Object
- #root ⇒ Object
-
#stop(later = false) ⇒ Object
Attempt to stop the current node immediately, including all non-transient children.
- #stopped? ⇒ Boolean
-
#terminate ⇒ Object
Immediately terminate all children tasks, including transient tasks.
- #The parent node.=(parentnode. = (value)) ⇒ Object
- #to_s ⇒ Object (also: #inspect)
-
#transient? ⇒ Boolean
Represents whether a node is transient.
-
#traverse(&block) ⇒ Object
Traverse the task tree.
Constructor Details
#initialize(parent = nil, annotation: nil, transient: false) ⇒ Node
Create a new node in the tree.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/async/node.rb', line 57 def initialize(parent = nil, annotation: nil, transient: false) @parent = nil @children = nil @annotation = annotation @object_name = nil @transient = transient @head = nil @tail = nil if parent parent.add_child(self) end end |
Instance Attribute Details
#annotation ⇒ Object (readonly)
A useful identifier for the current node.
92 93 94 |
# File 'lib/async/node.rb', line 92 def annotation @annotation end |
#children ⇒ Object (readonly)
Returns the value of attribute children.
89 90 91 |
# File 'lib/async/node.rb', line 89 def children @children end |
#head ⇒ Object
80 81 82 |
# File 'lib/async/node.rb', line 80 def head @head end |
#parent ⇒ Object
Returns the value of attribute parent.
86 87 88 |
# File 'lib/async/node.rb', line 86 def parent @parent end |
#tail ⇒ Object
83 84 85 |
# File 'lib/async/node.rb', line 83 def tail @tail end |
Instance Method Details
#annotate(annotation) ⇒ Object
110 111 112 113 114 115 116 117 118 119 |
# File 'lib/async/node.rb', line 110 def annotate(annotation) if block_given? previous_annotation = @annotation @annotation = annotation yield @annotation = previous_annotation else @annotation = annotation end end |
#backtrace(*arguments) ⇒ Object
133 134 135 |
# File 'lib/async/node.rb', line 133 def backtrace(*arguments) nil end |
#children? ⇒ Boolean
Whether this node has any children.
96 97 98 |
# File 'lib/async/node.rb', line 96 def children? @children && !@children.empty? end |
#consume ⇒ Object
If the node has a parent, and is #finished?, then remove this node from the parent.
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/async/node.rb', line 186 def consume if parent = @parent and finished? parent.remove_child(self) if @children @children.each do |child| if child.finished? remove_child(child) else # In theory we don't need to do this... because we are throwing away the list. However, if you don't correctly update the list when moving the child to the parent, it foobars the enumeration, and subsequent nodes will be skipped, or in the worst case you might start enumerating the parents nodes. remove_child(child) parent.add_child(child) end end @children = nil end parent.consume end end |
#description ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/async/node.rb', line 121 def description @object_name ||= "#{self.class}:#{format '%#018x', object_id}#{@transient ? ' transient' : nil}" if @annotation "#{@object_name} #{@annotation}" elsif line = self.backtrace(0, 1)&.first "#{@object_name} #{line}" else @object_name end end |
#finished? ⇒ Boolean
Whether the node can be consumed (deleted) safely. By default, checks if the children set is empty.
180 181 182 |
# File 'lib/async/node.rb', line 180 def finished? @children.nil? || @children.finished? end |
#print_hierarchy(out = $stdout, backtrace: true) ⇒ Object
256 257 258 259 260 261 262 263 264 |
# File 'lib/async/node.rb', line 256 def print_hierarchy(out = $stdout, backtrace: true) self.traverse do |node, level| indent = "\t" * level out.puts "#{indent}#{node}" print_backtrace(out, indent, node) if backtrace end end |
#stop(later = false) ⇒ Object
Attempt to stop the current node immediately, including all non-transient children. Invokes #stop_children to stop all children.
240 241 242 243 |
# File 'lib/async/node.rb', line 240 def stop(later = false) # The implementation of this method may defer calling `stop_children`. stop_children(later) end |
#stopped? ⇒ Boolean
252 253 254 |
# File 'lib/async/node.rb', line 252 def stopped? @children.nil? end |
#terminate ⇒ Object
Immediately terminate all children tasks, including transient tasks. Internally invokes ‘stop(false)` on all children. This should be considered a last ditch effort and is used when closing the scheduler.
227 228 229 230 231 232 233 234 235 |
# File 'lib/async/node.rb', line 227 def terminate # Attempt to stop the current task immediately, and all children: stop(false) # If that doesn't work, take more serious action: @children&.each do |child| child.terminate end end |
#The parent node.=(parentnode. = (value)) ⇒ Object
86 |
# File 'lib/async/node.rb', line 86 attr :parent |
#to_s ⇒ Object Also known as: inspect
137 138 139 |
# File 'lib/async/node.rb', line 137 def to_s "\#<#{self.description}>" end |
#transient? ⇒ Boolean
Represents whether a node is transient. Transient nodes are not considered when determining if a node is finished. This is useful for tasks which are internal to an object rather than explicit user concurrency. For example, a child task which is pruning a connection pool is transient, because it is not directly related to the parent task, and should not prevent the parent task from finishing.
106 107 108 |
# File 'lib/async/node.rb', line 106 def transient? @transient end |
#traverse(&block) ⇒ Object
Traverse the task tree.
212 213 214 215 216 |
# File 'lib/async/node.rb', line 212 def traverse(&block) return enum_for(:traverse) unless block_given? self.traverse_recurse(&block) end |