1use std::{mem, ops, pin, ptr};
2
3use dope_core::{
4 driver::{self, schedule, settings},
5 io,
6};
7use o3::base::cell::region;
8
9use super::forward;
10use crate::{executor, topology::lending};
11
12#[pin_project::pin_project]
14#[repr(transparent)]
15pub struct Bound<'app, 'd, H, T> {
16 #[pin]
17 pub(super) inner: lending::raw::Pair<'app, 'd, H, T>,
18}
19
20impl<'app, 'd, H, T> Bound<'app, 'd, H, T> {
21 pub(crate) const fn new(head: pin::Pin<&'app mut H>, tail: T) -> Self {
22 const {
23 assert!(mem::size_of::<Self>() == mem::size_of::<(pin::Pin<&'app mut H>, T)>());
24 assert!(mem::align_of::<Self>() == mem::align_of::<(pin::Pin<&'app mut H>, T)>());
25 assert!(!mem::needs_drop::<Self>());
26 }
27 Self {
28 inner: lending::raw::Pair::new(head, tail),
29 }
30 }
31
32 pub fn tail(self: pin::Pin<&Self>) -> pin::Pin<&T> {
33 self.project_ref().inner.tail()
34 }
35}
36
37unsafe impl<'app, 'd, H, T> lending::raw::Project for Bound<'app, 'd, H, T> {
39 type App = lending::raw::Pair<'app, 'd, H, T>;
40
41 fn shared(self: pin::Pin<&Self>) -> pin::Pin<&Self::App> {
42 self.project_ref().inner
43 }
44
45 fn exclusive(self: pin::Pin<&mut Self>) -> pin::Pin<&mut Self::App> {
46 self.project().inner
47 }
48}
49
50impl<'app, 'd, H, T> executor::raw::Layout<'d> for Bound<'app, 'd, H, T>
51where
52 H: executor::raw::Layout<'d>,
53 T: executor::raw::Layout<'d>,
54{
55 type ParkPlan = <lending::raw::Pair<'app, 'd, H, T> as executor::raw::Layout<'d>>::ParkPlan;
56}
57
58unsafe impl<'app, 'd, H, T> executor::raw::App<'d> for Bound<'app, 'd, H, T>
62where
63 H: executor::raw::App<'d>,
64 T: executor::raw::App<'d>,
65{
66 const ROUTES: settings::Routes =
67 <lending::raw::Pair<'app, 'd, H, T> as executor::raw::App<'d>>::ROUTES;
68 const WAKE_ROUTES: settings::Routes =
69 <lending::raw::Pair<'app, 'd, H, T> as executor::raw::App<'d>>::WAKE_ROUTES;
70 const COORDS: usize = <lending::raw::Pair<'app, 'd, H, T> as executor::raw::App<'d>>::COORDS;
71
72 fn select_park() -> Option<Self::ParkPlan> {
73 <lending::raw::Pair<'app, 'd, H, T> as executor::raw::App<'d>>::select_park()
74 }
75
76 fn prepare_park(
77 app: pin::Pin<&Self>,
78 plan: &mut Self::ParkPlan,
79 ) -> Option<executor::raw::Count> {
80 <lending::raw::Pair<'app, 'd, H, T> as executor::raw::App<'d>>::prepare_park(
81 lending::raw::Project::shared(app),
82 plan,
83 )
84 }
85
86 unsafe fn park<'call, 'driver, 'turn>(
87 app: pin::Pin<&'call mut Self>,
88 plan: &mut Self::ParkPlan,
89 park: executor::raw::Park<'driver, 'turn, 'd>,
90 ) where
91 'd: 'driver + 'turn,
92 {
93 unsafe { forward::park(app, plan, park) }
95 }
96
97 unsafe fn activate<'call, 'driver, 'turn>(
98 app: pin::Pin<&'call mut Self>,
99 activate: executor::raw::Activate<'driver, 'turn, 'd>,
100 ) -> bool
101 where
102 'd: 'driver + 'turn,
103 {
104 unsafe { forward::activate(app, activate) }
106 }
107
108 fn admit(
109 app: pin::Pin<&Self>,
110 needs: &mut settings::claim::Needs,
111 ) -> Result<(), settings::errors::Claim> {
112 <lending::raw::Pair<'_, 'd, H, T> as executor::raw::App<'d>>::admit(
113 lending::raw::Project::shared(app),
114 needs,
115 )
116 }
117
118 fn released(released: executor::raw::Released<'_, Self>) -> executor::raw::Released<'_, Self> {
119 unsafe { released.visit(|app| app.project().inner.project().tail) }
122 }
123
124 fn install<'call, 'owner>(
125 call: executor::raw::Install<'call, 'owner, 'd, Self>,
126 ) -> executor::raw::Install<'call, 'owner, 'd, Self> {
127 forward::install(call)
128 }
129
130 fn dispatch<'call, 'driver, 'turn>(
131 call: executor::raw::Dispatch<'call, 'driver, 'turn, 'd, Self>,
132 ) -> ops::ControlFlow<io::Event<'d>> {
133 forward::dispatch(call)
134 }
135
136 fn progress(
137 app: pin::Pin<&Self>,
138 view: executor::raw::Progress<'_, '_, 'd>,
139 ) -> schedule::Progress<'d> {
140 <lending::raw::Pair<'_, 'd, H, T> as executor::raw::App<'d>>::progress(
141 lending::raw::Project::shared(app),
142 view,
143 )
144 }
145
146 fn stopping(
147 app: pin::Pin<&Self>,
148 view: executor::raw::Progress<'_, '_, 'd>,
149 ) -> schedule::Progress<'d> {
150 <lending::raw::Pair<'_, 'd, H, T> as executor::raw::App<'d>>::stopping(
151 lending::raw::Project::shared(app),
152 view,
153 )
154 }
155
156 fn shutdown<'call, 'turn, 'driver>(
157 call: executor::raw::Shutdown<'call, 'turn, 'driver, 'd, Self>,
158 ) -> executor::raw::Shutdown<'call, 'turn, 'driver, 'd, Self> {
159 let (mut app, turn, driver) = call.into_parts();
160 let tail = app.as_mut().project().inner.project().tail;
161 let call = executor::raw::Shutdown::new(tail, turn, driver);
162 let (turn, driver) = forward::shutdown(call).into_drive();
163 let head = app.as_mut().project().inner.project().head;
164 let call = executor::raw::Shutdown::new(head, turn, driver);
165 let (turn, driver) = forward::shutdown(call).into_drive();
166 executor::raw::Shutdown::new(app, turn, driver)
167 }
168
169 fn finish<'call, 'finish, 'owner, 'epoch>(
170 call: executor::raw::Finish<'call, 'finish, 'owner, 'epoch, 'd, Self>,
171 ) -> executor::raw::Finish<'call, 'finish, 'owner, 'epoch, 'd, Self> {
172 let (mut app, install, finish) = call.into_parts();
173 let tail = app.as_mut().project().inner.project().tail;
174 let call = executor::raw::Finish::new(tail, install, finish);
175 let (install, finish) =
176 <lending::raw::Owner<mem::ManuallyDrop<T>, T> as executor::raw::Finishes<'d>>::call(
177 call,
178 )
179 .into_finish();
180 let mut head = app.as_mut().project().inner.project().head;
181 let _ = <lending::raw::Borrowed<'_, H> as executor::raw::App<'d>>::released(
182 executor::raw::Released::new(head.as_mut()),
183 );
184 let call = executor::raw::Finish::new(head, install, finish);
185 let (install, finish) =
186 <lending::raw::Borrowed<'_, H> as executor::raw::Finishes<'d>>::call(call)
187 .into_finish();
188 executor::raw::Finish::new(app, install, finish)
189 }
190}
191
192impl<'parent, 'd, H, T> Bound<'parent, 'd, H, T>
193where
194 H: executor::raw::App<'d>,
195 T: executor::raw::App<'d>,
196{
197 pub(crate) unsafe fn finish_tail<'call, 'finish, 'owner, 'epoch>(
200 call: executor::raw::Finish<'call, 'finish, 'owner, 'epoch, 'd, Self>,
201 plan: Option<<Self as executor::raw::Layout<'d>>::ParkPlan>,
202 ) -> (
203 lending::raw::Borrowed<'parent, H>,
204 Option<<H as executor::raw::Layout<'d>>::ParkPlan>,
205 ) {
206 let (mut app, install, finish) = call.into_parts();
207 let tail = app.as_mut().project().inner.project().tail;
208 let call = executor::raw::Finish::new(tail, install, finish);
209 let _ = <lending::raw::Owner<mem::ManuallyDrop<T>, T> as executor::raw::Finishes<'d>>::call(
210 call,
211 );
212 let head = app.as_mut().project().inner.project().head;
213 let head = unsafe { ptr::read(head.get_unchecked_mut()) };
216 (head, plan.and_then(|plan| plan.3))
217 }
218}
219
220unsafe impl<'d, H, T> executor::raw::Drain<'d> for Bound<'_, 'd, H, T>
223where
224 H: executor::raw::App<'d>,
225 T: executor::raw::Drain<'d>,
226{
227 fn begin(
228 self: pin::Pin<&mut Self>,
229 turn: schedule::Turn<'_, 'd>,
230 driver: &mut driver::Context<'_, 'd>,
231 ) {
232 executor::raw::Drain::begin(self.project().inner, turn, driver);
233 }
234
235 fn progress(
236 self: pin::Pin<&Self>,
237 region: ®ion::Token<region::Identity<'d>>,
238 ) -> schedule::Progress<'d> {
239 executor::raw::Drain::progress(self.project_ref().inner, region)
240 }
241
242 fn force(
243 self: pin::Pin<&mut Self>,
244 turn: schedule::Turn<'_, 'd>,
245 driver: &mut driver::Context<'_, 'd>,
246 ) {
247 executor::raw::Drain::force(self.project().inner, turn, driver);
248 }
249}
250
251const _: () = {
252 assert!(mem::size_of::<Bound<'_, '_, (), ()>>() == mem::size_of::<&mut ()>());
253 assert!(mem::align_of::<Bound<'_, '_, (), ()>>() == mem::align_of::<&mut ()>());
254 assert!(!mem::needs_drop::<Bound<'_, '_, (), ()>>());
255};