use tokio::sync::oneshot;
use crate::ActorExitStatus;
pub enum JoinHandle {
ThreadJoinHandle(oneshot::Receiver<ActorExitStatus>),
TokioTaskJoinHandle(tokio::task::JoinHandle<ActorExitStatus>),
}
impl JoinHandle {
pub fn create_for_thread() -> (JoinHandle, oneshot::Sender<ActorExitStatus>) {
let (tx, rx) = oneshot::channel();
let join_handle = JoinHandle::ThreadJoinHandle(rx);
(join_handle, tx)
}
pub fn create_for_task(join_handle: tokio::task::JoinHandle<ActorExitStatus>) -> JoinHandle {
JoinHandle::TokioTaskJoinHandle(join_handle)
}
pub async fn join(self) -> ActorExitStatus {
match self {
Self::ThreadJoinHandle(rx) => rx.await.unwrap_or(ActorExitStatus::Panicked),
Self::TokioTaskJoinHandle(join_handle) => match join_handle.await {
Ok(exit_status) => exit_status,
Err(join_err) => {
if join_err.is_panic() {
ActorExitStatus::Panicked
} else {
ActorExitStatus::Killed
}
}
},
}
}
}
#[cfg(test)]
mod tests {
use super::JoinHandle;
use crate::ActorExitStatus;
#[tokio::test]
async fn test_join_handle_ok() {
let (join_handle, tx) = JoinHandle::create_for_thread();
tx.send(ActorExitStatus::Success).unwrap();
assert!(matches!(join_handle.join().await, ActorExitStatus::Success));
}
#[tokio::test]
async fn test_join_handle_panic() {
let (join_handle, tx) = JoinHandle::create_for_thread();
std::mem::drop(tx);
assert!(matches!(
join_handle.join().await,
ActorExitStatus::Panicked
));
}
}