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.



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/async/node.rb', line 75

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

#A useful identifier for the current node.(usefulidentifier) ⇒ Object (readonly)



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

attr :annotation

#annotationObject (readonly)

Returns the value of attribute annotation.



110
111
112
# File 'lib/async/node.rb', line 110

def annotation
  @annotation
end

#childrenObject (readonly)

Returns the value of attribute children.



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

def children
  @children
end

#headObject



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

def head
  @head
end

#Optional list of children.(listofchildren.) ⇒ Object (readonly)



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

attr :children

#parentObject

Returns the value of attribute parent.



104
105
106
# File 'lib/async/node.rb', line 104

def parent
  @parent
end

#tailObject



101
102
103
# File 'lib/async/node.rb', line 101

def tail
  @tail
end

Instance Method Details

#annotate(annotation) ⇒ Object

Annotate the node with a description.



144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/async/node.rb', line 144

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

Provides a backtrace for nodes that have an active execution context.



176
177
178
# File 'lib/async/node.rb', line 176

def backtrace(*arguments)
	nil
end

#cancel(later = false, cause: $!) ⇒ Object

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



288
289
290
291
# File 'lib/async/node.rb', line 288

def cancel(later = false, cause: $!)
	# The implementation of this method may defer calling `stop_children`.
	stop_children(later, cause: cause)
end

#cancelled?Boolean

Whether the node has been cancelled.

Returns:

  • (Boolean)


313
314
315
# File 'lib/async/node.rb', line 313

def cancelled?
	@children.nil?
end

#children?Boolean

Whether this node has any children.

Returns:

  • (Boolean)


114
115
116
# File 'lib/async/node.rb', line 114

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

#consumeObject

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



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/async/node.rb', line 232

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

A description of the node, including the annotation and object name.



161
162
163
164
165
166
167
168
169
170
171
# File 'lib/async/node.rb', line 161

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)


226
227
228
# File 'lib/async/node.rb', line 226

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

Print the hierarchy of the task tree from the given node.



327
328
329
330
331
332
333
334
335
# File 'lib/async/node.rb', line 327

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



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

def root
	@parent&.root || self
end

#stopObject

Deprecated.

Use #cancel instead.

Backward compatibility alias for #cancel.



295
296
297
# File 'lib/async/node.rb', line 295

def stop(...)
	cancel(...)
end

#stopped?Boolean

Deprecated.

Use #cancelled? instead.

Backward compatibility alias for #cancelled?.

Returns:

  • (Boolean)


319
320
321
# File 'lib/async/node.rb', line 319

def stopped?
	cancelled?
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.



272
273
274
275
276
277
278
279
280
281
282
# File 'lib/async/node.rb', line 272

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



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

attr :parent

#to_sObject Also known as: inspect



181
182
183
# File 'lib/async/node.rb', line 181

def to_s
	"\#<#{self.description}>"
end

#transient=(value) ⇒ Object

Change the transient state of the node.

A transient node is not considered when determining if a node is finished, and propagates up if the parent is consumed.



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

def transient=(value)
	if @transient != value
		@transient = value
		
		@parent&.children&.adjust_transient_count(value)
	end
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)


124
125
126
# File 'lib/async/node.rb', line 124

def transient?
	@transient
end

#traverse(&block) ⇒ Object

Traverse the task tree.



257
258
259
260
261
# File 'lib/async/node.rb', line 257

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

#waitObject

Wait for this node to complete. By default, nodes cannot be waited on. Subclasses like Task override this method to provide waiting functionality.



308
309
310
# File 'lib/async/node.rb', line 308

def wait
	nil
end