Skip to content

Commit 87647b7

Browse files
committed
gross workaround for rust-lang/rust#97708
this makes the nop fns #[doc(hidden)] pub`. the `Header` type is moved to a private module and made `pub`. @jamesmunns if you have a better solution, let's do that Signed-off-by: Eliza Weisman <[email protected]>
1 parent aa65400 commit 87647b7

File tree

1 file changed

+96
-58
lines changed

1 file changed

+96
-58
lines changed

maitake/src/task.rs

Lines changed: 96 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -106,55 +106,74 @@ pub struct Task<S, F: Future, STO> {
106106
storage: PhantomData<STO>,
107107
}
108108

109-
/// The task's header.
110-
///
111-
/// This contains the *untyped* components of the task which are identical
112-
/// regardless of the task's future, output, and scheduler types: the
113-
/// [vtable], [state cell], and [run queue links].
114-
///
115-
/// The header is the data at which a [`TaskRef`] points, and will likely be
116-
/// prefetched when dereferencing a [`TaskRef`] pointer.[^1] Therefore, the
117-
/// header should contain the task's most frequently accessed data, and should
118-
/// ideally fit within a CPU cache line.
119-
///
120-
/// # Safety
121-
///
122-
/// The [run queue links] *must* be the first field in this type, in order for
123-
/// the [`Linked::links` implementation] for this type to be sound. Therefore,
124-
/// the `#[repr(C)]` attribute on this struct is load-bearing.
125-
///
126-
/// [vtable]: Vtable
127-
/// [state cell]: StateCell
128-
/// [run queue links]: cordyceps::mpsc_queue::Links
129-
/// [`Linked::links` implementation]: #method.links
130-
///
131-
/// [^1]: On CPU architectures which support spatial prefetch, at least...
132-
#[repr(C)]
133-
#[derive(Debug)]
134-
pub struct Header {
135-
/// The task's links in the intrusive run queue.
109+
pub(crate) mod header {
110+
use super::*;
111+
/// The task's header.
112+
///
113+
/// This contains the *untyped* components of the task which are identical
114+
/// regardless of the task's future, output, and scheduler types: the
115+
/// [vtable], [state cell], and [run queue links].
116+
///
117+
/// The header is the data at which a [`TaskRef`] points, and will likely be
118+
/// prefetched when dereferencing a [`TaskRef`] pointer.[^1] Therefore, the
119+
/// header should contain the task's most frequently accessed data, and should
120+
/// ideally fit within a CPU cache line.
121+
///
122+
/// # /!\ EXTREMELY SERIOUS WARNING /!\
123+
///
124+
/// This is NOT a public API type and is *not* part of this crate's stable
125+
/// interface. It must be made `pub` as a workaround for a [compiler
126+
/// error][97708] where functions in the stub task vtable are improperly culled
127+
/// by the compiler if they are not `pub`, which requires that the `Header` type
128+
/// must be `pub` (as it's part of the type signature of one of those
129+
/// functions).
130+
///
131+
/// User code should NEVER interact with this type directly. Fortunately,
132+
/// there's no way for you to construct it... :)
136133
///
137134
/// # Safety
138135
///
139-
/// This MUST be the first field in this struct.
140-
run_queue: mpsc_queue::Links<Header>,
141-
142-
/// The task's state, which can be atomically updated.
143-
state: StateCell,
144-
145-
/// The task vtable for this task.
136+
/// The [run queue links] *must* be the first field in this type, in order for
137+
/// the [`Linked::links` implementation] for this type to be sound. Therefore,
138+
/// the `#[repr(C)]` attribute on this struct is load-bearing.
146139
///
147-
/// Note that this is different from the [waker vtable], which contains
148-
/// pointers to the waker methods (and depends primarily on the task's
149-
/// scheduler type). The task vtable instead contains methods for
150-
/// interacting with the task's future, such as polling it and reading the
151-
/// task's output. These depend primarily on the type of the future rather
152-
/// than the scheduler.
140+
/// [vtable]: Vtable
141+
/// [state cell]: StateCell
142+
/// [run queue links]: cordyceps::mpsc_queue::Links
143+
/// [`Linked::links` implementation]: #method.links
144+
/// [97708]: https://github.com/rust-lang/rust/issues/97708
153145
///
154-
/// [waker vtable]: core::task::RawWakerVTable
155-
vtable: &'static Vtable,
146+
/// [^1]: On CPU architectures which support spatial prefetch, at least...
147+
#[repr(C)]
148+
#[derive(Debug)]
149+
pub struct Header {
150+
/// The task's links in the intrusive run queue.
151+
///
152+
/// # Safety
153+
///
154+
/// This MUST be the first field in this struct.
155+
pub(super) run_queue: mpsc_queue::Links<Header>,
156+
157+
/// The task's state, which can be atomically updated.
158+
pub(super) state: StateCell,
159+
160+
/// The task vtable for this task.
161+
///
162+
/// Note that this is different from the [waker vtable], which contains
163+
/// pointers to the waker methods (and depends primarily on the task's
164+
/// scheduler type). The task vtable instead contains methods for
165+
/// interacting with the task's future, such as polling it and reading the
166+
/// task's output. These depend primarily on the type of the future rather
167+
/// than the scheduler.
168+
///
169+
/// [waker vtable]: core::task::RawWakerVTable
170+
pub(super) vtable: &'static Vtable,
171+
}
156172
}
157173

174+
#[doc(inline)]
175+
pub(crate) use self::header::Header;
176+
158177
enum Cell<F: Future> {
159178
Future(F),
160179
Finished(F::Output),
@@ -523,26 +542,45 @@ feature! {
523542
feature! {
524543
#![not(loom)]
525544

526-
mod nop {
527-
use super::*;
528-
pub unsafe fn nop(_ptr: TaskRef) -> Poll<()> {
529-
#[cfg(debug_assertions)]
530-
unreachable!("stub task ({_ptr:?}) should never be polled!");
531-
#[cfg(not(debug_assertions))]
532-
Poll::Pending
533-
}
534-
535-
536-
pub unsafe fn nop_deallocate(ptr: NonNull<Header>) {
537-
unreachable!("stub task ({ptr:p}) should never be deallocated!");
538-
}
539-
545+
/// # /!\ EXTREMELY SERIOUS WARNING /!\
546+
///
547+
/// This is NOT a public API and is *not* part of this crate's stable
548+
/// interface. It must be made `pub` as a workaround for a [compiler
549+
/// error][97708] where functions in the stub task vtable are improperly
550+
/// culled as dead code by the compiler if they are not `pub`.
551+
///
552+
/// User code should NEVER call this function directly. If you *do* call
553+
/// it...please note that it doesn't do anything interesting.
554+
///
555+
/// [97708]: https://github.com/rust-lang/rust/issues/97708
556+
#[doc(hidden)]
557+
pub unsafe fn nop(_ptr: TaskRef) -> Poll<()> {
558+
#[cfg(debug_assertions)]
559+
unreachable!("stub task ({_ptr:?}) should never be polled!");
560+
#[cfg(not(debug_assertions))]
561+
Poll::Pending
562+
}
563+
564+
/// # /!\ EXTREMELY SERIOUS WARNING /!\
565+
///
566+
/// This is NOT a public API and is *not* part of this crate's stable
567+
/// interface. It must be made `pub` as a workaround for a [compiler
568+
/// error][97708] where functions in the stub task vtable are improperly
569+
/// culled as dead code by the compiler if they are not `pub`.
570+
///
571+
/// User code should NEVER call this function directly. If you *do* call
572+
/// it...please note that it will always panic.
573+
///
574+
/// [97708]: https://github.com/rust-lang/rust/issues/97708
575+
#[doc(hidden)]
576+
pub unsafe fn nop_deallocate(ptr: NonNull<Header>) {
577+
unreachable!("stub task ({ptr:p}) should never be deallocated!");
540578
}
541579

542580
impl Vtable {
543581
const STUB: Vtable = Vtable {
544-
poll: nop::nop,
545-
deallocate: nop::nop_deallocate,
582+
poll: nop,
583+
deallocate: nop_deallocate,
546584
};
547585
}
548586

0 commit comments

Comments
 (0)