Skip to content

Commit 411b0c0

Browse files
committed
doc(bind): improve documentation
1 parent e6f38e2 commit 411b0c0

File tree

3 files changed

+79
-15
lines changed

3 files changed

+79
-15
lines changed

src/r3/src/bind/mod.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,16 @@
33
44
> This module re-exports stable items from [`r3_core::bind`][] as well as
55
> providing some additional items.
6-
"#)]
6+
"#, concat!(r#"
7+
<div class="toc-header"></div>
8+
9+
"#, r3_core::bind::__internal_module_doc_toc!(), r#"
10+
- [Examples](#examples)
11+
- [Structs](#structs) <!-- this section is generated by rustdoc -->
12+
- [Constants](#constants) <!-- this section is generated by rustdoc -->
13+
- [Traits](#traits) <!-- this section is generated by rustdoc -->
14+
- [Functions](#functions) <!-- this section is generated by rustdoc -->
15+
"#))]
716
//!
817
//! # Examples
918
//!
@@ -195,11 +204,12 @@ where
195204
}
196205

197206
/// A shorthand for
198-
/// [`Bind`][]`::`[`define`][1]`().`[`init`][2]`(`[`default`][3]`)`.
207+
/// [`Bind`][]`::`[`define`][1]`().`[`init`][2]`(`[`default`][3]`).`[`finish`][4]`(cfg)`.
199208
///
200209
/// [1]: Bind::define
201210
/// [2]: BindDefiner::init_with_bind
202211
/// [3]: core::default::default
212+
/// [4]: BindDefiner::finish
203213
///
204214
/// # Example
205215
///

src/r3_core/src/bind.rs

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
1-
#![doc = __internal_module_doc!("crate", "")]
1+
#![doc = __internal_module_doc!("crate", "", "")]
22
#![doc = include_str!("./common.md")]
3+
4+
/// The table of contents for [`__internal_module_doc`][].
5+
#[rustfmt::skip]
6+
#[doc(hidden)]
7+
pub macro __internal_module_doc_toc() {r#"
8+
- [Binders](#binders)
9+
- [Initialization Order](#initialization-order)
10+
- [Planned Features](#planned-features) "#} // No EOL at the end
11+
312
/// The part of the module-level documentation shared between `r3::bind` and
413
/// `r3_core::bind`. This is necessary because `r3::bind` itself isn't a
514
/// re-export of `r3_core::bind`, but it's desirable for it to have the same
615
/// documentation.
716
#[rustfmt::skip]
817
#[doc(hidden)]
918
#[macropol::macropol] // Replace `$metavariables` in literals and doc comments
10-
pub macro __internal_module_doc($r3_core:expr, $admonitions:expr) {r#"
19+
pub macro __internal_module_doc($r3_core:expr, $admonitions:expr, $toc:expr) {
20+
r#"
1121
Bindings ([`Bind`][]), a static storage with [runtime initialization][1] and
1222
[configuration-time][2] borrow checking.
1323
@@ -17,14 +27,17 @@ Bindings are essentially fancy global variables defined in a kernel
1727
configuration. They are defined by [`Bind::define`][] and initialized by
1828
provided closures at runtime. They can be consumed or borrowed by the entry
1929
points of [executable kernel objects][4] or the initializers of another
20-
bindings.
30+
bindings, with a dependency graph explicitly defined by the passing of
31+
[*binders*][15].
2132
2233
The configuration system tracks the usage of bindings and employs static checks
23-
to ensure that the borrowing rules are observed by the users of the bindings. It
34+
to ensure that the borrowing rules are followed by the users of the bindings. It
2435
aborts the compilation if the rules may be violated.
2536
26-
Bindings use hunks ([`Hunk`][3]) as a storage for their contents. They are
27-
initialized in [startup hooks][14].
37+
Bindings use hunks ([`Hunk`][3]) as a storage for their contents. Bindings are
38+
initialized in [startup hooks][14], where [CPU Lock][17] is active, <!--
39+
[ref:startup_hook_cpu_lock_active] --> and therefore most kernel services
40+
are unavailable.
2841
2942
<div class="admonition-follows"></div>
3043
@@ -36,13 +49,40 @@ initialized in [startup hooks][14].
3649
> In RTIC, all resources are defined in one place and initialized by an
3750
> application-provided `#[init]` function.
3851
52+
$toc
53+
3954
# Binders
4055
41-
*Binders* ([`Binder`][]) represent specific borrow modes of bindings. A
42-
configuration function creates them by calling [`Bind`][]'s methods and use them
43-
in the definition of another object where the binding is intended to be
44-
consumed, i.e., borrowed or moved out by its associated function. The type a
45-
binder produces is called its *materialized* form.
56+
A *binder* ([`Binder`][]) represents a specific borrow mode of a binding. A
57+
configuration function creates a binding by calling one of [`Bind`][]'s methods
58+
and uses it in the definition of another object where the binding is intended to
59+
be consumed, i.e., borrowed or moved out by its entry point or initializer. The
60+
type a binder produces is called its *materialized* form.
61+
62+
```rust,ignore
63+
use r3::{bind::bind, kernel::StaticTimer, prelude::*};
64+
65+
let count = bind((), || 0).finish(cfg);
66+
// ^^ ^^
67+
// .--' '--------,
68+
// no binders no materialized values
69+
70+
StaticTimer::define()
71+
// n.b. `(x,)` is a one-element tuple
72+
.start_with_bind((count.borrow_mut(),), |count: &mut i32| {
73+
// ^^^^^^^^^^^^^^^^^^ ^^^^^^^^
74+
// | |
75+
// BindBorrowMut<'_, _, i32> &'call mut i32
76+
// gives... for some lifetime 'call
77+
})
78+
.finish(b);
79+
```
80+
81+
The only way for safe code to make a binding available to runtime code in a
82+
meaningful way is to include a binder in a dependency list (e.g., the `binder`
83+
parameter of [`ExecutableDefinerExt::start_with_bind`][]) as shown above or to
84+
call [`Bind::as_ref`][] to create a [`BindRef`][], which is directly consumable
85+
in runtime code. Most binders can't escape from a configuration function.
4686
4787
The following table lists all provided binders:
4888
@@ -68,6 +108,11 @@ The following table lists all provided binders:
68108
69109
- The **Confers** column shows the respective materialized forms of the binders.
70110
The lifetime `'call` represents the call duration of the consuming function.
111+
- For `&'call T` and `&'call mut T`, the caller has the freedom of choosing
112+
an arbitrary lifetime, so the consuming function must be generic over any
113+
lifetimes. In function and closure parameters, reference types without
114+
explicit lifetimes are automatically made generic in this way owing to [the
115+
lifetime elision rules][16].
71116
72117
- The **On binding** column shows which types of binders can be consumed by
73118
another binding's initializer via [`BindDefiner::init_with_bind`][].
@@ -115,7 +160,11 @@ The following features are planned and may be implemented in the future:
115160
[12]: crate::kernel::StaticInterruptHandler
116161
[13]: crate::kernel::StaticTimer
117162
[14]: crate::kernel::StartupHook
118-
"#}
163+
[15]: #binders
164+
[16]: https://doc.rust-lang.org/1.58.1/reference/lifetime-elision.html#lifetime-elision-in-functions
165+
[17]: $r3_core#system-states
166+
"#
167+
}
119168

120169
use core::{cell::UnsafeCell, marker::PhantomData, mem::MaybeUninit};
121170

@@ -973,6 +1022,11 @@ enum BindBorrowType {
9731022
/// spawn a thread that executes after the execution of all startup hooks is
9741023
/// complete.
9751024
///
1025+
/// See [`ExecutableDefinerExt`][] for an extension trait providing a method
1026+
/// to specify a closure that consumes [binders][1].
1027+
///
1028+
/// [1]: index.html#binders
1029+
///
9761030
/// # Safety
9771031
///
9781032
/// At any point of time, the provided [`Closure`] must never be invoked by two

src/r3_core/src/lib.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ An **(execution) thread** is a sequence of instructions executed by a processor.
262262

263263
The properties of threads such as how and when they are created and whether they can block or not are specific to each thread type.
264264

265-
The initial thread that starts up the kernel is called the **main thread**. This is where the initialization of kernel structures takes place. Additionally, an application can register one or more [**startup hooks**] to execute user code here. Startup hooks execute with CPU Lock active and *should never deactivate CPU Lock*. The main thread exits when the kernel dispatches the first task.
265+
The initial thread that starts up the kernel is called the **main thread**. This is where the initialization of kernel structures takes place. Additionally, an application can register one or more [**startup hooks**] to execute user code here. <!-- [tag:startup_hook_cpu_lock_active] --> Startup hooks execute with CPU Lock active and *should never deactivate CPU Lock*. The main thread exits when the kernel dispatches the first task.
266266

267267
<!-- TODO: It's useful to introduce a term "the boot phase". -->
268268

0 commit comments

Comments
 (0)