@@ -18,3 +18,115 @@ function set_task_tid!(task::Task, tid::Integer)
18
18
end
19
19
@assert Threads. threadid (task) == tid " jl_set_task_tid failed!"
20
20
end
21
+
22
+ if isdefined (Base, :waitany )
23
+ import Base: waitany, waitall
24
+ else
25
+ # Vendored from Base
26
+ # License is MIT
27
+ waitany (tasks; throw= true ) = _wait_multiple (tasks, throw)
28
+ waitall (tasks; failfast= true , throw= true ) = _wait_multiple (tasks, throw, true , failfast)
29
+ function _wait_multiple (waiting_tasks, throwexc= false , all= false , failfast= false )
30
+ tasks = Task[]
31
+
32
+ for t in waiting_tasks
33
+ t isa Task || error (" Expected an iterator of `Task` object" )
34
+ push! (tasks, t)
35
+ end
36
+
37
+ if (all && ! failfast) || length (tasks) <= 1
38
+ exception = false
39
+ # Force everything to finish synchronously for the case of waitall
40
+ # with failfast=false
41
+ for t in tasks
42
+ _wait (t)
43
+ exception |= istaskfailed (t)
44
+ end
45
+ if exception && throwexc
46
+ exceptions = [TaskFailedException (t) for t in tasks if istaskfailed (t)]
47
+ throw (CompositeException (exceptions))
48
+ else
49
+ return tasks, Task[]
50
+ end
51
+ end
52
+
53
+ exception = false
54
+ nremaining:: Int = length (tasks)
55
+ done_mask = falses (nremaining)
56
+ for (i, t) in enumerate (tasks)
57
+ if istaskdone (t)
58
+ done_mask[i] = true
59
+ exception |= istaskfailed (t)
60
+ nremaining -= 1
61
+ else
62
+ done_mask[i] = false
63
+ end
64
+ end
65
+
66
+ if nremaining == 0
67
+ return tasks, Task[]
68
+ elseif any (done_mask) && (! all || (failfast && exception))
69
+ if throwexc && (! all || failfast) && exception
70
+ exceptions = [TaskFailedException (t) for t in tasks[done_mask] if istaskfailed (t)]
71
+ throw (CompositeException (exceptions))
72
+ else
73
+ return tasks[done_mask], tasks[.~ done_mask]
74
+ end
75
+ end
76
+
77
+ chan = Channel {Int} (Inf )
78
+ sentinel = current_task ()
79
+ waiter_tasks = fill (sentinel, length (tasks))
80
+
81
+ for (i, done) in enumerate (done_mask)
82
+ done && continue
83
+ t = tasks[i]
84
+ if istaskdone (t)
85
+ done_mask[i] = true
86
+ exception |= istaskfailed (t)
87
+ nremaining -= 1
88
+ exception && failfast && break
89
+ else
90
+ waiter = @task put! (chan, i)
91
+ waiter. sticky = false
92
+ _wait2 (t, waiter)
93
+ waiter_tasks[i] = waiter
94
+ end
95
+ end
96
+
97
+ while nremaining > 0
98
+ i = take! (chan)
99
+ t = tasks[i]
100
+ waiter_tasks[i] = sentinel
101
+ done_mask[i] = true
102
+ exception |= istaskfailed (t)
103
+ nremaining -= 1
104
+
105
+ # stop early if requested, unless there is something immediately
106
+ # ready to consume from the channel (using a race-y check)
107
+ if (! all || (failfast && exception)) && ! isready (chan)
108
+ break
109
+ end
110
+ end
111
+
112
+ close (chan)
113
+
114
+ if nremaining == 0
115
+ return tasks, Task[]
116
+ else
117
+ remaining_mask = .~ done_mask
118
+ for i in findall (remaining_mask)
119
+ waiter = waiter_tasks[i]
120
+ donenotify = tasks[i]. donenotify:: ThreadSynchronizer
121
+ @lock donenotify Base. list_deletefirst! (donenotify. waitq, waiter)
122
+ end
123
+ done_tasks = tasks[done_mask]
124
+ if throwexc && exception
125
+ exceptions = [TaskFailedException (t) for t in done_tasks if istaskfailed (t)]
126
+ throw (CompositeException (exceptions))
127
+ else
128
+ return done_tasks, tasks[remaining_mask]
129
+ end
130
+ end
131
+ end
132
+ end
0 commit comments