@@ -71,10 +71,10 @@ open class URLSessionTask : NSObject, NSCopying {
71
71
}
72
72
/// All operations must run on this queue.
73
73
fileprivate let workQueue : DispatchQueue
74
- /// This queue is used to make public attributes thread safe. It's a
75
- /// **concurrent** queue and must be used with a barries when writing. This
76
- /// allows multiple concurrent readers or a single writer .
77
- fileprivate let taskAttributesIsolation : DispatchQueue
74
+ /// Using dispatch semaphore to make public attributes thread safe.
75
+ /// A semaphore is a simpler option against the usage of concurrent queue
76
+ /// as the critical sections are very short .
77
+ fileprivate let semaphore = DispatchSemaphore ( value : 1 )
78
78
79
79
public override init ( ) {
80
80
// Darwin Foundation oddly allows calling this initializer, even though
@@ -88,7 +88,6 @@ open class URLSessionTask : NSObject, NSCopying {
88
88
originalRequest = nil
89
89
body = . none
90
90
workQueue = DispatchQueue ( label: " URLSessionTask.notused.0 " )
91
- taskAttributesIsolation = DispatchQueue ( label: " URLSessionTask.notused.1 " , attributes: DispatchQueue . Attributes. concurrent)
92
91
let fileName = NSTemporaryDirectory ( ) + NSUUID( ) . uuidString + " .tmp "
93
92
_ = FileManager . default. createFile ( atPath: fileName, contents: nil )
94
93
self . tempFileURL = URL ( fileURLWithPath: fileName)
@@ -105,7 +104,6 @@ open class URLSessionTask : NSObject, NSCopying {
105
104
internal init ( session: URLSession , request: URLRequest , taskIdentifier: Int , body: _Body ) {
106
105
self . session = session
107
106
self . workQueue = session. workQueue
108
- self . taskAttributesIsolation = session. taskAttributesIsolation
109
107
self . taskIdentifier = taskIdentifier
110
108
self . originalRequest = request
111
109
self . body = body
@@ -140,17 +138,32 @@ open class URLSessionTask : NSObject, NSCopying {
140
138
/// May differ from originalRequest due to http server redirection
141
139
/*@NSCopying*/ open fileprivate( set) var currentRequest : URLRequest ? {
142
140
get {
143
- return taskAttributesIsolation. sync { self . _currentRequest }
141
+ semaphore. wait ( )
142
+ defer {
143
+ semaphore. signal ( )
144
+ }
145
+ return self . _currentRequest
146
+ }
147
+ set {
148
+ semaphore. wait ( )
149
+ self . _currentRequest = newValue
150
+ semaphore. signal ( )
144
151
}
145
- //TODO: dispatch_barrier_async
146
- set { taskAttributesIsolation. async ( flags: . barrier) { self . _currentRequest = newValue } }
147
152
}
148
153
fileprivate var _currentRequest : URLRequest ? = nil
149
154
/*@NSCopying*/ open fileprivate( set) var response : URLResponse ? {
150
155
get {
151
- return taskAttributesIsolation. sync { self . _response }
156
+ semaphore. wait ( )
157
+ defer {
158
+ semaphore. signal ( )
159
+ }
160
+ return self . _response
161
+ }
162
+ set {
163
+ semaphore. wait ( )
164
+ self . _response = newValue
165
+ semaphore. signal ( )
152
166
}
153
- set { taskAttributesIsolation. async ( flags: . barrier) { self . _response = newValue } }
154
167
}
155
168
fileprivate var _response : URLResponse ? = nil
156
169
@@ -162,20 +175,35 @@ open class URLSessionTask : NSObject, NSCopying {
162
175
/// Number of body bytes already received
163
176
open fileprivate( set) var countOfBytesReceived : Int64 {
164
177
get {
165
- return taskAttributesIsolation. sync { self . _countOfBytesReceived }
178
+ semaphore. wait ( )
179
+ defer {
180
+ semaphore. signal ( )
181
+ }
182
+ return self . _countOfBytesReceived
183
+ }
184
+ set {
185
+ semaphore. wait ( )
186
+ self . _countOfBytesReceived = newValue
187
+ semaphore. signal ( )
166
188
}
167
- set { taskAttributesIsolation. async ( flags: . barrier) { self . _countOfBytesReceived = newValue } }
168
189
}
169
190
fileprivate var _countOfBytesReceived : Int64 = 0
170
191
171
192
/// Number of body bytes already sent */
172
193
open fileprivate( set) var countOfBytesSent : Int64 {
173
194
get {
174
- return taskAttributesIsolation. sync { self . _countOfBytesSent }
195
+ semaphore. wait ( )
196
+ defer {
197
+ semaphore. signal ( )
198
+ }
199
+ return self . _countOfBytesSent
200
+ }
201
+ set {
202
+ semaphore. wait ( )
203
+ self . _countOfBytesSent = newValue
204
+ semaphore. signal ( )
175
205
}
176
- set { taskAttributesIsolation. async ( flags: . barrier) { self . _countOfBytesSent = newValue } }
177
206
}
178
-
179
207
fileprivate var _countOfBytesSent : Int64 = 0
180
208
181
209
/// Number of body bytes we expect to send, derived from the Content-Length of the HTTP request */
@@ -201,9 +229,17 @@ open class URLSessionTask : NSObject, NSCopying {
201
229
*/
202
230
open var state : URLSessionTask . State {
203
231
get {
204
- return taskAttributesIsolation. sync { self . _state }
232
+ semaphore. wait ( )
233
+ defer {
234
+ semaphore. signal ( )
235
+ }
236
+ return self . _state
237
+ }
238
+ set {
239
+ semaphore. wait ( )
240
+ self . _state = newValue
241
+ semaphore. signal ( )
205
242
}
206
- set { taskAttributesIsolation. async ( flags: . barrier) { self . _state = newValue } }
207
243
}
208
244
fileprivate var _state : URLSessionTask . State = . suspended
209
245
@@ -283,10 +319,16 @@ open class URLSessionTask : NSObject, NSCopying {
283
319
/// URLSessionTask.highPriority, but use is not restricted to these.
284
320
open var priority : Float {
285
321
get {
286
- return taskAttributesIsolation. sync { self . _priority }
322
+ semaphore. wait ( )
323
+ defer {
324
+ semaphore. signal ( )
325
+ }
326
+ return self . _priority
287
327
}
288
328
set {
289
- taskAttributesIsolation. async ( flags: . barrier) { self . _priority = newValue }
329
+ semaphore. wait ( )
330
+ self . _priority = newValue
331
+ semaphore. signal ( )
290
332
}
291
333
}
292
334
fileprivate var _priority : Float = URLSessionTask . defaultPriority
0 commit comments