use super::*;
use core::pin::Pin;
use derive_more::{Display, Error};
use std::future::Future;
use std::task::{Context, Poll};
use std::time::Duration;
use crate::ResourceId;
pub struct Sleep {
id: ResourceId,
}
pub fn sleep(duration: Duration) -> Sleep {
let id = ocall::create_timer(duration.as_millis() as i32).expect("failed to create timer");
Sleep { id: ResourceId(id) }
}
impl Future for Sleep {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
use env::OcallError;
let waker_id = env::tasks::intern_waker(cx.waker().clone());
let rv = ocall::poll_read(waker_id, self.id.0, &mut []);
match rv {
Ok(_) => Poll::Ready(()),
Err(OcallError::Pending) => Poll::Pending,
Err(err) => panic!("unexpected error: {:?}", err),
}
}
}
#[derive(Display, Error, Debug)]
pub struct TimedOut;
pub async fn timeout<T: Future<Output = O>, O>(
duration: Duration,
future: T,
) -> Result<O, TimedOut> {
use futures::FutureExt;
futures::select! {
v = future.fuse() => Ok(v),
_ = sleep(duration).fuse() => Err(TimedOut),
}
}
pub struct Rest {
resting: bool,
}
impl Rest {
pub fn new(resting: bool) -> Self {
Rest { resting }
}
}
impl Future for Rest {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.resting {
self.resting = false;
cx.waker().wake_by_ref();
Poll::Pending
} else {
Poll::Ready(())
}
}
}
pub fn maybe_rest() -> Rest {
let remaining = ocall::gas_remaining().expect("failed to get gas remaining");
Rest::new(remaining < 30)
}