mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
experiment with a slowjob that can return data
This commit is contained in:
parent
4e4aa0d1db
commit
8b6b463177
@ -76,6 +76,7 @@ pub mod uid;
|
||||
#[cfg(not(target_arch = "wasm32"))] pub mod vol;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod volumes;
|
||||
pub mod slowjob;
|
||||
|
||||
pub use combat::DamageSource;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
|
100
common/src/slowjob.rs
Normal file
100
common/src/slowjob.rs
Normal file
@ -0,0 +1,100 @@
|
||||
use std::sync::RwLock;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{Ordering, AtomicU64};
|
||||
use core::any::Any;
|
||||
use crossbeam_channel::{Receiver, Sender};
|
||||
|
||||
/// a slow job is a CPU heavy task, that is not I/O blocking.
|
||||
/// It usually takes longer than a tick to compute, so it's outsourced
|
||||
/// Internally the rayon threadpool is used to calculate t
|
||||
pub struct SlowJobPool {
|
||||
next_id: AtomicU64,
|
||||
queue: RwLock<HashMap<String, HashMap<u64, Queue>>>,
|
||||
finished: RwLock<HashMap<String, Vec<Box<dyn Any>>>>,
|
||||
running_jobs: RwLock<HashMap<String, Arc<AtomicU64>>>,
|
||||
receiver: Receiver<(String, Box<dyn Any>)>,
|
||||
sender: Sender<(String, Box<dyn Any>)>,
|
||||
}
|
||||
|
||||
pub struct SlowJob {
|
||||
name: String,
|
||||
id: u64,
|
||||
}
|
||||
|
||||
struct Queue {
|
||||
task: Box<dyn FnOnce() -> ()>,
|
||||
running_cnt: Arc<AtomicU64>,
|
||||
}
|
||||
|
||||
|
||||
impl SlowJobPool {
|
||||
pub fn new() -> Self {
|
||||
let (sender,receiver) = crossbeam_channel::unbounded();
|
||||
Self {
|
||||
next_id: AtomicU64::new(0),
|
||||
queue: RwLock::new(HashMap::new()),
|
||||
finished: RwLock::new(HashMap::new()),
|
||||
receiver,
|
||||
sender
|
||||
}
|
||||
}
|
||||
|
||||
/// spawn a new slow job
|
||||
pub fn spawn<F, D>(&self, name: &str, f: F) -> SlowJob where
|
||||
F: FnOnce() -> D + Send + 'static,
|
||||
D: Any + 'static,
|
||||
{
|
||||
let id = self.next_id.fetch_add(1, Ordering::Relaxed);
|
||||
let running_cnt = {
|
||||
let mut lock = self.running_jobs.write().unwrap();
|
||||
lock.entry(name.to_string()).or_default().clone()
|
||||
};
|
||||
let running_cnt_clone = Arc::clone(&running_cnt);
|
||||
let sender = self.sender.clone();
|
||||
let name_clone = name.to_string();
|
||||
let queue = Queue {
|
||||
task: Box::new(move || {
|
||||
let result = f();
|
||||
let _ = sender.send((name_clone, Box::new(result)));
|
||||
running_cnt_clone.fetch_sub(1, Ordering::Relaxed);
|
||||
}),
|
||||
running_cnt,
|
||||
};
|
||||
{
|
||||
let mut lock = self.queue.write().unwrap();
|
||||
lock.entry(name.to_string()).or_default().insert(id, queue);
|
||||
}
|
||||
SlowJob {
|
||||
name: name.to_string(),
|
||||
id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cancel(&self, job: SlowJob) {
|
||||
let mut lock = self.queue.write().unwrap();
|
||||
if let Some(map) = lock.get_mut(&job.name) {
|
||||
map.remove(&job.id);
|
||||
}
|
||||
}
|
||||
|
||||
/// collect all slow jobs finished
|
||||
pub fn collect(&self, name: &str) -> Vec<Box<dyn Any>> {
|
||||
let mut lock = self.finished.write().unwrap();
|
||||
for (name, data) in self.receiver.try_iter() {
|
||||
lock.entry(name).or_default().push(data);
|
||||
}
|
||||
lock.remove(name).unwrap_or_default()
|
||||
}
|
||||
|
||||
fn maintain(&self) {
|
||||
/*
|
||||
let mut lock = self.queue.write().unwrap();
|
||||
if let Some(map) = lock.get_mut(&job.name) {
|
||||
map.remove(&job.id);
|
||||
}
|
||||
*/
|
||||
|
||||
//let d = rayon::spawn(f);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user