rust异步编程:官方标准库

标准库代码位于https://github.com/rust-lang/rust/tree/master/library
这里使用目前最新版本1.45.2

涉及的包

std::future::*

对应src/libstd/future.rs,主要提供以下api

pub use core::future::Future;
pub use core::future::{
    
    from_generator, get_context, ResumeTy};
pub use core::future::{
    
    pending, ready, Pending, Ready};
pub use core::future::IntoFuture;

core::future对应src/libcore/future目录,有以下文件

future.rs      
into_future.rs 
mod.rs         
pending.rs     
poll_fn.rs     
ready.rs

std::poll::*std::wake::*

对应src/libcore/task/mod.rs,主要提供以下api

mod poll;
pub use self::poll::Poll;

mod wake;
pub use self::wake::{
    
    Context, RawWaker, RawWakerVTable, Waker};

src/libcore/task目录,有以下文件

mod.rs
poll.rs
wake.rs

Future

src/libcore/future/future.rs

#[lang = "future_trait"]
pub trait Future {
    
    
    type Output;
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}

Future trait 是异步编程最基础的trait,它有一个poll方法,poll的第二个参数是Context,Context包含一个唤醒函数,poll方法返回Poll::Ready或者Poll::Pending

Context

src/libcore/task/wake.rs

异步任务的上下文,Future的poll方法使用,目前内部只包装了Waker,不排除以后会加其他的东西

pub struct Context<'a> {
    
    
    waker: &'a Waker,
    _marker: PhantomData<fn(&'a ()) -> &'a ()>,
}

impl<'a> Context<'a> {
    
    
    #[inline]
    pub fn from_waker(waker: &'a Waker) -> Self {
    
    
        Context {
    
     waker, _marker: PhantomData }
    }
    #[inline]
    pub fn waker(&self) -> &'a Waker {
    
    
        &self.waker
    }
}

Waker

src/libcore/task/wake.rs

唤醒函数,用于通知executor该task可以运行了,它实现了Send、Sync、Clone,封装了RawWaker实例,RawWaker定义了executor特定的唤醒行为(一般使用条件变量和互斥锁实现wait、notify)

pub struct Waker {
    
    
    waker: RawWaker,
}

impl Unpin for Waker {
    
    }
unsafe impl Send for Waker {
    
    }
unsafe impl Sync for Waker {
    
    }
impl Clone for Waker {
    
    
    fn clone(&self) -> Self {
    
    
        Waker {
    
    
            waker: unsafe {
    
     (self.waker.vtable.clone)(self.waker.data) },
        }
    }
}

RawWaker

src/libcore/task/wake.rs

#[derive(PartialEq, Debug)]
pub struct RawWaker {
    
    
    data: *const (),
    vtable: &'static RawWakerVTable,
}

RawWakerVTable

src/libcore/task/wake.rs

一个虚拟函数指针表(vtable),用在RawWaker中

#[derive(PartialEq, Copy, Clone, Debug)]
pub struct RawWakerVTable {
    
    

    clone: unsafe fn(*const ()) -> RawWaker,

    wake: unsafe fn(*const ()),

    wake_by_ref: unsafe fn(*const ()),

    drop: unsafe fn(*const ()),
}

Poll

src/libcore/task/poll.rs

Future的poll方法返回值

#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Poll<T> {
    
    
    Ready(T),
    Pending,
}

Ready

src/libcore/future/ready.rs

创建一个立即准备好值的Future

#[derive(Debug, Clone)]
pub struct Ready<T>(Option<T>);

impl<T> Unpin for Ready<T> {
    
    }

impl<T> Future for Ready<T> {
    
    
    type Output = T;

    #[inline]
    fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<T> {
    
    
        Poll::Ready(self.0.take().expect("Ready polled after completion"))
    }
}
pub fn ready<T>(t: T) -> Ready<T> {
    
    
    Ready(Some(t))
}

eg

 #![feature(future_readiness_fns)]
 use core::future;
 async fn run() {
    
    
   let a = future::ready(1);
   assert_eq!(a.await, 1);
}

Pending

src/libcore/future/pending.rs

创建一个永远也无法完成(计算)的Future

#[derive(Debug)]
pub struct Pending<T> {
    
    
    _data: marker::PhantomData<T>,
}

pub fn pending<T>() -> Pending<T> {
    
    
    Pending {
    
     _data: marker::PhantomData }
}
impl<T> Future for Pending<T> {
    
    
    type Output = T;

    fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<T> {
    
    
        Poll::Pending
    }
}

eg

#![feature(future_readiness_fns)]
use core::future;
async fn run() {
    
    
	let future = future::pending();
	let () = future.await;
    unreachable!();
}

IntoFuture

src/libcore/future/into_future.rs

将一个类型转换成Future

pub trait IntoFuture {
    
    
    type Output;
    type Future: Future<Output = Self::Output>;
    fn into_future(self) -> Self::Future;
}

impl<F: Future> IntoFuture for F {
    
    
    type Output = F::Output;
    type Future = F;
    fn into_future(self) -> Self::Future {
    
    
        self
    }
}

from_generator

src/libcore/future/mod.rs

  • ansyc代码块最终由编译器转换成一个生成器,生成器会包装在GenFuture中,GenFuture实现 Future,在poll中调用生成器的resume方法,如果是状态时Yielded则返回Poll::Pending,如果是Complete(x),则返回Poll::Ready(x)
  • ResumeTy 存在的意义:生成器无法实现for<'a, 'b> Generator<&'a mut Context<'b>>,因此需要一个裸指针,而裸指针或NonNull无法SendSync
#[derive(Debug, Copy, Clone)]
pub struct ResumeTy(NonNull<Context<'static>>);

unsafe impl Send for ResumeTy {
    
    }

unsafe impl Sync for ResumeTy {
    
    }

pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
where
    T: Generator<ResumeTy, Yield = ()>,
{
    
    
    struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);
    impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {
    
    }

    impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> {
    
    
        type Output = T::Return;
        fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
    
    
            // Safety:!Unpin + !Drop
            let gen = unsafe {
    
     Pin::map_unchecked_mut(self, |s| &mut s.0) };
            match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) {
    
    
                GeneratorState::Yielded(()) => Poll::Pending,
                GeneratorState::Complete(x) => Poll::Ready(x),
            }
        }
    }
    GenFuture(gen)
}


pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> {
    
    
    &mut *cx.0.as_ptr().cast()
}

猜你喜欢

转载自blog.csdn.net/kk3909/article/details/108155264