HiveBrain v1.2.0
Get Started
← Back to all entries
patternswiftMinor

Canonical Implementation for a Concurrent Subclass of NSOperation in Swift 2

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
swiftcanonicalnsoperationsubclassforimplementationconcurrent

Problem

I would like to develop a kind of template or canonical implementation for a concurrent subclass of NSOperation in Swift.

See here for my previous request which is implemented in Objective-C.
In that previous solution, there are still issues when the operation will be cancelled while it has not yet been started. There is also more or less sloppy approach regarding concurrency when accessing the properties isExecuting and isFinished.

In this new implementation, using Swift, I also try to address the previous issues.

I appreciate any comments, suggestions and questions.

Requirements:

  • Thread safe API.



  • start shall only start the task once, otherwise it should have no effect.



  • The operation object should not prematurely deinit while the task is executing.



  • Provide a reusable subclass of NSOperation that can be easily used as a base class of any custom operation.



References:

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html

Generic class Operation:

Note: The type parameter T refers to the type of the calculated value of the underlying asynchronous task. Since the task can also fail, an appropriate "Return type" of such a task is a Result which is a discriminated union representing either a value of type T or an error conforming to protocol ErrorType. The Result is a Swift enum.

```
import Foundation

public enum OperationError : Int, ErrorType {
case Cancelled = -1
case NoTask = -1000
}

private var queue_ID_key = 0

public class Operation : NSOperation {

public typealias ValueType = T
public typealias ResultType = Result
public typealias ContinuationFunc = ResultType -> ()

private var _result: Result?
private let _syncQueue = dispatch_queue_create("operation.sync_queue", DISPATCH_QUEUE_SERIAL);
private var _isExecuting = false
private var _isFinished = false
private var _continuation: ContinuationFunc?
private var _self: NS

Solution

I think you made a typo in the setter of finished.

You have self._isExecuting = newValue instead of self._isFinished = newValue.

When we wait for operations to finish, this typo will cause it to hang.

Context

StackExchange Code Review Q#107659, answer score: 4

Revisions (0)

No revisions yet.