Class: Async::Task

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

Overview

Encapsulates the state of a running task and it’s result.

Instance Attribute Summary collapse

Attributes inherited from Node

#annotation, #children, #head, #parent, #tail

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Node

#The parent node.=, #annotate, #children?, #consume, #description, #print_hierarchy, #root, #terminate, #transient?, #traverse

Constructor Details

#initialize(parent = Task.current?, finished: nil, **options, &block) ⇒ Task

Create a new task.



65
66
67
68
69
70
71
72
73
74
# File 'lib/async/task.rb', line 65

def initialize(parent = Task.current?, finished: nil, **options, &block)
	super(parent, **options)
	
	@status = :initialized
	@result = nil
	@finished = finished
	
	@block = block
	@fiber = nil
end

Instance Attribute Details

#fiberObject (readonly)



106
107
108
# File 'lib/async/task.rb', line 106

def fiber
  @fiber
end

#resultObject (readonly)

Access the result of the task without waiting. May be nil if the task is not completed.



154
155
156
# File 'lib/async/task.rb', line 154

def result
  @result
end

#statusObject (readonly)



113
114
115
# File 'lib/async/task.rb', line 113

def status
  @status
end

Class Method Details

.currentObject

Lookup the Async::Task for the current fiber. Raise ‘RuntimeError` if none is available. @raises If task was not #set! for the current fiber.



186
187
188
# File 'lib/async/task.rb', line 186

def self.current
	Thread.current[:async_task] or raise RuntimeError, "No async task available!"
end

.current?Boolean

Check if there is a task defined for the current fiber.

Returns:

  • (Boolean)


192
193
194
# File 'lib/async/task.rb', line 192

def self.current?
	Thread.current[:async_task]
end

.yieldObject

Deprecated.

With no replacement.



58
59
60
# File 'lib/async/task.rb', line 58

def self.yield
	Fiber.scheduler.transfer
end

Instance Method Details

#alive?Boolean

Returns:

  • (Boolean)


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

def alive?
	@fiber&.alive?
end

#async(*arguments, **options, &block) ⇒ Object



126
127
128
129
130
131
132
# File 'lib/async/task.rb', line 126

def async(*arguments, **options, &block)
	task = Task.new(self, **options, &block)
	
	task.run(*arguments)
	
	return task
end

#backtrace(*arguments) ⇒ Object



81
82
83
# File 'lib/async/task.rb', line 81

def backtrace(*arguments)
	@fiber&.backtrace(*arguments)
end

#complete?Boolean

Returns:

  • (Boolean)


224
225
226
# File 'lib/async/task.rb', line 224

def complete?
	@status == :complete
end

#current?Boolean

Returns:

  • (Boolean)


196
197
198
# File 'lib/async/task.rb', line 196

def current?
	self.equal?(Thread.current[:async_task])
end

#failed?Boolean

Returns:

  • (Boolean)


212
213
214
# File 'lib/async/task.rb', line 212

def failed?
	@status == :failed
end

#finished?Boolean

Whether we can remove this node from the reactor graph.

Returns:

  • (Boolean)


208
209
210
# File 'lib/async/task.rb', line 208

def finished?
	super && @status != :running
end

#reactorObject



76
77
78
# File 'lib/async/task.rb', line 76

def reactor
	self.root
end

#run(*arguments) ⇒ Object

Begin the execution of the task.



116
117
118
119
120
121
122
123
124
# File 'lib/async/task.rb', line 116

def run(*arguments)
	if @status == :initialized
		@status = :running
		
		schedule(arguments)
	else
		raise RuntimeError, "Task already running!"
	end
end

#running?Boolean

Check if the task is running.

Returns:

  • (Boolean)


202
203
204
# File 'lib/async/task.rb', line 202

def running?
	@status == :running
end

#sleep(duration = nil) ⇒ Object

Deprecated.

Prefer Kernel#sleep except when compatibility with ‘stable-v1` is required.



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

def sleep(duration = nil)
	super
end

#stop(later = false) ⇒ Object

Stop the task and all of its children.



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/async/task.rb', line 157

def stop(later = false)
	if self.stopped?
		# If we already stopped this task... don't try to stop it again:
		return
	end
	
	if self.running?
		if self.current?
			if later
				Fiber.scheduler.push Stop::Later.new(self)
			else
				raise Stop, "Stopping current task!"
			end
		elsif @fiber&.alive?
			begin
				Fiber.scheduler.raise(@fiber, Stop)
			rescue FiberError
				Fiber.scheduler.push Stop::Later.new(self)
			end
		end
	else
		# We are not running, but children might be, so transition directly into stopped state:
		stop!
	end
end

#stopped?Boolean

Returns:

  • (Boolean)


220
221
222
# File 'lib/async/task.rb', line 220

def stopped?
	@status == :stopped
end

#stopping?Boolean

Returns:

  • (Boolean)


216
217
218
# File 'lib/async/task.rb', line 216

def stopping?
	@status == :stopping
end

#to_sObject



86
87
88
# File 'lib/async/task.rb', line 86

def to_s
	"\#<#{self.description} (#{@status})>"
end

#waitObject

Retrieve the current result of the task. Will cause the caller to wait until result is available. @raises If the task’s fiber is the current fiber.



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/async/task.rb', line 137

def wait
	raise "Cannot wait on own fiber" if Fiber.current.equal?(@fiber)
	
	if running?
		@finished ||= Condition.new
		@finished.wait
	end
	
	case @result
	when Exception
		raise @result
	else
		return @result
	end
end

#with_timeout(timeout, exception = TimeoutError, message = "execution expired", &block) ⇒ Object

Deprecated.


96
97
98
# File 'lib/async/task.rb', line 96

def with_timeout(timeout, exception = TimeoutError, message = "execution expired", &block)
	Fiber.scheduler.timeout_after(timeout, exception, message, &block)
end

#yieldObject

Yield back to the reactor and allow other fibers to execute.



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

def yield
	Fiber.scheduler.yield
end