@@ -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
@@ -136,17 +134,32 @@ open class URLSessionTask : NSObject, NSCopying {
136
134
/// May differ from originalRequest due to http server redirection
137
135
/*@NSCopying*/ open fileprivate( set) var currentRequest : URLRequest ? {
138
136
get {
139
- return taskAttributesIsolation. sync { self . _currentRequest }
137
+ semaphore. wait ( )
138
+ defer {
139
+ semaphore. signal ( )
140
+ }
141
+ return self . _currentRequest
142
+ }
143
+ set {
144
+ semaphore. wait ( )
145
+ self . _currentRequest = newValue
146
+ semaphore. signal ( )
140
147
}
141
- //TODO: dispatch_barrier_async
142
- set { taskAttributesIsolation. async ( flags: . barrier) { self . _currentRequest = newValue } }
143
148
}
144
149
fileprivate var _currentRequest : URLRequest ? = nil
145
150
/*@NSCopying*/ open fileprivate( set) var response : URLResponse ? {
146
151
get {
147
- return taskAttributesIsolation. sync { self . _response }
152
+ semaphore. wait ( )
153
+ defer {
154
+ semaphore. signal ( )
155
+ }
156
+ return self . _response
157
+ }
158
+ set {
159
+ semaphore. wait ( )
160
+ self . _response = newValue
161
+ semaphore. signal ( )
148
162
}
149
- set { taskAttributesIsolation. async ( flags: . barrier) { self . _response = newValue } }
150
163
}
151
164
fileprivate var _response : URLResponse ? = nil
152
165
@@ -158,20 +171,35 @@ open class URLSessionTask : NSObject, NSCopying {
158
171
/// Number of body bytes already received
159
172
open fileprivate( set) var countOfBytesReceived : Int64 {
160
173
get {
161
- return taskAttributesIsolation. sync { self . _countOfBytesReceived }
174
+ semaphore. wait ( )
175
+ defer {
176
+ semaphore. signal ( )
177
+ }
178
+ return self . _countOfBytesReceived
179
+ }
180
+ set {
181
+ semaphore. wait ( )
182
+ self . _countOfBytesReceived = newValue
183
+ semaphore. signal ( )
162
184
}
163
- set { taskAttributesIsolation. async ( flags: . barrier) { self . _countOfBytesReceived = newValue } }
164
185
}
165
186
fileprivate var _countOfBytesReceived : Int64 = 0
166
187
167
188
/// Number of body bytes already sent */
168
189
open fileprivate( set) var countOfBytesSent : Int64 {
169
190
get {
170
- return taskAttributesIsolation. sync { self . _countOfBytesSent }
191
+ semaphore. wait ( )
192
+ defer {
193
+ semaphore. signal ( )
194
+ }
195
+ return self . _countOfBytesSent
196
+ }
197
+ set {
198
+ semaphore. wait ( )
199
+ self . _countOfBytesSent = newValue
200
+ semaphore. signal ( )
171
201
}
172
- set { taskAttributesIsolation. async ( flags: . barrier) { self . _countOfBytesSent = newValue } }
173
202
}
174
-
175
203
fileprivate var _countOfBytesSent : Int64 = 0
176
204
177
205
/// Number of body bytes we expect to send, derived from the Content-Length of the HTTP request */
@@ -207,9 +235,17 @@ open class URLSessionTask : NSObject, NSCopying {
207
235
*/
208
236
open var state : URLSessionTask . State {
209
237
get {
210
- return taskAttributesIsolation. sync { self . _state }
238
+ semaphore. wait ( )
239
+ defer {
240
+ semaphore. signal ( )
241
+ }
242
+ return self . _state
243
+ }
244
+ set {
245
+ semaphore. wait ( )
246
+ self . _state = newValue
247
+ semaphore. signal ( )
211
248
}
212
- set { taskAttributesIsolation. async ( flags: . barrier) { self . _state = newValue } }
213
249
}
214
250
fileprivate var _state : URLSessionTask . State = . suspended
215
251
@@ -289,10 +325,16 @@ open class URLSessionTask : NSObject, NSCopying {
289
325
/// URLSessionTask.highPriority, but use is not restricted to these.
290
326
open var priority : Float {
291
327
get {
292
- return taskAttributesIsolation. sync { self . _priority }
328
+ semaphore. wait ( )
329
+ defer {
330
+ semaphore. signal ( )
331
+ }
332
+ return self . _priority
293
333
}
294
334
set {
295
- taskAttributesIsolation. async ( flags: . barrier) { self . _priority = newValue }
335
+ semaphore. wait ( )
336
+ self . _priority = newValue
337
+ semaphore. signal ( )
296
338
}
297
339
}
298
340
fileprivate var _priority : Float = URLSessionTask . defaultPriority
0 commit comments