#[allow(dead_code)]
pub fn timestamp() -> u64 {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs()
}
cfg_async! {
use futures_lite::future::{ready, Ready};
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
pub struct Notify {
rx: crate::channel::Receiver<()>,
triggered: bool,
}
impl std::fmt::Debug for Notify {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Notify").finish()
}
}
impl Notify {
pub fn new() -> (Self, NotifyHandle) {
let (tx, rx) = crate::channel::bounded(1);
let this = Self {
rx,
triggered: false,
};
(this, NotifyHandle { tx })
}
pub async fn wait(&mut self) {
if self.triggered {
return;
}
use futures_lite::StreamExt as _;
let _ = self.rx.next().await;
self.triggered = true;
}
}
#[derive(Clone)]
pub struct NotifyHandle {
tx: crate::channel::Sender<()>,
}
impl std::fmt::Debug for NotifyHandle {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("NotifyHandle").finish()
}
}
impl NotifyHandle {
pub async fn notify(self) -> bool {
self.tx.send(()).await.is_ok()
}
}
pub enum Either<L, R> {
Left(L),
Right(R),
}
pub use Either::{Left, Right};
pub trait FutExt
where
Self: Future + Send + Sync + Sized,
Self::Output: Send + Sync,
{
fn either<F>(self, other: F) -> Or<Self, F>
where
F: Future + Send + Sync,
F::Output: Send + Sync;
fn first<F>(self, other: F) -> Or<Self, F>
where
F: Future + Send + Sync,
F::Output: Send + Sync;
fn now_or_never(self) -> Or<Self, Ready<()>>;
}
impl<T> FutExt for T
where
T: Future + Send + Sync,
T::Output: Send + Sync,
{
fn either<F>(self, right: F) -> Or<Self, F>
where
F: Future + Send + Sync,
F::Output: Send + Sync,
{
let left = self;
Or {
left,
right,
biased: false,
}
}
fn first<F>(self, right: F) -> Or<Self, F>
where
F: Future + Send + Sync,
F::Output: Send + Sync,
{
let left = self;
Or {
left,
right,
biased: true,
}
}
fn now_or_never(self) -> Or<Self, Ready<()>> {
self.first(ready(()))
}
}
pin_project_lite::pin_project! {
pub struct Or<A, B> {
#[pin]
left: A,
#[pin]
right: B,
biased: bool,
}
}
impl<A, B> Future for Or<A, B>
where
A: Future + Send + Sync,
A::Output: Send + Sync,
B: Future + Send + Sync,
A::Output: Send + Sync,
{
type Output = Either<A::Output, B::Output>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
macro_rules! poll {
($expr:ident => $map:expr) => {
if let Poll::Ready(t) = this.$expr.poll(cx).map($map) {
return Poll::Ready(t);
}
};
}
if *this.biased {
poll!(left => Left);
poll!(right => Right);
return Poll::Pending;
}
if fastrand::bool() {
poll!(left => Left);
poll!(right => Right);
} else {
poll!(right => Right);
poll!(left => Left);
}
Poll::Pending
}
}
}