Rust asynchronous programming: futures-core of futures-rs

Article Directory

Overview

futures-core contains the core features and types of the future library

The directory structure is as follows

├── future.rs
├── lib.rs
├── stream.rs
└── task
    ├── __internal
    │   ├── atomic_waker.rs
    │   └── mod.rs
    ├── mod.rs
    └── poll.rs

Exposed api

futures-core/src/lib.rs

pub mod future;
pub use self::future::{
    
    Future, FusedFuture, TryFuture};

pub mod stream;
pub use self::stream::{
    
    Stream, FusedStream, TryStream};

#[macro_use]
pub mod task;

future

futures-core/src/future.rs

/// 用于动态分发Future
#[cfg(feature = "alloc")]
pub type BoxFuture<'a, T> = Pin<alloc::boxed::Box<dyn Future<Output = T> + Send + 'a>>;

/// 和`BoxFuture`类似, 只是没有send需求
#[cfg(feature = "alloc")]
pub type LocalBoxFuture<'a, T> = Pin<alloc::boxed::Box<dyn Future<Output = T> + 'a>>;

pub trait FusedFuture: Future {
    
    
    /// 如果不再对future轮循,则返回true
    fn is_terminated(&self) -> bool;
}


mod private_try_future {
    
    
    use super::Future;

    pub trait Sealed {
    
    }

    impl<F, T, E> Sealed for F where F: ?Sized + Future<Output = Result<T, E>> {
    
    }
}

/// 包含了出错的情况,将返回值封装在Result中
pub trait TryFuture: Future + private_try_future::Sealed {
    
    
    type Ok;

    type Error;
    
    fn try_poll(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Result<Self::Ok, Self::Error>>;
}

stream

futures-core/src/stream.rs

Stream is multiple futures, and each future can be iterated like an iterator

/// 用于动态分发Stream
#[cfg(feature = "alloc")]
pub type BoxStream<'a, T> = Pin<alloc::boxed::Box<dyn Stream<Item = T> + Send + 'a>>;

/// 和`BoxStream`类似, 只是没有send需求
#[cfg(feature = "alloc")]
pub type LocalBoxStream<'a, T> = Pin<alloc::boxed::Box<dyn Stream<Item = T> + 'a>>;


pub trait Stream {
    
    
    /// Values yielded by the stream.
    type Item;
    
    /// 尝试提取此流的下一个值,如果当前的值不可用,注册当前任务以唤醒
    /// 返回`Poll::Pending`,表示流的下一个值尚未准备好
    /// 返回`Poll::Ready(Some(val))`,表示流已经成功产生一个值
    /// 返回`Poll::Ready(None)` 表示流已经终止
    fn poll_next(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Self::Item>>;

    /// 返回流的剩余长度
    fn size_hint(&self) -> (usize, Option<usize>) {
    
    
        (0, None)
    }
}

pub trait FusedStream: Stream {
    
    
    /// 如果不再对stream轮循,则返回true
    fn is_terminated(&self) -> bool;
}

mod private_try_future {
    
    
    use super::Future;

    pub trait Sealed {
    
    }

    impl<F, T, E> Sealed for F where F: ?Sized + Future<Output = Result<T, E>> {
    
    }
}

/// 包含了出错的情况,将返回值封装在Result中
pub trait TryFuture: Future + private_try_future::Sealed {
    
    
    type Ok;

    type Error;

    fn try_poll(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Result<Self::Ok, Self::Error>>;
}

task

futures-core/src/task

Mainly includes the realization of AtomicWaker

pub struct AtomicWaker {
    
    
    state: AtomicUsize,
    waker: UnsafeCell<Option<Waker>>,
}

/// Idle state
const WAITING: usize = 0;

/// A new waker value is being registered with the `AtomicWaker` cell.
const REGISTERING: usize = 0b01;

/// The waker currently registered with the `AtomicWaker` cell is being woken.
const WAKING: usize = 0b10;


impl AtomicWaker {
    
    
    /// Create an `AtomicWaker`.
    pub const fn new() -> Self {
    
    
        // Make sure that task is Sync
        trait AssertSync: Sync {
    
    }
        impl AssertSync for Waker {
    
    }

        AtomicWaker {
    
    
            state: AtomicUsize::new(WAITING),
            waker: UnsafeCell::new(None),
        }
    }

    /// 注册waker 以便在调用wake时得到通知
    ///
    /// # Examples
    ///
    /// Here is how `register` is used when implementing a flag.
    ///
    /// ```
    /// use futures::future::Future;
    /// use futures::task::{Context, Poll, AtomicWaker};
    /// use std::sync::atomic::AtomicBool;
    /// use std::sync::atomic::Ordering::Relaxed;
    /// use std::pin::Pin;
    ///
    /// struct Flag {
    
    
    ///     waker: AtomicWaker,
    ///     set: AtomicBool,
    /// }
    ///
    /// impl Future for Flag {
    
    
    ///     type Output = ();
    ///
    ///     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
    
    
    ///         // Register **before** checking `set` to avoid a race condition
    ///         // that would result in lost notifications.
    ///         self.waker.register(cx.waker());
    ///
    ///         if self.set.load(Relaxed) {
    
    
    ///             Poll::Ready(())
    ///         } else {
    
    
    ///             Poll::Pending
    ///         }
    ///     }
    /// }
    /// ```
    pub fn register(&self, waker: &Waker) {
    
    
        match self.state.compare_and_swap(WAITING, REGISTERING, Acquire) {
    
    
            WAITING => {
    
    
                unsafe {
    
    
                    // Locked acquired, update the waker cell
                    *self.waker.get() = Some(waker.clone());

                    let res = self.state.compare_exchange(
                        REGISTERING, WAITING, AcqRel, Acquire);

                    match res {
    
    
                        Ok(_) => {
    
    
                        }
                        Err(actual) => {
    
    
                            debug_assert_eq!(actual, REGISTERING | WAKING);

                            let waker = (*self.waker.get()).take().unwrap();

                            self.state.swap(WAITING, AcqRel);

                            waker.wake();
                        }
                    }
                }
            }
            WAKING => {
    
    
                waker.wake_by_ref();
            }
            state => {
    
    
                debug_assert!(
                    state == REGISTERING ||
                    state == REGISTERING | WAKING);
            }
        }
    }

    /// 调用wake
    pub fn wake(&self) {
    
    
        if let Some(waker) = self.take() {
    
    
            waker.wake();
        }
    }

    /// 返回传递给register的最后一个Waker,以便用户唤醒它
    pub fn take(&self) -> Option<Waker> {
    
    
        match self.state.fetch_or(WAKING, AcqRel) {
    
    
            WAITING => {
    
    
                // The waking lock has been acquired.
                let waker = unsafe {
    
     (*self.waker.get()).take() };

                // Release the lock
                self.state.fetch_and(!WAKING, Release);

                waker
            }
            state => {
    
    
                debug_assert!(
                    state == REGISTERING ||
                    state == REGISTERING | WAKING ||
                    state == WAKING);
                None
            }
        }
    }
}

Guess you like

Origin blog.csdn.net/kk3909/article/details/108173741