cyper_core/
executor.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
use std::{
    future::Future,
    pin::Pin,
    task::{Context, Poll},
    time::{Duration, Instant},
};

use hyper::rt::{Executor, Sleep, Timer};
use send_wrapper::SendWrapper;

/// An executor service based on [`compio::runtime`]. It uses
/// [`compio::runtime::spawn`] interally.
#[derive(Debug, Default, Clone)]
pub struct CompioExecutor;

impl<F: Future<Output = ()> + Send + 'static> Executor<F> for CompioExecutor {
    fn execute(&self, fut: F) {
        compio::runtime::spawn(fut).detach();
    }
}

struct SleepFuture<T: Send + Sync + Future<Output = ()>>(T);

impl<T: Send + Sync + Future<Output = ()>> Sleep for SleepFuture<T> {}

impl<T: Send + Sync + Future<Output = ()>> Future for SleepFuture<T> {
    type Output = ();

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        unsafe { self.map_unchecked_mut(|this| &mut this.0) }.poll(cx)
    }
}

/// An timer service based on [`compio::time`].
#[derive(Debug, Default, Clone)]
pub struct CompioTimer;

impl Timer for CompioTimer {
    fn sleep(&self, duration: Duration) -> Pin<Box<dyn Sleep>> {
        Box::pin(SleepFuture(SendWrapper::new(compio::time::sleep(duration))))
    }

    fn sleep_until(&self, deadline: Instant) -> Pin<Box<dyn Sleep>> {
        Box::pin(SleepFuture(SendWrapper::new(compio::time::sleep_until(
            deadline,
        ))))
    }
}