Update docs

This commit is contained in:
Dániel Buga 2023-08-14 17:53:42 +02:00
parent e4f3979ec8
commit 890f29ccfe
2 changed files with 29 additions and 24 deletions

View File

@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
- Replaced Pender. Implementations now must define an extern function called `__pender`.
## 0.2.1 - 2023-08-10 ## 0.2.1 - 2023-08-10
- Avoid calling `pend()` when waking expired timers - Avoid calling `pend()` when waking expired timers

View File

@ -291,21 +291,6 @@ impl<F: Future + 'static, const N: usize> TaskPool<F, N> {
} }
} }
/// Platform/architecture-specific action executed when an executor has pending work.
///
/// When a task within an executor is woken, the `Pender` is called. This does a
/// platform/architecture-specific action to signal there is pending work in the executor.
/// When this happens, you must arrange for [`Executor::poll`] to be called.
///
/// You can think of it as a waker, but for the whole executor.
///
/// Platform/architecture implementations must provide a function that can be referred to as:
///
/// ```rust
/// extern "Rust" {
/// fn __pender(context: *mut ());
/// }
/// ```
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub(crate) struct Pender(*mut ()); pub(crate) struct Pender(*mut ());
@ -451,15 +436,31 @@ impl SyncExecutor {
/// ///
/// - To get the executor to do work, call `poll()`. This will poll all queued tasks (all tasks /// - To get the executor to do work, call `poll()`. This will poll all queued tasks (all tasks
/// that "want to run"). /// that "want to run").
/// - You must supply a [`Pender`]. The executor will call it to notify you it has work /// - You must supply a pender function, as shown below. The executor will call it to notify you
/// to do. You must arrange for `poll()` to be called as soon as possible. /// it has work to do. You must arrange for `poll()` to be called as soon as possible.
/// - Enabling `arch-xx` features will define a pender function for you. This means that you
/// are limited to using the executors provided to you by the architecture/platform
/// implementation. If you need a different executor, you must not enable `arch-xx` features.
/// ///
/// The [`Pender`] can be called from *any* context: any thread, any interrupt priority /// The pender can be called from *any* context: any thread, any interrupt priority
/// level, etc. It may be called synchronously from any `Executor` method call as well. /// level, etc. It may be called synchronously from any `Executor` method call as well.
/// You must deal with this correctly. /// You must deal with this correctly.
/// ///
/// In particular, you must NOT call `poll` directly from the pender callback, as this violates /// In particular, you must NOT call `poll` directly from the pender callback, as this violates
/// the requirement for `poll` to not be called reentrantly. /// the requirement for `poll` to not be called reentrantly.
///
/// The pender function must be exported with the name `__pender` and have the following signature:
///
/// ```rust
/// #[export_name = "__pender"]
/// fn pender(context: *mut ()) {
/// // schedule `poll()` to be called
/// }
/// ```
///
/// The `context` argument is a piece of arbitrary data the executor will pass to the pender.
/// You can set the `context` when calling [`Executor::new()`]. You can use it to, for example,
/// differentiate between executors, or to pass a pointer to a callback that should be called.
#[repr(transparent)] #[repr(transparent)]
pub struct Executor { pub struct Executor {
pub(crate) inner: SyncExecutor, pub(crate) inner: SyncExecutor,
@ -474,9 +475,9 @@ impl Executor {
/// Create a new executor. /// Create a new executor.
/// ///
/// When the executor has work to do, it will call the [`Pender`]. /// When the executor has work to do, it will call the pender function and pass `context` to it.
/// ///
/// See [`Executor`] docs for details on `Pender`. /// See [`Executor`] docs for details on the pender.
pub fn new(context: *mut ()) -> Self { pub fn new(context: *mut ()) -> Self {
Self { Self {
inner: SyncExecutor::new(Pender(context)), inner: SyncExecutor::new(Pender(context)),
@ -502,16 +503,16 @@ impl Executor {
/// This loops over all tasks that are queued to be polled (i.e. they're /// This loops over all tasks that are queued to be polled (i.e. they're
/// freshly spawned or they've been woken). Other tasks are not polled. /// freshly spawned or they've been woken). Other tasks are not polled.
/// ///
/// You must call `poll` after receiving a call to the [`Pender`]. It is OK /// You must call `poll` after receiving a call to the pender. It is OK
/// to call `poll` even when not requested by the `Pender`, but it wastes /// to call `poll` even when not requested by the pender, but it wastes
/// energy. /// energy.
/// ///
/// # Safety /// # Safety
/// ///
/// You must NOT call `poll` reentrantly on the same executor. /// You must NOT call `poll` reentrantly on the same executor.
/// ///
/// In particular, note that `poll` may call the `Pender` synchronously. Therefore, you /// In particular, note that `poll` may call the pender synchronously. Therefore, you
/// must NOT directly call `poll()` from the `Pender` callback. Instead, the callback has to /// must NOT directly call `poll()` from the pender callback. Instead, the callback has to
/// somehow schedule for `poll()` to be called later, at a time you know for sure there's /// somehow schedule for `poll()` to be called later, at a time you know for sure there's
/// no `poll()` already running. /// no `poll()` already running.
pub unsafe fn poll(&'static self) { pub unsafe fn poll(&'static self) {