@@ -34,13 +34,10 @@ open class URLSessionTask : NSObject, NSCopying {
34
34
internal var session : URLSessionProtocol ! //change to nil when task completes
35
35
internal let body : _Body
36
36
fileprivate var _protocol : URLProtocol ! = nil
37
+ private let syncQ = DispatchQueue ( label: " org.swift.URLSessionTask.SyncQ " )
37
38
38
39
/// All operations must run on this queue.
39
40
internal let workQueue : DispatchQueue
40
- /// Using dispatch semaphore to make public attributes thread safe.
41
- /// A semaphore is a simpler option against the usage of concurrent queue
42
- /// as the critical sections are very short.
43
- fileprivate let semaphore = DispatchSemaphore ( value: 1 )
44
41
45
42
public override init ( ) {
46
43
// Darwin Foundation oddly allows calling this initializer, even though
@@ -66,7 +63,8 @@ open class URLSessionTask : NSObject, NSCopying {
66
63
}
67
64
internal init ( session: URLSession , request: URLRequest , taskIdentifier: Int , body: _Body ) {
68
65
self . session = session
69
- self . workQueue = session. workQueue
66
+ /* make sure we're actually having a serial queue as it's used for synchronization */
67
+ self . workQueue = DispatchQueue . init ( label: " org.swift.URLSessionTask.WorkQueue " , target: session. workQueue)
70
68
self . taskIdentifier = taskIdentifier
71
69
self . originalRequest = request
72
70
self . body = body
@@ -112,31 +110,19 @@ open class URLSessionTask : NSObject, NSCopying {
112
110
/// May differ from originalRequest due to http server redirection
113
111
/*@NSCopying*/ open internal( set) var currentRequest : URLRequest ? {
114
112
get {
115
- semaphore. wait ( )
116
- defer {
117
- semaphore. signal ( )
118
- }
119
- return self . _currentRequest
113
+ return self . syncQ. sync { return self . _currentRequest }
120
114
}
121
115
set {
122
- semaphore. wait ( )
123
- self . _currentRequest = newValue
124
- semaphore. signal ( )
116
+ self . syncQ. sync { self . _currentRequest = newValue }
125
117
}
126
118
}
127
119
fileprivate var _currentRequest : URLRequest ? = nil
128
120
/*@NSCopying*/ open internal( set) var response : URLResponse ? {
129
121
get {
130
- semaphore. wait ( )
131
- defer {
132
- semaphore. signal ( )
133
- }
134
- return self . _response
122
+ return self . syncQ. sync { return self . _response }
135
123
}
136
124
set {
137
- semaphore. wait ( )
138
- self . _response = newValue
139
- semaphore. signal ( )
125
+ self . syncQ. sync { self . _response = newValue }
140
126
}
141
127
}
142
128
fileprivate var _response : URLResponse ? = nil
@@ -149,33 +135,21 @@ open class URLSessionTask : NSObject, NSCopying {
149
135
/// Number of body bytes already received
150
136
open internal( set) var countOfBytesReceived : Int64 {
151
137
get {
152
- semaphore. wait ( )
153
- defer {
154
- semaphore. signal ( )
155
- }
156
- return self . _countOfBytesReceived
138
+ return self . syncQ. sync { return self . _countOfBytesReceived }
157
139
}
158
140
set {
159
- semaphore. wait ( )
160
- self . _countOfBytesReceived = newValue
161
- semaphore. signal ( )
141
+ self . syncQ. sync { self . _countOfBytesReceived = newValue }
162
142
}
163
143
}
164
144
fileprivate var _countOfBytesReceived : Int64 = 0
165
145
166
146
/// Number of body bytes already sent */
167
147
open internal( set) var countOfBytesSent : Int64 {
168
148
get {
169
- semaphore. wait ( )
170
- defer {
171
- semaphore. signal ( )
172
- }
173
- return self . _countOfBytesSent
149
+ return self . syncQ. sync { return self . _countOfBytesSent }
174
150
}
175
151
set {
176
- semaphore. wait ( )
177
- self . _countOfBytesSent = newValue
178
- semaphore. signal ( )
152
+ self . syncQ. sync { self . _countOfBytesSent = newValue }
179
153
}
180
154
}
181
155
@@ -215,16 +189,10 @@ open class URLSessionTask : NSObject, NSCopying {
215
189
*/
216
190
open var state : URLSessionTask . State {
217
191
get {
218
- semaphore. wait ( )
219
- defer {
220
- semaphore. signal ( )
221
- }
222
- return self . _state
192
+ return self . syncQ. sync { self . _state }
223
193
}
224
194
set {
225
- semaphore. wait ( )
226
- self . _state = newValue
227
- semaphore. signal ( )
195
+ self . syncQ. sync { self . _state = newValue }
228
196
}
229
197
}
230
198
fileprivate var _state : URLSessionTask . State = . suspended
@@ -305,16 +273,10 @@ open class URLSessionTask : NSObject, NSCopying {
305
273
/// URLSessionTask.highPriority, but use is not restricted to these.
306
274
open var priority : Float {
307
275
get {
308
- semaphore. wait ( )
309
- defer {
310
- semaphore. signal ( )
311
- }
312
- return self . _priority
276
+ return self . workQueue. sync { return self . _priority }
313
277
}
314
278
set {
315
- semaphore. wait ( )
316
- self . _priority = newValue
317
- semaphore. signal ( )
279
+ self . workQueue. sync { self . _priority = newValue }
318
280
}
319
281
}
320
282
fileprivate var _priority : Float = URLSessionTask . defaultPriority
@@ -565,7 +527,9 @@ extension _ProtocolClient : URLProtocolClient {
565
527
session. delegateQueue. addOperation {
566
528
delegate. urlSession ( session, task: task, didCompleteWithError: nil )
567
529
task. state = . completed
568
- session. taskRegistry. remove ( task)
530
+ task. workQueue. async {
531
+ session. taskRegistry. remove ( task)
532
+ }
569
533
}
570
534
case . noDelegate:
571
535
task. state = . completed
@@ -616,7 +580,9 @@ extension _ProtocolClient : URLProtocolClient {
616
580
session. delegateQueue. addOperation {
617
581
delegate. urlSession ( session, task: task, didCompleteWithError: error as Error )
618
582
task. state = . completed
619
- session. taskRegistry. remove ( task)
583
+ task. workQueue. async {
584
+ session. taskRegistry. remove ( task)
585
+ }
620
586
}
621
587
case . noDelegate:
622
588
task. state = . completed
@@ -625,7 +591,9 @@ extension _ProtocolClient : URLProtocolClient {
625
591
session. delegateQueue. addOperation {
626
592
completion ( nil , nil , error)
627
593
task. state = . completed
628
- session. taskRegistry. remove ( task)
594
+ task. workQueue. async {
595
+ session. taskRegistry. remove ( task)
596
+ }
629
597
}
630
598
case . downloadCompletionHandler( let completion) :
631
599
session. delegateQueue. addOperation {
0 commit comments