Progress checker works

This commit is contained in:
quexeky
2024-10-18 20:42:26 +11:00
parent 496c6a57e3
commit 7fec00ded0
6 changed files with 98 additions and 11 deletions
+1
View File
@@ -1,2 +1,3 @@
mod downloads; mod downloads;
mod manifest; mod manifest;
pub mod progress;
+66
View File
@@ -0,0 +1,66 @@
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use rayon::ThreadPoolBuilder;
pub struct ProgressChecker<T>
where T: 'static + Send + Sync
{
counter: AtomicUsize,
f: Arc<Box<dyn Fn(T) + Send + Sync + 'static>>,
}
impl<T> ProgressChecker<T>
where T: Send + Sync
{
pub fn new(f: Box<dyn Fn(T) + Send + Sync + 'static>) -> Self {
Self {
f: f.into(),
counter: AtomicUsize::new(0)
}
}
pub async fn run_contexts_sequentially_async(&self, contexts: Vec<T>) {
for context in contexts {
(self.f)(context);
self.counter.fetch_add(1, Ordering::Relaxed);
}
}
pub fn run_contexts_sequentially(&self, contexts: Vec<T>) {
for context in contexts {
(self.f)(context);
self.counter.fetch_add(1, Ordering::Relaxed);
}
}
pub async fn run_contexts_parallel_async(&self, contexts: Vec<T>, max_threads: usize) {
let threads = ThreadPoolBuilder::new()
// If max_threads == 0, then the limit will be determined
// by Rayon's internal RAYON_NUM_THREADS
.num_threads(max_threads)
.build()
.unwrap();
for context in contexts {
let f = self.f.clone();
threads.spawn(move || f(context));
}
}
pub fn run_contexts_parallel(&self, contexts: Vec<T>, max_threads: usize) {
let threads = ThreadPoolBuilder::new()
// If max_threads == 0, then the limit will be determined
// by Rayon's internal RAYON_NUM_THREADS
.num_threads(max_threads)
.build()
.unwrap();
for context in contexts {
let f = self.f.clone();
threads.spawn(move || f(context));
}
}
pub fn get_progress(&self) -> usize {
self.counter.load(Ordering::Relaxed)
}
// I strongly dislike type casting in my own code, so I've shovelled it into here
pub fn get_progress_percentage<C: Into<f64>>(&self, capacity: C) -> f64 {
(self.get_progress() as f64) / (capacity.into())
}
}
+2 -1
View File
@@ -5,6 +5,8 @@ mod remote;
mod unpacker; mod unpacker;
mod downloads; mod downloads;
mod utils; mod utils;
#[cfg(test)]
mod tests;
use auth::{auth_initiate, generate_authorization_header, recieve_handshake}; use auth::{auth_initiate, generate_authorization_header, recieve_handshake};
use db::{DatabaseInterface, DATA_ROOT_DIR}; use db::{DatabaseInterface, DATA_ROOT_DIR};
@@ -104,7 +106,6 @@ pub fn run() {
fetch_library, fetch_library,
fetch_game, fetch_game,
// Downloads // Downloads
download_game
]) ])
.plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_shell::init())
.setup(|app| { .setup(|app| {
+1
View File
@@ -0,0 +1 @@
mod progress_tests;
+17
View File
@@ -0,0 +1,17 @@
use crate::downloads::progress::ProgressChecker;
#[test]
fn test_progress_sequentially() {
let p = ProgressChecker::new(Box::new(test_fn));
p.run_contexts_sequentially((1..100).collect());
println!("Progress: {}", p.get_progress_percentage(100));
}
#[test]
fn test_progress_parallel() {
let p = ProgressChecker::new(Box::new(test_fn));
p.run_contexts_parallel((1..100).collect(), 10);
}
fn test_fn(int: usize) {
println!("{}", int);
}
+9 -8
View File
@@ -1,13 +1,9 @@
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::atomic::Ordering::Relaxed; use std::sync::atomic::Ordering::Relaxed;
use crate::utils::ProgressChecker::Complete; use rayon::{ThreadPool, ThreadPoolBuilder};
#[derive(Eq, PartialEq)]
pub enum ProgressChecker {
Complete,
Incomplete
}
/*
// This function is designed to take in any function which does not regularly return a value, // This function is designed to take in any function which does not regularly return a value,
// and instead loops over it until it returns "Complete". The current number of iterations // and instead loops over it until it returns "Complete". The current number of iterations
// is counted by "progress" // is counted by "progress"
@@ -18,16 +14,20 @@ pub async fn progress_updater(function: Box<dyn Fn() -> ProgressChecker>, progre
} }
} }
pub async fn new_progress_updater<T, D>(function: Box<dyn Fn(T) -> D>, contexts: T, progress: AtomicUsize) {
}
pub async fn threaded_progress_updater<F>(f: F, progress: AtomicUsize, max_threads: usize, instances: usize) -> ProgressChecker pub async fn threaded_progress_updater<F>(f: F, progress: AtomicUsize, max_threads: usize, instances: usize) -> ProgressChecker
where F: Fn() -> ProgressChecker + Send + Clone + Copy + 'static where F: Fn() -> ProgressChecker + Send + Clone + Copy + 'static
{ {
let mut threads = Vec::new(); let mut threads = Vec::new();
let pool = ThreadPoolBuilder::new().num_threads(max_threads).build().unwrap();
for instance in 0..instances { for instance in 0..instances {
let func = tokio::spawn(async move { pool.spawn(move || -> ProgressChecker {
let res = f(); let res = f();
return res return res
}); });
threads.push(func);
} }
let mut completed = ProgressChecker::Incomplete; let mut completed = ProgressChecker::Incomplete;
for thread in threads { for thread in threads {
@@ -42,3 +42,4 @@ where F: Fn() -> ProgressChecker + Send + Clone + Copy + 'static
fn test() -> ProgressChecker { fn test() -> ProgressChecker {
ProgressChecker::Incomplete ProgressChecker::Incomplete
} }
*/