use core::pin::Pin;
use futures::{
future::Future,
task::{Context, Poll, Waker},
};
use std::sync::{Arc, Mutex, MutexGuard};
#[derive(Debug, Clone)]
pub struct ButtplugFutureState<T> {
reply: Option<T>,
waker: Option<Waker>,
}
impl<T> Default for ButtplugFutureState<T> {
fn default() -> Self {
ButtplugFutureState::<T> {
reply: None,
waker: None,
}
}
}
impl<T> ButtplugFutureState<T> {
pub fn set_reply(&mut self, reply: T) {
if self.reply.is_some() {
panic!("set_reply_msg called multiple times on the same future.");
}
self.reply = Some(reply);
if self.waker.is_some() {
self.waker.take().unwrap().wake();
}
}
}
#[derive(Debug)]
pub struct ButtplugFutureStateShared<T> {
state: Arc<Mutex<ButtplugFutureState<T>>>,
}
unsafe impl<T> Sync for ButtplugFutureStateShared<T> {
}
unsafe impl<T> Send for ButtplugFutureStateShared<T> {
}
impl<T> ButtplugFutureStateShared<T> {
pub fn new(state: ButtplugFutureState<T>) -> Self {
Self {
state: Arc::new(Mutex::new(state)),
}
}
pub(super) fn lock(&self) -> MutexGuard<'_, ButtplugFutureState<T>> {
self.state.lock().unwrap()
}
pub fn set_reply(&self, reply: T) {
self.lock().set_reply(reply);
}
}
impl<T> Default for ButtplugFutureStateShared<T> {
fn default() -> Self {
Self {
state: Arc::new(Mutex::new(ButtplugFutureState::<T>::default())),
}
}
}
impl<T> Clone for ButtplugFutureStateShared<T> {
fn clone(&self) -> Self {
Self {
state: self.state.clone(),
}
}
}
#[derive(Debug)]
pub struct ButtplugFuture<T> {
waker_state: ButtplugFutureStateShared<T>,
}
impl<T> Default for ButtplugFuture<T> {
fn default() -> Self {
ButtplugFuture::<T> {
waker_state: ButtplugFutureStateShared::<T>::default(),
}
}
}
impl<T> ButtplugFuture<T> {
pub fn get_state_clone(&self) -> ButtplugFutureStateShared<T> {
self.waker_state.clone()
}
}
impl<T> Future for ButtplugFuture<T> {
type Output = T;
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let mut waker_state = self.waker_state.lock();
if waker_state.reply.is_some() {
let msg = waker_state.reply.take().unwrap();
Poll::Ready(msg)
} else {
waker_state.waker = Some(cx.waker().clone());
Poll::Pending
}
}
}