You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
raise"Cannot wait on own fiber!"ifFiber.current.equal?(@fiber)
131
184
132
-
ifrunning?
185
+
# `finish!` will set both of these to nil before signaling the condition:
186
+
if@block || @fiber
133
187
@finished ||= Condition.new
134
188
@finished.wait
135
189
end
@@ -151,17 +205,22 @@ def stop(later = false)
151
205
return
152
206
end
153
207
154
-
ifself.running?
208
+
# If the fiber is alive, we need to stop it:
209
+
if@fiber&.alive?
155
210
ifself.current?
156
211
iflater
212
+
# If the fiber is the current fiber and we want to stop it later, schedule it:
157
213
Fiber.scheduler.push(Stop::Later.new(self))
158
214
else
215
+
# Otherwise, raise the exception directly:
159
216
raiseStop,"Stopping current task!"
160
217
end
161
-
elsif@fiber&.alive?
218
+
else
219
+
# If the fiber is not curent, we can raise the exception directly:
162
220
begin
163
221
Fiber.scheduler.raise(@fiber,Stop)
164
222
rescueFiberError
223
+
# In some cases, this can cause a FiberError (it might be resumed already), so we schedule it to be stopped later:
165
224
Fiber.scheduler.push(Stop::Later.new(self))
166
225
end
167
226
end
@@ -188,36 +247,34 @@ def current?
188
247
self.equal?(Thread.current[:async_task])
189
248
end
190
249
191
-
# Check if the task is running.
192
-
# @returns [Boolean]
193
-
defrunning?
194
-
@status == :running
195
-
end
196
-
197
-
# Whether we can remove this node from the reactor graph.
198
-
# @returns [Boolean]
199
-
deffinished?
200
-
super && @fiber.nil?
201
-
end
202
-
203
-
deffailed?
204
-
@status == :failed
205
-
end
250
+
private
206
251
207
-
defstopped?
208
-
@status == :stopped
252
+
# Finish the current task, moving any children to the parent.
253
+
deffinish!
254
+
# Don't hold references to the fiber or block after the task has finished:
255
+
@fiber=nil
256
+
@block=nil# If some how we went directly from initialized to finished.
257
+
258
+
# Attempt to remove this node from the task tree.
259
+
consume
260
+
261
+
# If this task was being used as a future, signal completion here:
262
+
if@finished
263
+
@finished.signal(self)
264
+
@finished=nil
265
+
end
209
266
end
210
267
211
-
defcomplete?
212
-
@status == :complete
268
+
# State transition into the completed state.
269
+
defcompleted!(result)
270
+
@result=result
271
+
@status=:completed
213
272
end
214
273
215
-
private
216
-
217
274
# This is a very tricky aspect of tasks to get right. I've modelled it after `Thread` but it's slightly different in that the exception can propagate back up through the reactor. If the user writes code which raises an exception, that exception should always be visible, i.e. cause a failure. If it's not visible, such code fails silently and can be very difficult to debug.
0 commit comments