You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
80 lines
1.6 KiB
80 lines
1.6 KiB
//! Hosts `Imouto`'s `Kokoro`.
|
|
|
|
use super::*;
|
|
use std::{
|
|
pin::Pin,
|
|
task::{
|
|
Poll,
|
|
Context,
|
|
},
|
|
mem,
|
|
};
|
|
use pin_project::{
|
|
pin_project,
|
|
};
|
|
use futures::{
|
|
future::Future,
|
|
};
|
|
use tokio::{
|
|
task,
|
|
sync::{
|
|
oneshot,
|
|
mpsc,
|
|
},
|
|
};
|
|
|
|
#[derive(Debug)]
|
|
pub enum Worker
|
|
{
|
|
Attached(task::JoinHandle<Result<(), eyre::Report>>),
|
|
/// Worker has not been attached yet
|
|
Suspended(Kokoro),
|
|
/// Worker filed to spawn,
|
|
Crashed,
|
|
}
|
|
|
|
/// Host this `Kokoro`
|
|
async fn work(mut kokoro: Kokoro, mut recv: mpsc::Receiver<Vec<Delta>>) -> Result<(), eyre::Report>
|
|
{
|
|
while let Some(new) = recv.recv().await {
|
|
kokoro.apply(new).await?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
impl Worker
|
|
{
|
|
/// Host this suspended state worker with a channel to receive updates from.
|
|
///
|
|
/// # Panics
|
|
/// If we are not in the `Suspended` state.
|
|
pub fn host(&mut self, recv: mpsc::Receiver<Vec<Delta>>) -> WorkerHandle
|
|
{
|
|
match mem::replace(self, Self::Crashed) {
|
|
Self::Suspended(kokoro) => {
|
|
let (tx, rx) = oneshot::channel();
|
|
*self = Self::Attached(task::spawn(async move {
|
|
let vl = work(kokoro, recv).await;
|
|
tx.send(()).unwrap();
|
|
vl
|
|
}));
|
|
WorkerHandle(rx)
|
|
},
|
|
_ => panic!("Attempted to host non-suspended worker"),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A handle on a spawned worker
|
|
#[pin_project]
|
|
pub struct WorkerHandle(#[pin] oneshot::Receiver<()>);
|
|
|
|
impl Future for WorkerHandle
|
|
{
|
|
type Output = ();
|
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
let this = self.project();
|
|
this.0.poll(cx).map(|x| x.unwrap())
|
|
}
|
|
}
|