Class: Async::Node

Inherits:
Object
  • Object
show all
Defined in:
lib/async/node.rb

Overview

A node in a tree, used for implementing the task hierarchy.

Direct Known Subclasses

Scheduler, Task

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parent = nil, annotation: nil, transient: false) ⇒ Node

Create a new node in the tree.



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/async/node.rb', line 59

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

#annotationObject (readonly)

A useful identifier for the current node.



94
95
96
# File 'lib/async/node.rb', line 94

def annotation
  @annotation
end

#childrenObject (readonly)

Returns the value of attribute children.



91
92
93
# File 'lib/async/node.rb', line 91

def children
  @children
end

#headObject



82
83
84
# File 'lib/async/node.rb', line 82

def head
  @head
end

#parentObject

Returns the value of attribute parent.



88
89
90
# File 'lib/async/node.rb', line 88

def parent
  @parent
end

#tailObject



85
86
87
# File 'lib/async/node.rb', line 85

def tail
  @tail
end

Instance Method Details

#annotate(annotation) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/async/node.rb', line 112

def annotate(annotation)
  if block_given?
    begin
      current_annotation = @annotation
      @annotation = annotation
      return yield
    ensure
      @annotation = current_annotation
    end
  else
    @annotation = annotation
  end
end

#backtrace(*arguments) ⇒ Object



142
143
144
# File 'lib/async/node.rb', line 142

def backtrace(*arguments)
  nil
end

#children?Boolean

Whether this node has any children.

Returns:

  • (Boolean)


98
99
100
# File 'lib/async/node.rb', line 98

def children?
  @children && !@children.empty?
end

#consumeObject

If the node has a parent, and is #finished?, then remove this node from the parent.



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/async/node.rb', line 195

def consume
  if parent = @parent and finished?
    parent.remove_child(self)
    
    # If we have children, then we need to move them to our the parent if they are not finished:
    if @children
      while child = @children.shift
        if child.finished?
          child.set_parent(nil)
        else
          parent.add_child(child)
        end
      end
      
      @children = nil
    end
    
    parent.consume
  end
end

#descriptionObject



130
131
132
133
134
135
136
137
138
139
140
# File 'lib/async/node.rb', line 130

def description
  @object_name ||= "#{self.class}:#{format '%#018x', object_id}#{@transient ? ' transient' : nil}"
  
  if annotation = self.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.

Returns:

  • (Boolean)


189
190
191
# File 'lib/async/node.rb', line 189

def finished?
  @children.nil? || @children.finished?
end


266
267
268
269
270
271
272
273
274
# File 'lib/async/node.rb', line 266

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

#rootObject



77
78
79
# File 'lib/async/node.rb', line 77

def root
  @parent&.root || self
end

#stop(later = false) ⇒ Object

Attempt to stop the current node immediately, including all non-transient children. Invokes #stop_children to stop all children.



250
251
252
253
# File 'lib/async/node.rb', line 250

def stop(later = false)
  # The implementation of this method may defer calling `stop_children`.
  stop_children(later)
end

#stopped?Boolean

Returns:

  • (Boolean)


262
263
264
# File 'lib/async/node.rb', line 262

def stopped?
  @children.nil?
end

#terminateObject

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.



235
236
237
238
239
240
241
242
243
244
245
# File 'lib/async/node.rb', line 235

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
  
  return @children.nil?
end

#The parent node.=(parentnode. = (value)) ⇒ Object



88
# File 'lib/async/node.rb', line 88

attr :parent

#to_sObject Also known as: inspect



146
147
148
# File 'lib/async/node.rb', line 146

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.

Returns:

  • (Boolean)


108
109
110
# File 'lib/async/node.rb', line 108

def transient?
  @transient
end

#traverse(&block) ⇒ Object

Traverse the task tree.



220
221
222
223
224
# File 'lib/async/node.rb', line 220

def traverse(&block)
  return enum_for(:traverse) unless block_given?
  
  self.traverse_recurse(&block)
end