diff options
| author | 2026-01-18 12:17:56 +0800 | |
|---|---|---|
| committer | 2026-01-18 12:17:56 +0800 | |
| commit | e7d683d79bec482a13c821f8c1da3c8c1d719d1b (patch) | |
| tree | 09b03146e6ab8d4696406c4f4ed442c56e5b6ccb /src-tauri/src/core | |
| parent | 1021c921c5690ceb800c03140de0723f3338e121 (diff) | |
| download | DropOut-e7d683d79bec482a13c821f8c1da3c8c1d719d1b.tar.gz DropOut-e7d683d79bec482a13c821f8c1da3c8c1d719d1b.zip | |
fix(downloader): use proper atomic ordering for thread-safe progress tracking
Replace Ordering::Relaxed with appropriate synchronization:
- Ordering::AcqRel for fetch_add operations that modify shared state
- Ordering::Acquire for loads that depend on other thread's writes
- Ordering::Release for stores that other threads may read
This ensures visibility of downloaded bytes and completed files across
concurrent download tasks without data races.
Diffstat (limited to 'src-tauri/src/core')
| -rw-r--r-- | src-tauri/src/core/downloader.rs | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/src-tauri/src/core/downloader.rs b/src-tauri/src/core/downloader.rs index 9c6b7f0..26f6ebd 100644 --- a/src-tauri/src/core/downloader.rs +++ b/src-tauri/src/core/downloader.rs @@ -270,12 +270,12 @@ pub async fn download_with_resume( } current_pos += chunk_len; - let total_downloaded = progress.fetch_add(chunk_len, Ordering::Relaxed) + chunk_len; + let total_downloaded = progress.fetch_add(chunk_len, Ordering::AcqRel) + chunk_len; // Emit progress event (throttled) - let last_bytes = last_progress_bytes.load(Ordering::Relaxed); + let last_bytes = last_progress_bytes.load(Ordering::Acquire); if total_downloaded - last_bytes > 100 * 1024 || total_downloaded >= total_size { - last_progress_bytes.store(total_downloaded, Ordering::Relaxed); + last_progress_bytes.store(total_downloaded, Ordering::Release); let elapsed = start_time.elapsed().as_secs_f64(); let speed = if elapsed > 0.0 { @@ -319,7 +319,7 @@ pub async fn download_with_resume( all_success = false; if e.contains("cancelled") { // Save progress for resume - metadata.downloaded_bytes = progress.load(Ordering::Relaxed); + metadata.downloaded_bytes = progress.load(Ordering::Acquire); let meta_content = serde_json::to_string_pretty(&metadata).map_err(|e| e.to_string())?; tokio::fs::write(&meta_path, meta_content).await.ok(); @@ -335,7 +335,7 @@ pub async fn download_with_resume( if !all_success { // Save progress - metadata.downloaded_bytes = progress.load(Ordering::Relaxed); + metadata.downloaded_bytes = progress.load(Ordering::Acquire); let meta_content = serde_json::to_string_pretty(&metadata).map_err(|e| e.to_string())?; tokio::fs::write(&meta_path, meta_content).await.ok(); return Err("Some segments failed".to_string()); @@ -482,19 +482,19 @@ impl GlobalProgress { /// Get current progress snapshot without modification fn snapshot(&self) -> ProgressSnapshot { ProgressSnapshot { - completed_files: self.completed_files.load(Ordering::Relaxed), + completed_files: self.completed_files.load(Ordering::Acquire), total_files: self.total_files, - total_downloaded_bytes: self.total_downloaded_bytes.load(Ordering::Relaxed), + total_downloaded_bytes: self.total_downloaded_bytes.load(Ordering::Acquire), } } /// Increment completed files counter and return updated snapshot fn inc_completed(&self) -> ProgressSnapshot { - let completed = self.completed_files.fetch_add(1, Ordering::Relaxed) + 1; + let completed = self.completed_files.fetch_add(1, Ordering::Release) + 1; ProgressSnapshot { completed_files: completed, total_files: self.total_files, - total_downloaded_bytes: self.total_downloaded_bytes.load(Ordering::Relaxed), + total_downloaded_bytes: self.total_downloaded_bytes.load(Ordering::Acquire), } } @@ -502,10 +502,10 @@ impl GlobalProgress { fn add_bytes(&self, delta: u64) -> ProgressSnapshot { let total_bytes = self .total_downloaded_bytes - .fetch_add(delta, Ordering::Relaxed) + .fetch_add(delta, Ordering::AcqRel) + delta; ProgressSnapshot { - completed_files: self.completed_files.load(Ordering::Relaxed), + completed_files: self.completed_files.load(Ordering::Acquire), total_files: self.total_files, total_downloaded_bytes: total_bytes, } |