@@ -74,7 +74,9 @@ public class HTTPClient {
74
74
let poolManager : HTTPConnectionPool . Manager
75
75
76
76
/// Shared thread pool used for file IO. It is given to the user through ``HTTPClientResponseDelegate/provideSharedThreadPool(fileIOPool:)-6phmu``
77
- private let fileIOThreadPool = NIOThreadPool ( numberOfThreads: 1 )
77
+ private var fileIOThreadPool : NIOThreadPool ?
78
+ private var fileIOThreadPoolLock = Lock ( )
79
+
78
80
private var state : State
79
81
private let stateLock = Lock ( )
80
82
@@ -100,7 +102,6 @@ public class HTTPClient {
100
102
public required init ( eventLoopGroupProvider: EventLoopGroupProvider ,
101
103
configuration: Configuration = Configuration ( ) ,
102
104
backgroundActivityLogger: Logger ) {
103
- self . fileIOThreadPool. start ( )
104
105
self . eventLoopGroupProvider = eventLoopGroupProvider
105
106
switch self . eventLoopGroupProvider {
106
107
case . shared( let group) :
@@ -217,6 +218,16 @@ public class HTTPClient {
217
218
}
218
219
}
219
220
221
+ private func shutdownFileIOThreadPool( queue: DispatchQueue , _ callback: @escaping ( Error ? ) -> Void ) {
222
+ self . fileIOThreadPoolLock. withLockVoid {
223
+ guard let fileIOThreadPool = fileIOThreadPool else {
224
+ callback ( nil )
225
+ return
226
+ }
227
+ fileIOThreadPool. shutdownGracefully ( queue: queue, callback)
228
+ }
229
+ }
230
+
220
231
private func shutdown( requiresCleanClose: Bool , queue: DispatchQueue , _ callback: @escaping ( Error ? ) -> Void ) {
221
232
do {
222
233
try self . stateLock. withLock {
@@ -245,7 +256,7 @@ public class HTTPClient {
245
256
let error : Error ? = ( requiresClean && unclean) ? HTTPClientError . uncleanShutdown : nil
246
257
return ( callback, error)
247
258
}
248
- self . fileIOThreadPool . shutdownGracefully ( queue: queue) { ioThreadPoolError in
259
+ self . shutdownFileIOThreadPool ( queue: queue) { ioThreadPoolError in
249
260
self . shutdownEventLoop ( queue: queue) { error in
250
261
let reportedError = error ?? ioThreadPoolError ?? uncleanError
251
262
callback ( reportedError)
@@ -255,6 +266,18 @@ public class HTTPClient {
255
266
}
256
267
}
257
268
269
+ private func makeOrGetFileIOThreadPool( ) -> NIOThreadPool {
270
+ self . fileIOThreadPoolLock. withLock {
271
+ guard let fileIOThreadPool = fileIOThreadPool else {
272
+ let fileIOThreadPool = NIOThreadPool ( numberOfThreads: ProcessInfo . processInfo. processorCount)
273
+ fileIOThreadPool. start ( )
274
+ self . fileIOThreadPool = fileIOThreadPool
275
+ return fileIOThreadPool
276
+ }
277
+ return fileIOThreadPool
278
+ }
279
+ }
280
+
258
281
/// Execute `GET` request using specified URL.
259
282
///
260
283
/// - parameters:
@@ -572,8 +595,6 @@ public class HTTPClient {
572
595
metadata: [ " ahc-eventloop " : " \( taskEL) " ,
573
596
" ahc-el-preference " : " \( eventLoopPreference) " ] )
574
597
575
- delegate. provideSharedThreadPool ( fileIOPool: self . fileIOThreadPool)
576
-
577
598
let failedTask : Task < Delegate . Response > ? = self . stateLock. withLock {
578
599
switch state {
579
600
case . upAndRunning:
@@ -582,7 +603,8 @@ public class HTTPClient {
582
603
logger. debug ( " client is shutting down, failing request " )
583
604
return Task< Delegate . Response> . failedTask( eventLoop: taskEL,
584
605
error: HTTPClientError . alreadyShutdown,
585
- logger: logger)
606
+ logger: logger,
607
+ makeOrGetFileIOThreadPool: self . makeOrGetFileIOThreadPool)
586
608
}
587
609
}
588
610
@@ -605,7 +627,7 @@ public class HTTPClient {
605
627
}
606
628
} ( )
607
629
608
- let task = Task < Delegate . Response > ( eventLoop: taskEL, logger: logger)
630
+ let task = Task < Delegate . Response > ( eventLoop: taskEL, logger: logger, makeOrGetFileIOThreadPool : self . makeOrGetFileIOThreadPool )
609
631
do {
610
632
let requestBag = try RequestBag (
611
633
request: request,
0 commit comments