1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
#![stable(feature = "futures_api", since = "1.36.0")]
use crate::fmt;
use crate::marker::{PhantomData, Unpin};
/// `RawWaker` 允许任务执行器的实现者创建 [`Waker`],该 [`Waker`] 提供自定义的唤醒行为。
///
/// [vtable]: https://en.wikipedia.org/wiki/Virtual_method_table
///
/// 它由一个数据指针和一个自定义 `RawWaker` 行为的 [虚函数指针表 (vtable)][vtable] 组成。
///
///
#[derive(PartialEq, Debug)]
#[stable(feature = "futures_api", since = "1.36.0")]
pub struct RawWaker {
/// 数据指针,可用于根据执行程序的要求存储任意数据。
/// 这可能是,例如
/// 指向与任务关联的 `Arc` 的类型擦除的指针。
/// 该字段的值作为第一个参数传递给 vtable 一部分的所有函数。
///
data: *const (),
/// 虚拟函数指针表,可自定义此唤醒程序的行为。
vtable: &'static RawWakerVTable,
}
impl RawWaker {
/// 根据提供的 `data` 指针和 `vtable` 创建新的 `RawWaker`。
///
/// `data` 指针可用于存储执行程序所需的任意数据。这可能是,例如
/// 指向与任务关联的 `Arc` 的类型擦除的指针。
/// 该指针的值将作为第一个参数传递给 `vtable` 一部分的所有函数。
///
/// `vtable` 自定义从 `RawWaker` 创建的 `Waker` 的行为。
/// 对于 `Waker` 上的每个操作,将调用底层 `RawWaker` 的 `vtable` 中的关联函数。
///
///
///
#[inline]
#[rustc_promotable]
#[stable(feature = "futures_api", since = "1.36.0")]
#[rustc_const_stable(feature = "futures_api", since = "1.36.0")]
#[must_use]
pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> RawWaker {
RawWaker { data, vtable }
}
/// 获取用于创建此 `RawWaker` 的 `data` 指针。
#[inline]
#[must_use]
#[unstable(feature = "waker_getters", issue = "87021")]
pub fn data(&self) -> *const () {
self.data
}
/// 获取用于创建此 `RawWaker` 的 `vtable` 指针。
#[inline]
#[must_use]
#[unstable(feature = "waker_getters", issue = "87021")]
pub fn vtable(&self) -> &'static RawWakerVTable {
self.vtable
}
}
/// 虚拟函数指针表 (vtable),用于指定 [`RawWaker`] 的行为。
///
/// 传递给 vtable 内所有函数的指针是来自封闭的 [`RawWaker`] 对象的 `data` 指针。
///
/// 仅应在 [`RawWaker`] 实现内部从正确构造的 [`RawWaker`] 对象的 `data` 指针上调用此结构体内部的函数。
/// 使用任何其他 `data` 指针调用所包含的函数之一将导致未定义的行为。
///
/// 这些函数都必须是线程安全的 (即使 [`RawWaker`] 是 <code>\![Send] + \![Sync]</code>),因为 [`Waker`] 是 <code>[Send] + [Sync]</code>,因此唤醒器可以移动到任意线程或由 `&` 引用调用。
///
/// 例如,这意味着如果 `clone` 和 `drop` 函数管理一个引用计数,它们必须以原子方式进行。
///
///
///
///
///
///
#[stable(feature = "futures_api", since = "1.36.0")]
#[derive(PartialEq, Copy, Clone, Debug)]
pub struct RawWakerVTable {
/// 克隆 [`RawWaker`] 时,例如克隆存储 [`RawWaker`] 的 [`Waker`] 时,将调用此函数。
///
/// 此函数的实现必须保留 [`RawWaker`] 的此附加实例和关联任务所需的所有资源。
/// 在生成的 [`RawWaker`] 上调用 `wake` 应该会唤醒原 [`RawWaker`] 会唤醒的相同任务。
///
///
///
clone: unsafe fn(*const ()) -> RawWaker,
/// 在 [`Waker`] 上调用 `wake` 时将调用此函数。
/// 它必须唤醒与此 [`RawWaker`] 相关的任务。
///
/// 此函数的实现必须确保释放与该 [`RawWaker`] 实例和关联任务相关联的所有资源。
///
///
wake: unsafe fn(*const ()),
/// 在 [`Waker`] 上调用 `wake_by_ref` 时将调用此函数。
/// 它必须唤醒与此 [`RawWaker`] 相关的任务。
///
/// 该函数与 `wake` 相似,但不能消耗提供的数据指针。
///
wake_by_ref: unsafe fn(*const ()),
/// 当 [`Waker`] 得到抛弃时,这个函数被调用。
///
/// 此函数的实现必须确保释放与该 [`RawWaker`] 实例和关联任务相关联的所有资源。
///
///
drop: unsafe fn(*const ()),
}
impl RawWakerVTable {
/// 从提供的 `clone`,`wake`,`wake_by_ref` 和 `drop` 函数创建新的 `RawWakerVTable`。
///
/// 这些函数都必须是线程安全的 (即使 [`RawWaker`] 是 <code>\![Send] + \![Sync]</code>),因为 [`Waker`] 是 <code>[Send] + [Sync]</code>,因此唤醒器可以移动到任意线程或由 `&` 引用调用。
///
/// 例如,这意味着如果 `clone` 和 `drop` 函数管理一个引用计数,它们必须以原子方式进行。
///
/// # `clone`
///
/// 克隆 [`RawWaker`] 时,例如克隆存储 [`RawWaker`] 的 [`Waker`] 时,将调用此函数。
///
/// 此函数的实现必须保留 [`RawWaker`] 的此附加实例和关联任务所需的所有资源。
/// 在生成的 [`RawWaker`] 上调用 `wake` 应该会唤醒原 [`RawWaker`] 会唤醒的相同任务。
///
/// # `wake`
///
/// 在 [`Waker`] 上调用 `wake` 时将调用此函数。
/// 它必须唤醒与此 [`RawWaker`] 相关的任务。
///
/// 此函数的实现必须确保释放与该 [`RawWaker`] 实例和关联任务相关联的所有资源。
///
/// # `wake_by_ref`
///
/// 在 [`Waker`] 上调用 `wake_by_ref` 时将调用此函数。
/// 它必须唤醒与此 [`RawWaker`] 相关的任务。
///
/// 该函数与 `wake` 相似,但不能消耗提供的数据指针。
///
/// # `drop`
///
/// 当 [`Waker`] 得到抛弃时,这个函数被调用。
///
/// 此函数的实现必须确保释放与该 [`RawWaker`] 实例和关联任务相关联的所有资源。
///
///
///
///
///
///
///
///
///
///
///
#[rustc_promotable]
#[stable(feature = "futures_api", since = "1.36.0")]
#[rustc_const_stable(feature = "futures_api", since = "1.36.0")]
pub const fn new(
clone: unsafe fn(*const ()) -> RawWaker,
wake: unsafe fn(*const ()),
wake_by_ref: unsafe fn(*const ()),
drop: unsafe fn(*const ()),
) -> Self {
Self { clone, wake, wake_by_ref, drop }
}
}
/// 异步任务的上下文。
///
/// 目前,`Context` 仅用于提供对可用于唤醒当前任务的 [`&Waker`](Waker) 的访问。
///
#[stable(feature = "futures_api", since = "1.36.0")]
#[lang = "Context"]
pub struct Context<'a> {
waker: &'a Waker,
// 通过强制生命周期不变,确保我们能够抵御未来的变化 (参数位置生命周期是逆变的,而返回位置生命周期是协变的)。
//
//
//
_marker: PhantomData<fn(&'a ()) -> &'a ()>,
// 确保 `Context` 是 `!Send` 和 `!Sync`,以便允许 future `!Send` 或者 `!Sync` 字段。
//
_marker2: PhantomData<*mut ()>,
}
impl<'a> Context<'a> {
/// 从 [`&Waker`](Waker) 创建一个新的 `Context`。
#[stable(feature = "futures_api", since = "1.36.0")]
#[rustc_const_unstable(feature = "const_waker", issue = "102012")]
#[must_use]
#[inline]
pub const fn from_waker(waker: &'a Waker) -> Self {
Context { waker, _marker: PhantomData, _marker2: PhantomData }
}
/// 返回对当前任务的 [`Waker`] 的引用。
#[stable(feature = "futures_api", since = "1.36.0")]
#[rustc_const_unstable(feature = "const_waker", issue = "102012")]
#[must_use]
#[inline]
pub const fn waker(&self) -> &'a Waker {
&self.waker
}
}
#[stable(feature = "futures_api", since = "1.36.0")]
impl fmt::Debug for Context<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Context").field("waker", &self.waker).finish()
}
}
/// `Waker` 是通过通知执行者准备运行来唤醒任务的句柄。
///
/// 该句柄封装了 [`RawWaker`] 实例,该实例定义了特定于执行者的唤醒行为。
///
/// `Waker` 的典型生命周期是它由执行程序构造,包裹在 [`Context`] 中,然后传递给 [`Future::poll()`]。
/// 然后,如果 future 选择返回 [`Poll::Pending`],它还必须以某种方式存储唤醒器,并在应该再次轮询 future 时调用 [`Waker::wake()`]。
///
///
/// 实现 [`Clone`]、[`Send`] 和 [`Sync`]; 因此,可以从任何线程调用唤醒器,包括不以任何方式由执行程序管理的线程。
/// 例如,当阻塞函数调用在另一个线程上完成时,可以这样做以唤醒 future。
///
/// [`Future::poll()`]: core::future::Future::poll
/// [`Poll::Pending`]: core::task::Poll::Pending
///
///
///
///
///
#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/66401
#[stable(feature = "futures_api", since = "1.36.0")]
pub struct Waker {
waker: RawWaker,
}
#[stable(feature = "futures_api", since = "1.36.0")]
impl Unpin for Waker {}
#[stable(feature = "futures_api", since = "1.36.0")]
unsafe impl Send for Waker {}
#[stable(feature = "futures_api", since = "1.36.0")]
unsafe impl Sync for Waker {}
impl Waker {
/// 唤醒与此 `Waker` 相关的任务。
///
/// 只要 executor 一直在运行,任务还没有完成,就保证每次调用 [`wake()`](Self::wake) (或者 [`wake_by_ref()`](Self::wake_by_ref))) 之后都会至少跟这个 `Waker` 所属的任务的一个 [`poll()`]。
/// 这使得在运行潜在的无限处理循环时可以暂时让步给其他任务。
///
/// 请注意,以上暗示多个唤醒可能会被运行时合并为单个 [`poll()`] 调用。
///
/// 另请注意,不能保证屈服于竞争任务: 执行者选择运行哪个任务,执行者可以选择再次运行当前任务。
///
/// [`poll()`]: crate::future::Future::poll
///
///
///
///
///
///
///
#[inline]
#[stable(feature = "futures_api", since = "1.36.0")]
pub fn wake(self) {
// 实际的唤醒调用通过虚拟函数调用委托给执行程序定义的实现。
//
let wake = self.waker.vtable.wake;
let data = self.waker.data;
// 不要调用 `drop` - `wake` 将消耗唤醒器。
crate::mem::forget(self);
// SAFETY: 这是安全的,因为 `Waker::from_raw` 是初始化 `wake` 和 `data` 的唯一方法,要求用户确认 `RawWaker` 的契约已得到遵守。
//
//
unsafe { (wake)(data) };
}
/// 唤醒与此 `Waker` 相关的任务,而不消耗 `Waker`。
///
/// 这类似于 [`wake()`](Self::wake),但在拥有 `Waker` 可用的情况下效率可能会稍低。
/// 此方法应该比调用 `waker.clone().wake()` 更可取。
///
#[inline]
#[stable(feature = "futures_api", since = "1.36.0")]
pub fn wake_by_ref(&self) {
// 实际的唤醒调用通过虚拟函数调用委托给执行程序定义的实现。
//
// SAFETY: 请参见 `wake`
unsafe { (self.waker.vtable.wake_by_ref)(self.waker.data) }
}
/// 如果此 `Waker` 和另一个 `Waker` 将唤醒相同的任务,则返回 `true`。
///
/// 该函数在尽力而为的基础上起作用,即使 `Waker`s 唤醒相同的任务,也可能返回 false。
/// 但是,如果此函数返回 `true`,则可以确保 Waker 唤醒相同的任务。
///
/// 该函数主要用于优化目的。
///
#[inline]
#[must_use]
#[stable(feature = "futures_api", since = "1.36.0")]
pub fn will_wake(&self, other: &Waker) -> bool {
self.waker == other.waker
}
/// 从 [`RawWaker`] 创建一个新的 `Waker`。
///
/// 如果未遵守 [`RawWaker`] 和 [`RawWakerVTable`] 文档中定义的契约,则返回的 `Waker` 的行为是不确定的。
///
/// 因此,此方法是不安全的。
#[inline]
#[must_use]
#[stable(feature = "futures_api", since = "1.36.0")]
#[rustc_const_unstable(feature = "const_waker", issue = "102012")]
pub const unsafe fn from_raw(waker: RawWaker) -> Waker {
Waker { waker }
}
/// 获取对底层 [`RawWaker`] 的引用。
#[inline]
#[must_use]
#[unstable(feature = "waker_getters", issue = "87021")]
pub fn as_raw(&self) -> &RawWaker {
&self.waker
}
}
#[stable(feature = "futures_api", since = "1.36.0")]
impl Clone for Waker {
#[inline]
fn clone(&self) -> Self {
Waker {
// SAFETY: 这是安全的,因为 `Waker::from_raw` 是初始化 `clone` 和 `data` 的唯一方法,要求用户确认 [`RawWaker`] 的契约已得到遵守。
//
//
waker: unsafe { (self.waker.vtable.clone)(self.waker.data) },
}
}
}
#[stable(feature = "futures_api", since = "1.36.0")]
impl Drop for Waker {
#[inline]
fn drop(&mut self) {
// SAFETY: 这是安全的,因为 `Waker::from_raw` 是初始化 `drop` 和 `data` 的唯一方法,要求用户确认 `RawWaker` 的契约已得到遵守。
//
//
unsafe { (self.waker.vtable.drop)(self.waker.data) }
}
}
#[stable(feature = "futures_api", since = "1.36.0")]
impl fmt::Debug for Waker {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let vtable_ptr = self.waker.vtable as *const RawWakerVTable;
f.debug_struct("Waker")
.field("data", &self.waker.data)
.field("vtable", &vtable_ptr)
.finish()
}
}