@@ -3,21 +3,15 @@ use crate::{error::DownloadError, Error};
3
3
use reqwest:: { Client , Url } ;
4
4
use std:: { path:: Path , sync:: Arc } ;
5
5
use tokio:: sync:: { mpsc, Semaphore } ;
6
- use tokio_util:: sync:: CancellationToken ;
6
+ use tokio_util:: { sync:: CancellationToken , task :: TaskTracker } ;
7
7
8
8
#[ derive( Debug ) ]
9
9
pub struct DownloadManager {
10
10
queue : mpsc:: Sender < DownloadRequest > ,
11
11
semaphore : Arc < Semaphore > ,
12
12
cancel : CancellationToken ,
13
13
config : DownloadManagerConfig ,
14
- }
15
-
16
- impl Drop for DownloadManager {
17
- fn drop ( & mut self ) {
18
- // Need to manually close the semaphore to make sure dispatcher_thread stops waiting for permits
19
- self . semaphore . close ( ) ;
20
- }
14
+ tracker : TaskTracker ,
21
15
}
22
16
23
17
impl Default for DownloadManager {
@@ -31,14 +25,16 @@ impl DownloadManager {
31
25
let ( tx, rx) = mpsc:: channel ( config. queue_size ( ) ) ;
32
26
let client = Client :: new ( ) ;
33
27
let semaphore = Arc :: new ( Semaphore :: new ( config. max_concurrent ( ) ) ) ;
28
+ let tracker = TaskTracker :: new ( ) ;
34
29
let manager = Self {
35
30
queue : tx,
36
31
semaphore : semaphore. clone ( ) ,
37
32
cancel : CancellationToken :: new ( ) ,
38
33
config,
34
+ tracker : tracker. clone ( ) ,
39
35
} ;
40
36
// Spawn the dispatcher thread to handle download requests
41
- tokio :: spawn ( async move { dispatcher_thread ( client, rx, semaphore) . await } ) ;
37
+ tracker . spawn ( dispatcher_thread ( client, rx, semaphore, tracker . clone ( ) ) ) ;
42
38
manager
43
39
}
44
40
@@ -98,14 +94,15 @@ async fn dispatcher_thread(
98
94
client : Client ,
99
95
mut rx : mpsc:: Receiver < DownloadRequest > ,
100
96
sem : Arc < Semaphore > ,
97
+ tracker : TaskTracker ,
101
98
) {
102
99
while let Some ( request) = rx. recv ( ) . await {
103
100
let permit = match sem. clone ( ) . acquire_owned ( ) . await {
104
101
Ok ( permit) => permit,
105
102
Err ( _) => break ,
106
103
} ;
107
104
let client = client. clone ( ) ;
108
- tokio :: spawn ( async move {
105
+ tracker . spawn ( async move {
109
106
// Move the permit into the worker thread so it's automatically released when the thread finishes
110
107
let _permit = permit;
111
108
download_thread ( client. clone ( ) , request) . await ;
0 commit comments