Skip to content

Commit 7a858f5

Browse files
committed
[Concurrency] Fix CooperativeExecutor to not loop forever.
If a job enqueues another job on the executor, we might never leave the inner `while` loop in the `run()` method. Fix this by taking the contents of the run queue and only running those jobs in the queue at the time we enter the inner loop.
1 parent c93a898 commit 7a858f5

File tree

2 files changed

+11
-1
lines changed

2 files changed

+11
-1
lines changed

stdlib/public/Concurrency/CooperativeExecutor.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,8 @@ extension CooperativeExecutor: RunLoopExecutor {
248248
#endif
249249

250250
// Now run any queued jobs
251-
while let job = runQueue.pop() {
251+
var runQ = runQueue.take()
252+
while let job = runQ.pop() {
252253
unsafe ExecutorJob(job).runSynchronously(
253254
on: self.asUnownedSerialExecutor()
254255
)

stdlib/public/Concurrency/PriorityQueue.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ struct PriorityQueue<T> {
4040
self.compare = compare
4141
}
4242

43+
/// Take the queue.
44+
///
45+
/// This returns a copy of the queue, and empties the original.
46+
mutating func take() -> PriorityQueue<T> {
47+
var q = PriorityQueue(compare: self.compare)
48+
swap(&self, &q)
49+
return q
50+
}
51+
4352
/// Push an item onto the queue.
4453
///
4554
/// Parameters:

0 commit comments

Comments
 (0)