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()
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值