@@ -30,13 +30,10 @@ open class URLSessionTask : NSObject, NSCopying {
30
30
internal var session : URLSessionProtocol ! //change to nil when task completes
31
31
internal let body : _Body
32
32
fileprivate var _protocol : URLProtocol ? = nil
33
-
33
+ private let syncQ = DispatchQueue ( label: " org.swift.URLSessionTask.SyncQ " )
34
+
34
35
/// All operations must run on this queue.
35
36
internal let workQueue : DispatchQueue
36
- /// Using dispatch semaphore to make public attributes thread safe.
37
- /// A semaphore is a simpler option against the usage of concurrent queue
38
- /// as the critical sections are very short.
39
- fileprivate let semaphore = DispatchSemaphore ( value: 1 )
40
37
41
38
public override init ( ) {
42
39
// Darwin Foundation oddly allows calling this initializer, even though
@@ -62,7 +59,8 @@ open class URLSessionTask : NSObject, NSCopying {
62
59
}
63
60
internal init ( session: URLSession , request: URLRequest , taskIdentifier: Int , body: _Body ) {
64
61
self . session = session
65
- self . workQueue = session. workQueue
62
+ /* make sure we're actually having a serial queue as it's used for synchronization */
63
+ self . workQueue = DispatchQueue . init ( label: " org.swift.URLSessionTask.WorkQueue " , target: session. workQueue)
66
64
self . taskIdentifier = taskIdentifier
67
65
self . originalRequest = request
68
66
self . body = body
@@ -108,31 +106,19 @@ open class URLSessionTask : NSObject, NSCopying {
108
106
/// May differ from originalRequest due to http server redirection
109
107
/*@NSCopying*/ open internal( set) var currentRequest : URLRequest ? {
110
108
get {
111
- semaphore. wait ( )
112
- defer {
113
- semaphore. signal ( )
114
- }
115
- return self . _currentRequest
109
+ return self . syncQ. sync { return self . _currentRequest }
116
110
}
117
111
set {
118
- semaphore. wait ( )
119
- self . _currentRequest = newValue
120
- semaphore. signal ( )
112
+ self . syncQ. sync { self . _currentRequest = newValue }
121
113
}
122
114
}
123
115
fileprivate var _currentRequest : URLRequest ? = nil
124
116
/*@NSCopying*/ open internal( set) var response : URLResponse ? {
125
117
get {
126
- semaphore. wait ( )
127
- defer {
128
- semaphore. signal ( )
129
- }
130
- return self . _response
118
+ return self . syncQ. sync { return self . _response }
131
119
}
132
120
set {
133
- semaphore. wait ( )
134
- self . _response = newValue
135
- semaphore. signal ( )
121
+ self . syncQ. sync { self . _response = newValue }
136
122
}
137
123
}
138
124
fileprivate var _response : URLResponse ? = nil
@@ -145,33 +131,21 @@ open class URLSessionTask : NSObject, NSCopying {
145
131
/// Number of body bytes already received
146
132
open internal( set) var countOfBytesReceived : Int64 {
147
133
get {
148
- semaphore. wait ( )
149
- defer {
150
- semaphore. signal ( )
151
- }
152
- return self . _countOfBytesReceived
134
+ return self . syncQ. sync { return self . _countOfBytesReceived }
153
135
}
154
136
set {
155
- semaphore. wait ( )
156
- self . _countOfBytesReceived = newValue
157
- semaphore. signal ( )
137
+ self . syncQ. sync { self . _countOfBytesReceived = newValue }
158
138
}
159
139
}
160
140
fileprivate var _countOfBytesReceived : Int64 = 0
161
141
162
142
/// Number of body bytes already sent */
163
143
open internal( set) var countOfBytesSent : Int64 {
164
144
get {
165
- semaphore. wait ( )
166
- defer {
167
- semaphore. signal ( )
168
- }
169
- return self . _countOfBytesSent
145
+ return self . syncQ. sync { return self . _countOfBytesSent }
170
146
}
171
147
set {
172
- semaphore. wait ( )
173
- self . _countOfBytesSent = newValue
174
- semaphore. signal ( )
148
+ self . syncQ. sync { self . _countOfBytesSent = newValue }
175
149
}
176
150
}
177
151
@@ -211,16 +185,10 @@ open class URLSessionTask : NSObject, NSCopying {
211
185
*/
212
186
open var state : URLSessionTask . State {
213
187
get {
214
- semaphore. wait ( )
215
- defer {
216
- semaphore. signal ( )
217
- }
218
- return self . _state
188
+ return self . syncQ. sync { self . _state }
219
189
}
220
190
set {
221
- semaphore. wait ( )
222
- self . _state = newValue
223
- semaphore. signal ( )
191
+ self . syncQ. sync { self . _state = newValue }
224
192
}
225
193
}
226
194
fileprivate var _state : URLSessionTask . State = . suspended
@@ -315,16 +283,10 @@ open class URLSessionTask : NSObject, NSCopying {
315
283
/// URLSessionTask.highPriority, but use is not restricted to these.
316
284
open var priority : Float {
317
285
get {
318
- semaphore. wait ( )
319
- defer {
320
- semaphore. signal ( )
321
- }
322
- return self . _priority
286
+ return self . workQueue. sync { return self . _priority }
323
287
}
324
288
set {
325
- semaphore. wait ( )
326
- self . _priority = newValue
327
- semaphore. signal ( )
289
+ self . workQueue. sync { self . _priority = newValue }
328
290
}
329
291
}
330
292
fileprivate var _priority : Float = URLSessionTask . defaultPriority
@@ -569,7 +531,9 @@ extension _ProtocolClient : URLProtocolClient {
569
531
session. delegateQueue. addOperation {
570
532
delegate. urlSession ( session, task: task, didCompleteWithError: nil )
571
533
task. state = . completed
572
- session. taskRegistry. remove ( task)
534
+ task. workQueue. async {
535
+ session. taskRegistry. remove ( task)
536
+ }
573
537
}
574
538
case . noDelegate:
575
539
task. state = . completed
@@ -625,7 +589,9 @@ extension _ProtocolClient : URLProtocolClient {
625
589
session. delegateQueue. addOperation {
626
590
delegate. urlSession ( session, task: task, didCompleteWithError: error as Error )
627
591
task. state = . completed
628
- session. taskRegistry. remove ( task)
592
+ task. workQueue. async {
593
+ session. taskRegistry. remove ( task)
594
+ }
629
595
}
630
596
case . noDelegate:
631
597
task. state = . completed
@@ -634,7 +600,9 @@ extension _ProtocolClient : URLProtocolClient {
634
600
session. delegateQueue. addOperation {
635
601
completion ( nil , nil , error)
636
602
task. state = . completed
637
- session. taskRegistry. remove ( task)
603
+ task. workQueue. async {
604
+ session. taskRegistry. remove ( task)
605
+ }
638
606
}
639
607
case . downloadCompletionHandler( let completion) :
640
608
session. delegateQueue. addOperation {
0 commit comments