@@ -30,18 +30,10 @@ public final class FileDownloadDelegate: HTTPClientResponseDelegate {
30
30
public typealias Response = Progress
31
31
32
32
private let filePath : String
33
- private let io : NonBlockingFileIO
33
+ private var io : NonBlockingFileIO ?
34
34
private let reportHead : ( ( HTTPResponseHead ) -> Void ) ?
35
35
private let reportProgress : ( ( Progress ) -> Void ) ?
36
36
37
- private enum ThreadPool {
38
- case unowned
39
- // if we own the thread pool we also need to shut it down
40
- case owned( NIOThreadPool )
41
- }
42
-
43
- private let threadPool : ThreadPool
44
-
45
37
private var fileHandleFuture : EventLoopFuture < NIOFileHandle > ?
46
38
private var writeFuture : EventLoopFuture < Void > ?
47
39
@@ -61,7 +53,7 @@ public final class FileDownloadDelegate: HTTPClientResponseDelegate {
61
53
reportHead: ( ( HTTPResponseHead ) -> Void ) ? = nil ,
62
54
reportProgress: ( ( Progress ) -> Void ) ? = nil
63
55
) throws {
64
- try self . init ( path: path, sharedThreadPool : pool, reportHead: reportHead, reportProgress: reportProgress)
56
+ try self . init ( path: path, pool : . some ( pool) , reportHead: reportHead, reportProgress: reportProgress)
65
57
}
66
58
67
59
/// Initializes a new file download delegate and spawns a new thread for file I/O.
@@ -78,31 +70,36 @@ public final class FileDownloadDelegate: HTTPClientResponseDelegate {
78
70
reportHead: ( ( HTTPResponseHead ) -> Void ) ? = nil ,
79
71
reportProgress: ( ( Progress ) -> Void ) ? = nil
80
72
) throws {
81
- try self . init ( path: path, sharedThreadPool : nil , reportHead: reportHead, reportProgress: reportProgress)
73
+ try self . init ( path: path, pool : nil , reportHead: reportHead, reportProgress: reportProgress)
82
74
}
83
75
84
76
private init (
85
77
path: String ,
86
- sharedThreadPool : NIOThreadPool ? ,
78
+ pool : NIOThreadPool ? ,
87
79
reportHead: ( ( HTTPResponseHead ) -> Void ) ? = nil ,
88
80
reportProgress: ( ( Progress ) -> Void ) ? = nil
89
81
) throws {
90
- let pool : NIOThreadPool
91
- if let sharedThreadPool = sharedThreadPool {
92
- pool = sharedThreadPool
93
- self . threadPool = . unowned
82
+ if let pool = pool {
83
+ self . io = NonBlockingFileIO ( threadPool: pool)
94
84
} else {
95
- pool = NIOThreadPool ( numberOfThreads: 1 )
96
- self . threadPool = . owned( pool)
85
+ // we should use the shared thread pool from the HTTPClient which
86
+ // we will get shortly through a call to provideSharedThreadPool(fileIOPool:)
87
+ self . io = nil
97
88
}
98
-
99
- pool. start ( )
100
- self . io = NonBlockingFileIO ( threadPool: pool)
89
+
101
90
self . filePath = path
102
91
103
92
self . reportHead = reportHead
104
93
self . reportProgress = reportProgress
105
94
}
95
+
96
+ public func provideSharedThreadPool( fileIOPool: NIOThreadPool ) {
97
+ guard self . io == nil else {
98
+ // user has provided their own thread pool
99
+ return
100
+ }
101
+ self . io = NonBlockingFileIO ( threadPool: fileIOPool)
102
+ }
106
103
107
104
public func didReceiveHead(
108
105
task: HTTPClient . Task < Response > ,
@@ -122,24 +119,27 @@ public final class FileDownloadDelegate: HTTPClientResponseDelegate {
122
119
task: HTTPClient . Task < Response > ,
123
120
_ buffer: ByteBuffer
124
121
) -> EventLoopFuture < Void > {
122
+ guard let io = io else {
123
+ preconditionFailure ( " thread pool not provided by HTTPClient before calling \( #function) " )
124
+ }
125
125
self . progress. receivedBytes += buffer. readableBytes
126
126
self . reportProgress ? ( self . progress)
127
127
128
128
let writeFuture : EventLoopFuture < Void >
129
129
if let fileHandleFuture = self . fileHandleFuture {
130
130
writeFuture = fileHandleFuture. flatMap {
131
- self . io. write ( fileHandle: $0, buffer: buffer, eventLoop: task. eventLoop)
131
+ io. write ( fileHandle: $0, buffer: buffer, eventLoop: task. eventLoop)
132
132
}
133
133
} else {
134
- let fileHandleFuture = self . io. openFile (
134
+ let fileHandleFuture = io. openFile (
135
135
path: self . filePath,
136
136
mode: . write,
137
137
flags: . allowFileCreation( ) ,
138
138
eventLoop: task. eventLoop
139
139
)
140
140
self . fileHandleFuture = fileHandleFuture
141
141
writeFuture = fileHandleFuture. flatMap {
142
- self . io. write ( fileHandle: $0, buffer: buffer, eventLoop: task. eventLoop)
142
+ io. write ( fileHandle: $0, buffer: buffer, eventLoop: task. eventLoop)
143
143
}
144
144
}
145
145
@@ -150,12 +150,6 @@ public final class FileDownloadDelegate: HTTPClientResponseDelegate {
150
150
private func close( fileHandle: NIOFileHandle ) {
151
151
try ! fileHandle. close ( )
152
152
self . fileHandleFuture = nil
153
- switch self . threadPool {
154
- case . unowned:
155
- break
156
- case . owned( let pool) :
157
- try ! pool. syncShutdownGracefully ( )
158
- }
159
153
}
160
154
161
155
private func finalize( ) {
@@ -177,14 +171,4 @@ public final class FileDownloadDelegate: HTTPClientResponseDelegate {
177
171
self . finalize ( )
178
172
return self . progress
179
173
}
180
-
181
- deinit {
182
- switch threadPool {
183
- case . unowned:
184
- break
185
- case . owned( let pool) :
186
- // if the delegate is unused we still need to shutdown the thread pool
187
- try ! pool. syncShutdownGracefully ( )
188
- }
189
- }
190
174
}
0 commit comments