init
This commit is contained in:
commit
df3bbb09ab
4 changed files with 101 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
/Cargo.lock
|
7
Cargo.toml
Normal file
7
Cargo.toml
Normal file
|
@ -0,0 +1,7 @@
|
|||
[package]
|
||||
name = "jobdispatcher"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
authors = ["JMARyA <angelo@hydrar.de>"]
|
||||
|
||||
[dependencies]
|
5
README.md
Normal file
5
README.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
# JobDispatcher
|
||||
A thread-safe job dispatcher written in rust.
|
||||
|
||||
## Why does this exist?
|
||||
I had a data structure which could not be send across threads. So with this crate one can send the input over, the data structure can do it's thing in it's own thread and send the result back
|
87
src/lib.rs
Normal file
87
src/lib.rs
Normal file
|
@ -0,0 +1,87 @@
|
|||
use std::sync::{mpsc, Arc, Mutex};
|
||||
|
||||
#[derive(Clone)]
|
||||
/// A generic job dispatcher struct that allows sending jobs of type `T` and receiving results of type `V` using message passing.
|
||||
pub struct JobDispatcher<T: Send + 'static, V: Send + 'static> {
|
||||
sender: Arc<Mutex<mpsc::Sender<JobOrder<T, V>>>>,
|
||||
}
|
||||
|
||||
impl<T: Send + 'static, V: Send + 'static> JobDispatcher<T, V> {
|
||||
/// Creates a new instance of `JobDispatcher` and returns a tuple that contains it and a receiver end for `JobOrder`s.
|
||||
/// # Example:
|
||||
/// ```
|
||||
/// use jobdispatcher::*;
|
||||
/// // Create job dispatcher
|
||||
/// let (dispatcher, recv) = JobDispatcher::<i32, i32>::new();
|
||||
///
|
||||
/// // Worker Thread
|
||||
/// std::thread::spawn(move || {
|
||||
/// for job in recv {
|
||||
/// let result = job.param + 1;
|
||||
/// job.done(result);
|
||||
/// }
|
||||
/// });
|
||||
///
|
||||
/// // Usage
|
||||
/// let result = dispatcher.send(3);
|
||||
/// assert_eq!(result, 4);
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn new() -> (Self, mpsc::Receiver<JobOrder<T, V>>) {
|
||||
let (sender, receiver) = mpsc::channel();
|
||||
(
|
||||
Self {
|
||||
sender: Arc::new(Mutex::new(sender)),
|
||||
},
|
||||
receiver,
|
||||
)
|
||||
}
|
||||
|
||||
/// Sends a job of type `T` to the job dispatcher and waits for its result of type `V`.
|
||||
/// Returns the result of the job once it has been processed.
|
||||
/// # Panics
|
||||
/// This function panics when the `JobOrder` struct gets out of scope without returning a finished result.
|
||||
/// Additionally if the internal `Mutex` is poisoned, this function will panic as well.
|
||||
pub fn send(&self, param: T) -> V {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let job_order = JobOrder::new(param, move |ret| {
|
||||
tx.send(ret).unwrap();
|
||||
});
|
||||
self.sender.lock().unwrap().send(job_order).unwrap();
|
||||
rx.recv().unwrap()
|
||||
}
|
||||
|
||||
/// Sends a job of type `T` to the job dispatcher and waits for its result of type `V`.
|
||||
/// Returns `Some(V)` when the job returns an result, `None` if somehow nothing was returned or the internal `Mutex` is poisoned.
|
||||
pub fn try_send(&self, param: T) -> Option<V> {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let job_order = JobOrder::new(param, move |ret| {
|
||||
tx.send(ret).unwrap();
|
||||
});
|
||||
self.sender.lock().ok()?.send(job_order).ok()?;
|
||||
rx.recv().ok()
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct that represents a job order that encapsulates a job of type `T` and its result of type `V`, along with a callback function that will send the result back to the job origin.
|
||||
pub struct JobOrder<T, V> {
|
||||
/// The job parameter of type `T`.
|
||||
pub param: T,
|
||||
callback: Box<dyn FnOnce(V) + Send>,
|
||||
}
|
||||
|
||||
impl<T, V> JobOrder<T, V> {
|
||||
/// Creates a new `JobOrder` instance with the specified job parameter `param` of type `T` and a callback function that takes the job result of type `V` as an argument.
|
||||
#[must_use]
|
||||
fn new(param: T, callback: impl FnOnce(V) + Send + 'static) -> Self {
|
||||
Self {
|
||||
param,
|
||||
callback: Box::new(callback),
|
||||
}
|
||||
}
|
||||
|
||||
/// Send the result of the `JobOrder` back to it's origin
|
||||
pub fn done(self, val: V) {
|
||||
(self.callback)(val);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue