Skip to content

Commit c210b51

Browse files
committed
Add _Atomic.
1 parent aa3e25d commit c210b51

File tree

4 files changed

+104
-51
lines changed

4 files changed

+104
-51
lines changed

SwiftTask.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
1F4C76A41AD8CF40004E47C1 /* AlamofireTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F5FA35619A374E600975FB9 /* AlamofireTests.swift */; };
1717
1F4C76A51AD8CF41004E47C1 /* AlamofireTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F5FA35619A374E600975FB9 /* AlamofireTests.swift */; };
1818
1F6A8CA319A4E4F200369A5D /* SwiftTaskTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F46DEE3199EDF1000F97868 /* SwiftTaskTests.swift */; };
19+
1FB3B8F31B0A194F00F78900 /* _Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB3B8F21B0A194F00F78900 /* _Atomic.swift */; };
20+
1FB3B8F41B0A194F00F78900 /* _Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB3B8F21B0A194F00F78900 /* _Atomic.swift */; };
1921
1FCF71121AD8CD2B007079C2 /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FCF71111AD8CD2B007079C2 /* Alamofire.framework */; };
2022
1FCF71141AD8CD2F007079C2 /* Async.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FCF71131AD8CD2F007079C2 /* Async.framework */; };
2123
1FCF71161AD8CD38007079C2 /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FCF71151AD8CD38007079C2 /* Alamofire.framework */; };
@@ -53,6 +55,7 @@
5355
1F46DEFA199EDF8100F97868 /* SwiftTask.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftTask.swift; sourceTree = "<group>"; };
5456
1F46DEFC199EE2C200F97868 /* _TestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = _TestCase.swift; sourceTree = "<group>"; };
5557
1F5FA35619A374E600975FB9 /* AlamofireTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlamofireTests.swift; sourceTree = "<group>"; };
58+
1FB3B8F21B0A194F00F78900 /* _Atomic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = _Atomic.swift; sourceTree = "<group>"; };
5659
1FCF71111AD8CD2B007079C2 /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = "../Carthage/Checkouts/Alamofire/build/Debug-iphoneos/Alamofire.framework"; sourceTree = "<group>"; };
5760
1FCF71131AD8CD2F007079C2 /* Async.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Async.framework; path = "../Carthage/Checkouts/Async/build/Debug-iphoneos/Async.framework"; sourceTree = "<group>"; };
5861
1FCF71151AD8CD38007079C2 /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = ../Carthage/Checkouts/Alamofire/build/Debug/Alamofire.framework; sourceTree = "<group>"; };
@@ -133,6 +136,7 @@
133136
1FD7197A1AFE387C00BC38C4 /* Cancellable.swift */,
134137
48B58D7A1A6F255E0068E18C /* _StateMachine.swift */,
135138
487858231B09701F0022E56A /* _RecursiveLock.swift */,
139+
1FB3B8F21B0A194F00F78900 /* _Atomic.swift */,
136140
1F46DED7199EDF1000F97868 /* Supporting Files */,
137141
);
138142
path = SwiftTask;
@@ -349,6 +353,7 @@
349353
1F46DEFB199EDF8100F97868 /* SwiftTask.swift in Sources */,
350354
1FD7197B1AFE387C00BC38C4 /* Cancellable.swift in Sources */,
351355
48B58D7B1A6F255E0068E18C /* _StateMachine.swift in Sources */,
356+
1FB3B8F31B0A194F00F78900 /* _Atomic.swift in Sources */,
352357
487858241B09701F0022E56A /* _RecursiveLock.swift in Sources */,
353358
);
354359
runOnlyForDeploymentPostprocessing = 0;
@@ -390,6 +395,7 @@
390395
48CD5A3C19AEEBDF0042B9F1 /* SwiftTask.swift in Sources */,
391396
1FD7197C1AFE387C00BC38C4 /* Cancellable.swift in Sources */,
392397
48B58D7C1A6F255E0068E18C /* _StateMachine.swift in Sources */,
398+
1FB3B8F41B0A194F00F78900 /* _Atomic.swift in Sources */,
393399
487858251B09701F0022E56A /* _RecursiveLock.swift in Sources */,
394400
);
395401
runOnlyForDeploymentPostprocessing = 0;

SwiftTask/SwiftTask.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,16 @@ public class Task<Progress, Value, Error>: Cancellable, Printable
8484
internal let _paused: Bool
8585
internal var _initClosure: _InitClosure! // retained throughout task's lifetime
8686

87-
public var state: TaskState { return self._machine.state }
87+
public var state: TaskState { return self._machine.state.rawValue }
8888

8989
/// progress value (NOTE: always nil when `weakified = true`)
90-
public var progress: Progress? { return self._machine.progress }
90+
public var progress: Progress? { return self._machine.progress.rawValue }
9191

9292
/// fulfilled value
93-
public var value: Value? { return self._machine.value }
93+
public var value: Value? { return self._machine.value.rawValue }
9494

9595
/// rejected/cancelled tuple info
96-
public var errorInfo: ErrorInfo? { return self._machine.errorInfo }
96+
public var errorInfo: ErrorInfo? { return self._machine.errorInfo.rawValue }
9797

9898
public var name: String = "DefaultTask"
9999

@@ -424,7 +424,7 @@ public class Task<Progress, Value, Error>: Cancellable, Printable
424424
let selfMachine = self._machine
425425

426426
self._then(&canceller) {
427-
let innerTask = thenClosure(selfMachine.value, selfMachine.errorInfo)
427+
let innerTask = thenClosure(selfMachine.value.rawValue, selfMachine.errorInfo.rawValue)
428428
_bindInnerTask(innerTask, newMachine, progress, fulfill, _reject, configure)
429429
}
430430

@@ -484,11 +484,11 @@ public class Task<Progress, Value, Error>: Cancellable, Printable
484484

485485
// NOTE: using `self._then()` + `selfMachine` instead of `self.then()` will reduce Task allocation
486486
self._then(&canceller) {
487-
if let value = selfMachine.value {
487+
if let value = selfMachine.value.rawValue {
488488
let innerTask = successClosure(value)
489489
_bindInnerTask(innerTask, newMachine, progress, fulfill, _reject, configure)
490490
}
491-
else if let errorInfo = selfMachine.errorInfo {
491+
else if let errorInfo = selfMachine.errorInfo.rawValue {
492492
_reject(errorInfo)
493493
}
494494
}
@@ -534,10 +534,10 @@ public class Task<Progress, Value, Error>: Cancellable, Printable
534534
let selfMachine = self._machine
535535

536536
self._then(&canceller) {
537-
if let value = selfMachine.value {
537+
if let value = selfMachine.value.rawValue {
538538
fulfill(value)
539539
}
540-
else if let errorInfo = selfMachine.errorInfo {
540+
else if let errorInfo = selfMachine.errorInfo.rawValue {
541541
let innerTask = failureClosure(errorInfo)
542542
_bindInnerTask(innerTask, newMachine, progress, fulfill, _reject, configure)
543543
}
@@ -617,10 +617,10 @@ internal func _bindInnerTask<Progress2, Value2, Error>(
617617
configure.cancel = { innerTask.cancel(); return }
618618

619619
// pause/cancel innerTask if descendant task is already paused/cancelled
620-
if newMachine.state == .Paused {
620+
if newMachine.state.rawValue == .Paused {
621621
innerTask.pause()
622622
}
623-
else if newMachine.state == .Cancelled {
623+
else if newMachine.state.rawValue == .Cancelled {
624624
innerTask.cancel()
625625
}
626626
}

SwiftTask/_Atomic.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//
2+
// _Atomic.swift
3+
// SwiftTask
4+
//
5+
// Created by Yasuhiro Inami on 2015/05/18.
6+
// Copyright (c) 2015年 Yasuhiro Inami. All rights reserved.
7+
//
8+
9+
import Darwin
10+
11+
internal final class _Atomic<T>
12+
{
13+
private var spinlock = OS_SPINLOCK_INIT
14+
private var _rawValue: T
15+
16+
internal var rawValue: T
17+
{
18+
get {
19+
lock()
20+
let rawValue = self._rawValue
21+
unlock()
22+
23+
return rawValue
24+
}
25+
26+
set(newValue) {
27+
lock()
28+
self._rawValue = newValue
29+
unlock()
30+
}
31+
}
32+
33+
init(_ rawValue: T)
34+
{
35+
self._rawValue = rawValue
36+
}
37+
38+
private func lock()
39+
{
40+
withUnsafeMutablePointer(&self.spinlock, OSSpinLockLock)
41+
}
42+
43+
private func unlock()
44+
{
45+
withUnsafeMutablePointer(&self.spinlock, OSSpinLockUnlock)
46+
}
47+
}

SwiftTask/_StateMachine.swift

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -20,34 +20,34 @@ internal class _StateMachine<Progress, Value, Error>
2020
internal typealias ProgressTupleHandler = Task<Progress, Value, Error>._ProgressTupleHandler
2121

2222
internal let weakified: Bool
23-
internal private(set) var state: TaskState
23+
internal let state: _Atomic<TaskState>
2424

25-
internal private(set) var progress: Progress? // NOTE: always nil if `weakified = true`
26-
internal private(set) var value: Value?
27-
internal private(set) var errorInfo: ErrorInfo?
25+
internal let progress: _Atomic<Progress?> = _Atomic(nil) // NOTE: always nil if `weakified = true`
26+
internal let value: _Atomic<Value?> = _Atomic(nil)
27+
internal let errorInfo: _Atomic<ErrorInfo?> = _Atomic(nil)
28+
29+
internal let configuration = TaskConfiguration()
2830

2931
/// wrapper closure for `_initClosure` to invoke only once when started `.Running`,
3032
/// and will be set to `nil` afterward
3133
internal var initResumeClosure: (Void -> Void)?
3234

33-
internal private(set) lazy var progressTupleHandlers = _Handlers<ProgressTupleHandler>()
34-
internal private(set) lazy var completionHandlers = _Handlers<Void -> Void>()
35-
36-
internal let configuration = TaskConfiguration()
35+
private lazy var _progressTupleHandlers = _Handlers<ProgressTupleHandler>()
36+
private lazy var _completionHandlers = _Handlers<Void -> Void>()
3737

3838
private let _recursiveLock = _RecursiveLock()
3939

4040
internal init(weakified: Bool, paused: Bool)
4141
{
4242
self.weakified = weakified
43-
self.state = paused ? .Paused : .Running
43+
self.state = _Atomic(paused ? .Paused : .Running)
4444
}
4545

4646
internal func addProgressTupleHandler(inout token: _HandlerToken?, _ progressTupleHandler: ProgressTupleHandler) -> Bool
4747
{
4848
self._recursiveLock.lock()
49-
if self.state == .Running || self.state == .Paused {
50-
token = self.progressTupleHandlers.append(progressTupleHandler)
49+
if self.state.rawValue == .Running || self.state.rawValue == .Paused {
50+
token = self._progressTupleHandlers.append(progressTupleHandler)
5151
self._recursiveLock.unlock()
5252
return token != nil
5353
}
@@ -61,7 +61,7 @@ internal class _StateMachine<Progress, Value, Error>
6161
{
6262
self._recursiveLock.lock()
6363
if let handlerToken = handlerToken {
64-
let removedHandler = self.progressTupleHandlers.remove(handlerToken)
64+
let removedHandler = self._progressTupleHandlers.remove(handlerToken)
6565
self._recursiveLock.unlock()
6666
return removedHandler != nil
6767
}
@@ -74,8 +74,8 @@ internal class _StateMachine<Progress, Value, Error>
7474
internal func addCompletionHandler(inout token: _HandlerToken?, _ completionHandler: Void -> Void) -> Bool
7575
{
7676
self._recursiveLock.lock()
77-
if self.state == .Running || self.state == .Paused {
78-
token = self.completionHandlers.append(completionHandler)
77+
if self.state.rawValue == .Running || self.state.rawValue == .Paused {
78+
token = self._completionHandlers.append(completionHandler)
7979
self._recursiveLock.unlock()
8080
return token != nil
8181
}
@@ -89,7 +89,7 @@ internal class _StateMachine<Progress, Value, Error>
8989
{
9090
self._recursiveLock.lock()
9191
if let handlerToken = handlerToken {
92-
let removedHandler = self.completionHandlers.remove(handlerToken)
92+
let removedHandler = self._completionHandlers.remove(handlerToken)
9393
self._recursiveLock.unlock()
9494
return removedHandler != nil
9595
}
@@ -102,16 +102,16 @@ internal class _StateMachine<Progress, Value, Error>
102102
internal func handleProgress(progress: Progress)
103103
{
104104
self._recursiveLock.lock()
105-
if self.state == .Running {
105+
if self.state.rawValue == .Running {
106106

107-
let oldProgress = self.progress
107+
let oldProgress = self.progress.rawValue
108108

109109
// NOTE: if `weakified = false`, don't store progressValue for less memory footprint
110110
if !self.weakified {
111-
self.progress = progress
111+
self.progress.rawValue = progress
112112
}
113113

114-
for handler in self.progressTupleHandlers {
114+
for handler in self._progressTupleHandlers {
115115
handler(oldProgress: oldProgress, newProgress: progress)
116116
}
117117
self._recursiveLock.unlock()
@@ -124,9 +124,9 @@ internal class _StateMachine<Progress, Value, Error>
124124
internal func handleFulfill(value: Value)
125125
{
126126
self._recursiveLock.lock()
127-
if self.state == .Running {
128-
self.state = .Fulfilled
129-
self.value = value
127+
if self.state.rawValue == .Running {
128+
self.state.rawValue = .Fulfilled
129+
self.value.rawValue = value
130130
self._finish()
131131
self._recursiveLock.unlock()
132132
}
@@ -138,9 +138,9 @@ internal class _StateMachine<Progress, Value, Error>
138138
internal func handleRejectInfo(errorInfo: ErrorInfo)
139139
{
140140
self._recursiveLock.lock()
141-
if self.state == .Running || self.state == .Paused {
142-
self.state = errorInfo.isCancelled ? .Cancelled : .Rejected
143-
self.errorInfo = errorInfo
141+
if self.state.rawValue == .Running || self.state.rawValue == .Paused {
142+
self.state.rawValue = errorInfo.isCancelled ? .Cancelled : .Rejected
143+
self.errorInfo.rawValue = errorInfo
144144
self._finish()
145145
self._recursiveLock.unlock()
146146
}
@@ -152,9 +152,9 @@ internal class _StateMachine<Progress, Value, Error>
152152
internal func handlePause() -> Bool
153153
{
154154
self._recursiveLock.lock()
155-
if self.state == .Running {
155+
if self.state.rawValue == .Running {
156156
self.configuration.pause?()
157-
self.state = .Paused
157+
self.state.rawValue = .Paused
158158
self._recursiveLock.unlock()
159159
return true
160160
}
@@ -196,9 +196,9 @@ internal class _StateMachine<Progress, Value, Error>
196196
{
197197
if (self.initResumeClosure != nil) {
198198

199-
let isInitPaused = (self.state == .Paused)
199+
let isInitPaused = (self.state.rawValue == .Paused)
200200
if isInitPaused {
201-
self.state = .Running // switch `.Paused` => `.Resume` temporarily without invoking `configure.resume()`
201+
self.state.rawValue = .Running // switch `.Paused` => `.Resume` temporarily without invoking `configure.resume()`
202202
}
203203

204204
// NOTE: performing `initResumeClosure` might change `state` to `.Fulfilled` or `.Rejected` **immediately**
@@ -207,17 +207,17 @@ internal class _StateMachine<Progress, Value, Error>
207207

208208
// switch back to `.Paused` if temporary `.Running` has not changed
209209
// so that consecutive `_handleResume()` can perform `configure.resume()`
210-
if isInitPaused && self.state == .Running {
211-
self.state = .Paused
210+
if isInitPaused && self.state.rawValue == .Running {
211+
self.state.rawValue = .Paused
212212
}
213213
}
214214
}
215215

216216
private func _handleResume() -> Bool
217217
{
218-
if self.state == .Paused {
218+
if self.state.rawValue == .Paused {
219219
self.configuration.resume?()
220-
self.state = .Running
220+
self.state.rawValue = .Running
221221
return true
222222
}
223223
else {
@@ -228,9 +228,9 @@ internal class _StateMachine<Progress, Value, Error>
228228
internal func handleCancel(error: Error? = nil) -> Bool
229229
{
230230
self._recursiveLock.lock()
231-
if self.state == .Running || self.state == .Paused {
232-
self.state = .Cancelled
233-
self.errorInfo = ErrorInfo(error: error, isCancelled: true)
231+
if self.state.rawValue == .Running || self.state.rawValue == .Paused {
232+
self.state.rawValue = .Cancelled
233+
self.errorInfo.rawValue = ErrorInfo(error: error, isCancelled: true)
234234
self._finish()
235235
self._recursiveLock.unlock()
236236
return true
@@ -243,17 +243,17 @@ internal class _StateMachine<Progress, Value, Error>
243243

244244
private func _finish()
245245
{
246-
for handler in self.completionHandlers {
246+
for handler in self._completionHandlers {
247247
handler()
248248
}
249249

250-
self.progressTupleHandlers.removeAll()
251-
self.completionHandlers.removeAll()
250+
self._progressTupleHandlers.removeAll()
251+
self._completionHandlers.removeAll()
252252

253253
self.configuration.finish()
254254

255255
self.initResumeClosure = nil
256-
self.progress = nil
256+
self.progress.rawValue = nil
257257
}
258258
}
259259

0 commit comments

Comments
 (0)