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
//! Runtime, task spawning, blocking work, and opt-in I/O cancellation.
//!
//! # I/O cancellation
//!
//! Wrap an ordinary I/O future with [`FutureExt::with_cancellation`]. A source
//! owns cancellation authority; its copyable tokens only observe cancellation
//! and register operations:
//!
//! ```ignore
//! use karmaio::io::AsyncRead;
//! use karmaio::runtime::{CancellationSource, FutureExt};
//!
//! let source = CancellationSource::new();
//! let token = source.token();
//! karmaio::runtime::spawn_local(async move {
//! source.cancel();
//! });
//! let (res, buf) = stream.read(buf).with_cancellation(token).await;
//! ```
//!
//! [`CancellationSource::cancel`] is sticky and non-blocking. The observing
//! future must still be awaited; a completion that races cancellation may win
//! and return `Ok`. Dropping an I/O future requests platform cancellation and
//! forfeits the buffer.
//!
//! To time out an operation and recover its buffer, keep the wrapped future and
//! await it after requesting cancellation:
//!
//! ```ignore
//! use std::pin::pin;
//! use karmaio::io::AsyncRead;
//! use karmaio::runtime::{CancellationSource, FutureExt};
//! use karmaio::time::sleep;
//!
//! let source = CancellationSource::new();
//! let mut op = pin!(stream.read(buf).with_cancellation(source.token()));
//! let result = karmaio::select! {
//! result = &mut op => result,
//! _ = sleep(duration) => {
//! source.cancel();
//! op.await
//! }
//! };
//! ```
//!
//! Nested `.with_cancellation` combinators all apply; cancelling either source
//! cancels the submitted operation.
//!
//! ## Scope and submission
//!
//! A cancellation combinator affects karmaio I/O operations submitted while
//! its inner future is being polled. Bind it before the operation's first poll:
//! once an operation has been submitted, wrapping later does not attach that
//! existing operation to the token. Likewise, wrap a multishot stream before
//! its first [`crate::io::Stream::next`] call.
//!
//! The combinator does not make arbitrary futures cancellation-aware. For
//! example, wrapping [`std::future::pending`] does not make it complete when
//! the source is cancelled. Use [`CancellationToken::cancelled`] when a
//! non-I/O future needs to observe cancellation cooperatively.
//!
//! Cancellation scopes also do not propagate into tasks created with
//! [`spawn_local`]. A spawned task is polled independently, so pass it a token
//! explicitly and wrap the karmaio I/O operations inside that task.
//!
//! ## Stream ordering
//!
//! Platform cancellation is best-effort. If a stream read is dropped without
//! awaiting its terminal completion, starting another read on the same stream
//! can race the abandoned read. Cancel and then await the original future when
//! operation ordering matters.
use crateTask;
pub use crateStreamExt;
pub use crate;
pub use ;
pub use map_cancel_result;
pub use ;
pub use ;
pub