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
//! FFI handle that pairs a future with a stashed effect snapshot.
//!
//! [`EffectHandle`] extends [`HostHandle`] with a
//! per-handle effect cache and an application context pointer. When
//! `poll_once()` returns [`Pending`](core::task::Poll::Pending), the
//! bridge code snapshots the pending effect into the handle so the host
//! can inspect it via [`last_effect`](EffectHandle::last_effect) or
//! [`take_effect`](EffectHandle::take_effect) without racing.
//!
//! ```text
//! ┌──────────┐ poll_once() ┌──────────────────────┐
//! │ Host │ ──────────────> │ EffectHandle │
//! │ │ │ ┌────────────────┐ │
//! │ │ <────────────── │ │ HostHandle<F> │ │
//! │ │ Pending │ └────────────────┘ │
//! │ │ │ last_effect: E? │
//! │ reads │ last_effect() │ context: *const Ctx │
//! │ effect │ ──────────────> │ │
//! │ │ <────────────── │ │
//! └──────────┘ └──────────────────────┘
//! ```
use ;
use crateHostHandle;
/// FFI handle wrapping a [`HostHandle`] with a stashed effect and context.
///
/// This is the generalized version of an effect-carrying future handle.
/// It bundles:
///
/// - A [`HostHandle<F>`] for the underlying future
/// - A last-observed effect snapshot (`Option<E>`)
/// - A context pointer (`*const Ctx`) for application-specific state
///
/// The context pointer is a raw `*const Ctx` because FFI handles typically
/// outlive any particular borrow scope. Bridge authors are responsible for
/// ensuring the context outlives the handle.
///
/// # Slot ownership
///
/// For concurrent futures, each `EffectHandle` should be paired with
/// its own `Arc<EffectSlot>`. The bridge creates the `Arc`, clones it
/// into both the async closure and the handle. This gives each future
/// an independent effect channel with no capacity limit. See the
/// [crate-level docs](crate#slot-ownership) for examples.
///
/// # Type parameters
///
/// - `F`: the future type (e.g., `BoxFuture<'static, T>` or
/// `LocalBoxFuture<'static, T>`)
/// - `E`: the effect type (e.g., an enum of things the host can provide)
/// - `Ctx`: the application context type (e.g., the counter struct)
// SAFETY: The only non-auto-Send/Sync field is `*const Ctx`. FFI handles
// are single-owner — only the host's polling thread touches a given handle.
// The raw context pointer is only dereferenced while the handle is alive
// and the context has not been freed.
unsafe