Skip to content

Commit 7555941

Browse files
authored
Merge pull request #2953 from readdle/operation-order-breach-5.3
[5.3] Fix OperationQueue scheduling logic to prevent disruption of operation lists
2 parents 7dbf874 + b316e27 commit 7555941

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

Sources/Foundation/Operation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -993,7 +993,7 @@ open class OperationQueue : NSObject, ProgressReporting {
993993
// if the cached state is possibly not valid then the isReady value needs to be re-updated
994994
if Operation.__NSOperationState.enqueued == operation._state && operation._fetchCachedIsReady(&retest) {
995995
if let previous = prev?.takeUnretainedValue() {
996-
previous.__nextOperation = next
996+
previous.__nextPriorityOperation = next
997997
} else {
998998
_setFirstPriorityOperation(prio, next)
999999
}

Tests/Foundation/Tests/TestOperationQueue.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class TestOperationQueue : XCTestCase {
3434
("test_CancelWhileSuspended", test_CancelWhileSuspended),
3535
("test_OperationOrder", test_OperationOrder),
3636
("test_OperationOrder2", test_OperationOrder2),
37+
("test_ExecutionOrder", test_ExecutionOrder),
3738
("test_WaitUntilFinished", test_WaitUntilFinished),
3839
("test_OperationWaitUntilFinished", test_OperationWaitUntilFinished),
3940
("test_CustomOperationReady", test_CustomOperationReady),
@@ -531,6 +532,32 @@ class TestOperationQueue : XCTestCase {
531532
XCTAssertEqual(array, [5, 4, 3, 2, 1])
532533
}
533534

535+
func test_ExecutionOrder() {
536+
let queue = OperationQueue()
537+
538+
let didRunOp1 = expectation(description: "Did run first operation")
539+
let didRunOp1Dependency = expectation(description: "Did run first operation dependency")
540+
let didRunOp2 = expectation(description: "Did run second operation")
541+
var didRunOp1DependencyFirst = false
542+
543+
let op1 = BlockOperation {
544+
didRunOp1.fulfill()
545+
XCTAssertTrue(didRunOp1DependencyFirst, "Dependency should be executed first")
546+
}
547+
let op1Dependency = BlockOperation {
548+
didRunOp1Dependency.fulfill()
549+
didRunOp1DependencyFirst = true
550+
}
551+
op1.addDependency(op1Dependency)
552+
queue.addOperations([op1, op1Dependency], waitUntilFinished: false)
553+
554+
queue.addOperation {
555+
didRunOp2.fulfill()
556+
}
557+
558+
waitForExpectations(timeout: 1.0)
559+
}
560+
534561
func test_WaitUntilFinished() {
535562
let queue1 = OperationQueue()
536563
let queue2 = OperationQueue()

0 commit comments

Comments
 (0)