class Async::Node

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

def add_child child

def add_child child
 ||= Children.new
.insert(child)
_parent(self)

def annotate(annotation)

def annotate(annotation)
	if block_given?
		previous_annotation = @annotation
		@annotation = annotation
		yield
		@annotation = previous_annotation
	else
		@annotation = annotation
	end
end

def backtrace(*arguments)

def backtrace(*arguments)
	nil
end

def children?

Whether there are children?
def children?
	@children != nil && !@children.empty?
end

def consume

the parent.
If the node has a parent, and is {finished?}, then remove this node from
def consume
	if parent = @parent and finished?
		parent.delete_child(self)
		
		if @children
			@children.each do |child|
				if child.finished?
					delete_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.
					delete_child(child)
					parent.add_child(child)
				end
			end
			
			@children = nil
		end
		
		parent.consume
	end
end

def delete_child(child)

def delete_child(child)
.delete(child)
_parent(nil)

def description

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

def finished?

@returns [Boolean]
children set is empty.
Whether the node can be consumed safely. By default, checks if the
def finished?
	@children.nil? || @children.finished?
end

def initialize(parent = nil, annotation: nil, transient: false)

@parameter parent [Node | Nil] This node will attach to the given parent.
Create a new node in the tree.
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

def parent=(parent)

@returns [Node] Itself.
@parameter parent [Node | Nil] the parent to attach to, or nil to detach.
Change the parent of this node.
def parent=(parent)
	return if @parent.equal?(parent)
	
	if @parent
		@parent.delete_child(self)
		@parent = nil
	end
	
	if parent
		parent.add_child(self)
	end
	
	return self
end

def print_backtrace(out, indent, node)

def print_backtrace(out, indent, node)
	if backtrace = node.backtrace
		backtrace.each_with_index do |line, index|
			out.puts "#{indent}#{index.zero? ? "→ " : "  "}#{line}"
		end
	end
end

def print_hierarchy(out = $stdout, backtrace: true)

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

def root

@returns [Node] the root node in the hierarchy.
def root
	@parent&.root || self
end

def set_parent parent

def set_parent parent
 parent

def stop(later = false)

@parameter later [Boolean] Whether to defer stopping until some point in the future.
Invokes {#stop_children} to stop all children.
Attempt to stop the current node immediately, including all non-transient children.
def stop(later = false)
	# The implementation of this method may defer calling `stop_children`.
	stop_children(later)
end

def stop_children(later = false)

Attempt to stop all non-transient children.
def stop_children(later = false)
en&.each do |child|
stop(later) unless child.transient?

def stopped?

def stopped?
	@children.nil?
end

def terminate

Internally invokes `stop(false)` on all children.
Immediately terminate all children tasks, including transient tasks.
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

def to_s

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

def transient?

Is this node transient?
def transient?
	@transient
end

def traverse(level = 0, &block)

@yields {|node, level| ...} The node and the level relative to the given root.
Traverse the tree.
def traverse(level = 0, &block)
	yield self, level
	
	@children&.each do |child|
		child.traverse(level + 1, &block)
	end
end