mirror of
https://github.com/4yn/slidershim.git
synced 2026-09-07 16:25:40 -05:00
Async worker
This commit is contained in:
39
src-tauri/src/bin/test_async.rs
Normal file
39
src-tauri/src/bin/test_async.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
extern crate slidershim;
|
||||
|
||||
use std::{io, time::Duration};
|
||||
|
||||
use tokio::time::sleep;
|
||||
|
||||
// use slidershim::slider_io::worker::{AsyncJob, AsyncJobFut, AsyncJobRecvStop, AsyncWorker};
|
||||
|
||||
// struct CounterJob;
|
||||
|
||||
// impl AsyncJob for CounterJob {
|
||||
// fn job(self, mut recv_stop: AsyncJobRecvStop) -> AsyncJobFut {
|
||||
// return Box::pin(async move {
|
||||
// let mut x = 0;
|
||||
// loop {
|
||||
// x += 1;
|
||||
// println!("{}", x);
|
||||
// sleep(Duration::from_millis(500)).await;
|
||||
// match recv_stop.try_recv() {
|
||||
// Ok(_) => {
|
||||
// println!("@@@");
|
||||
// break;
|
||||
// }
|
||||
// _ => {}
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
fn main() {
|
||||
env_logger::Builder::new()
|
||||
.filter_level(log::LevelFilter::Debug)
|
||||
.init();
|
||||
|
||||
// let worker = AsyncWorker::new("counter", CounterJob);
|
||||
let mut input = String::new();
|
||||
let string = io::stdin().read_line(&mut input).unwrap();
|
||||
}
|
||||
@@ -69,7 +69,7 @@ fn main() {
|
||||
.setup(move |app| {
|
||||
let app_handle = app.handle();
|
||||
let config_clone = Arc::clone(&config);
|
||||
app.listen_global("heartbeat", move |e| {
|
||||
app.listen_global("heartbeat", move |_| {
|
||||
let config_handle = config_clone.lock().unwrap();
|
||||
info!("Heartbeat received");
|
||||
app_handle
|
||||
|
||||
40
src-tauri/src/slider_io/brokenithm.rs
Normal file
40
src-tauri/src/slider_io/brokenithm.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
use std::{convert::Infallible, net::SocketAddr};
|
||||
|
||||
use log::info;
|
||||
use tokio::time::sleep;
|
||||
|
||||
use hyper::{
|
||||
server::conn::AddrStream,
|
||||
service::{make_service_fn, service_fn},
|
||||
Body, Request, Response, Server,
|
||||
};
|
||||
|
||||
async fn handle_request(
|
||||
request: Request<Body>,
|
||||
remote_addr: SocketAddr,
|
||||
) -> Result<Response<Body>, Infallible> {
|
||||
Ok(Response::new(Body::from(format!(
|
||||
"Hello there connection {}\n",
|
||||
remote_addr
|
||||
))))
|
||||
}
|
||||
|
||||
pub async fn brokenithm_server() {
|
||||
let addr = SocketAddr::from(([0, 0, 0, 0], 1666));
|
||||
|
||||
info!("Brokenithm opening on {:?}", addr);
|
||||
|
||||
let make_svc = make_service_fn(|conn: &AddrStream| {
|
||||
let remote_addr = conn.remote_addr();
|
||||
async move {
|
||||
Ok::<_, Infallible>(service_fn(move |request: Request<Body>| {
|
||||
handle_request(request, remote_addr)
|
||||
}))
|
||||
}
|
||||
});
|
||||
|
||||
let server = Server::bind(&addr).serve(make_svc);
|
||||
if let Err(e) = server.await {
|
||||
eprintln!("Server error: {}", e);
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ use crate::slider_io::{
|
||||
config::DeviceMode,
|
||||
controller_state::{ControllerState, FullState, LedState},
|
||||
utils::{Buffer, ShimError},
|
||||
worker::Job,
|
||||
worker::ThreadJob,
|
||||
};
|
||||
|
||||
type HidReadCallback = fn(&Buffer, &mut ControllerState) -> ();
|
||||
@@ -212,7 +212,7 @@ impl HidDeviceJob {
|
||||
|
||||
const TIMEOUT: Duration = Duration::from_millis(20);
|
||||
|
||||
impl Job for HidDeviceJob {
|
||||
impl ThreadJob for HidDeviceJob {
|
||||
fn setup(&mut self) -> bool {
|
||||
match self.setup_impl() {
|
||||
Ok(r) => {
|
||||
|
||||
@@ -14,7 +14,7 @@ use crate::slider_io::{
|
||||
controller_state::{FullState, LedState},
|
||||
utils::Buffer,
|
||||
voltex::VoltexState,
|
||||
worker::Job,
|
||||
worker::ThreadJob,
|
||||
};
|
||||
|
||||
pub struct LedJob {
|
||||
@@ -150,7 +150,7 @@ impl LedJob {
|
||||
}
|
||||
}
|
||||
|
||||
impl Job for LedJob {
|
||||
impl ThreadJob for LedJob {
|
||||
fn setup(&mut self) -> bool {
|
||||
match &self.mode {
|
||||
LedMode::Serial { port } => {
|
||||
|
||||
@@ -2,15 +2,15 @@ use log::info;
|
||||
|
||||
use crate::slider_io::{
|
||||
config::Config, controller_state::FullState, device::HidDeviceJob, led::LedJob,
|
||||
output::OutputJob, worker::Worker,
|
||||
output::OutputJob, worker::ThreadWorker,
|
||||
};
|
||||
|
||||
pub struct Manager {
|
||||
state: FullState,
|
||||
config: Config,
|
||||
device_worker: Worker,
|
||||
output_worker: Worker,
|
||||
led_worker: Worker,
|
||||
device_worker: ThreadWorker,
|
||||
output_worker: ThreadWorker,
|
||||
led_worker: ThreadWorker,
|
||||
}
|
||||
|
||||
impl Manager {
|
||||
@@ -21,9 +21,12 @@ impl Manager {
|
||||
info!("LED config {:?}", config.led_mode);
|
||||
|
||||
let state = FullState::new();
|
||||
let device_worker = Worker::new(HidDeviceJob::from_config(&state, &config.device_mode));
|
||||
let output_worker = Worker::new(OutputJob::new(&state, &config.output_mode));
|
||||
let led_worker = Worker::new(LedJob::new(&state, &config.led_mode));
|
||||
let device_worker = ThreadWorker::new(
|
||||
"device",
|
||||
HidDeviceJob::from_config(&state, &config.device_mode),
|
||||
);
|
||||
let output_worker = ThreadWorker::new("output", OutputJob::new(&state, &config.output_mode));
|
||||
let led_worker = ThreadWorker::new("led", LedJob::new(&state, &config.led_mode));
|
||||
|
||||
Self {
|
||||
state,
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
mod config;
|
||||
mod utils;
|
||||
mod worker;
|
||||
pub mod worker;
|
||||
|
||||
mod controller_state;
|
||||
mod voltex;
|
||||
|
||||
mod brokenithm;
|
||||
mod gamepad;
|
||||
mod keyboard;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::slider_io::{
|
||||
controller_state::FullState,
|
||||
gamepad::GamepadOutput,
|
||||
keyboard::KeyboardOutput,
|
||||
worker::Job,
|
||||
worker::ThreadJob,
|
||||
};
|
||||
|
||||
pub trait OutputHandler: Send + Drop {
|
||||
@@ -38,7 +38,7 @@ impl OutputJob {
|
||||
}
|
||||
}
|
||||
|
||||
impl Job for OutputJob {
|
||||
impl ThreadJob for OutputJob {
|
||||
fn setup(&mut self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
use std::{
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
@@ -6,23 +8,35 @@ use std::{
|
||||
thread,
|
||||
};
|
||||
|
||||
pub trait Job: Send {
|
||||
use log::info;
|
||||
|
||||
use tokio::{
|
||||
runtime::Runtime,
|
||||
sync::oneshot::{self, Receiver},
|
||||
task,
|
||||
};
|
||||
|
||||
pub trait ThreadJob: Send {
|
||||
fn setup(&mut self) -> bool;
|
||||
fn tick(&mut self);
|
||||
fn teardown(&mut self);
|
||||
}
|
||||
|
||||
pub struct Worker {
|
||||
pub struct ThreadWorker {
|
||||
name: &'static str,
|
||||
thread: Option<thread::JoinHandle<()>>,
|
||||
stop_signal: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl Worker {
|
||||
pub fn new<T: 'static + Job>(mut job: T) -> Self {
|
||||
impl ThreadWorker {
|
||||
pub fn new<T: 'static + ThreadJob>(name: &'static str, mut job: T) -> Self {
|
||||
info!("Thread worker starting {}", name);
|
||||
|
||||
let stop_signal = Arc::new(AtomicBool::new(false));
|
||||
|
||||
let stop_signal_clone = Arc::clone(&stop_signal);
|
||||
Self {
|
||||
name,
|
||||
thread: Some(thread::spawn(move || {
|
||||
let setup_res = job.setup();
|
||||
stop_signal_clone.store(!setup_res, Ordering::SeqCst);
|
||||
@@ -33,6 +47,7 @@ impl Worker {
|
||||
}
|
||||
job.tick();
|
||||
}
|
||||
info!("Thread worker stopping internal {}", name);
|
||||
job.teardown();
|
||||
})),
|
||||
stop_signal,
|
||||
@@ -40,11 +55,74 @@ impl Worker {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Worker {
|
||||
impl Drop for ThreadWorker {
|
||||
fn drop(&mut self) {
|
||||
info!("Thread worker stopping {}", self.name);
|
||||
|
||||
self.stop_signal.store(true, Ordering::SeqCst);
|
||||
if self.thread.is_some() {
|
||||
self.thread.take().unwrap().join().ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type AsyncJobRecvStop = oneshot::Receiver<()>;
|
||||
pub type AsyncJobFut = Pin<Box<dyn Future<Output = ()> + Send + 'static>>;
|
||||
pub trait AsyncJob {
|
||||
fn job(self, recv_stop: AsyncJobRecvStop) -> AsyncJobFut;
|
||||
}
|
||||
|
||||
pub struct AsyncWorker {
|
||||
name: &'static str,
|
||||
runtime: Runtime,
|
||||
task: Option<task::JoinHandle<()>>,
|
||||
stop_signal: Option<oneshot::Sender<()>>,
|
||||
}
|
||||
|
||||
impl AsyncWorker {
|
||||
pub fn new<T: 'static + AsyncJob + Send>(name: &'static str, job: T) -> AsyncWorker {
|
||||
info!("Async worker starting {}", name);
|
||||
|
||||
let (send_stop, recv_stop) = oneshot::channel::<()>();
|
||||
let runtime = tokio::runtime::Builder::new_multi_thread()
|
||||
.worker_threads(1)
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let task = runtime.spawn(async move {
|
||||
let fut = job.job(recv_stop);
|
||||
fut.await;
|
||||
});
|
||||
|
||||
AsyncWorker {
|
||||
name,
|
||||
runtime,
|
||||
task: Some(task),
|
||||
stop_signal: Some(send_stop),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for AsyncWorker {
|
||||
fn drop(&mut self) {
|
||||
info!("Async worker stopping {}", self.name);
|
||||
|
||||
if self.stop_signal.is_some() {
|
||||
let send_stop = self.stop_signal.take().unwrap();
|
||||
self.runtime.block_on(async move {
|
||||
send_stop.send(()).unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
let name = self.name;
|
||||
|
||||
if self.task.is_some() {
|
||||
let task = self.task.take().unwrap();
|
||||
self.runtime.block_on(async move {
|
||||
task.await;
|
||||
info!("Async worker stopping internal {}", name);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user