Skip to main content

dope_runtime/topology/lending/raw/
owner.rs

1use std::{marker, mem, ops, pin};
2
3use dope_core::{
4    driver::{retained, 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]
13#[repr(transparent)]
14pub struct Owner<S, T> {
15    #[pin]
16    stored: S,
17    app: marker::PhantomData<T>,
18}
19
20impl<S, T> Owner<S, T> {
21    pub(super) const fn new(stored: S) -> Self {
22        Self {
23            stored,
24            app: marker::PhantomData,
25        }
26    }
27}
28
29// SAFETY: the pinned stored projection remains unchanged for the entire lifecycle.
30unsafe impl<S: lending::raw::Project<App = T>, T> lending::raw::Project for Owner<S, T> {
31    type App = T;
32
33    fn shared(self: pin::Pin<&Self>) -> pin::Pin<&Self::App> {
34        self.project_ref().stored.shared()
35    }
36
37    fn exclusive(self: pin::Pin<&mut Self>) -> pin::Pin<&mut Self::App> {
38        self.project().stored.exclusive()
39    }
40}
41
42impl<'d, S, T> executor::raw::Layout<'d> for Owner<S, T>
43where
44    T: executor::raw::Layout<'d>,
45{
46    type ParkPlan = <T as executor::raw::Layout<'d>>::ParkPlan;
47}
48
49// SAFETY: lifecycle traversal retains one exact pinned application. Its storage
50// is released once after final traversal, before its enclosing owner is finished.
51unsafe impl<'d, S, T> executor::raw::App<'d> for Owner<S, T>
52where
53    S: lending::raw::Project<App = T>,
54    T: executor::raw::App<'d>,
55    Self: executor::raw::Finishes<'d, Self>,
56{
57    const ROUTES: settings::Routes = T::ROUTES;
58    const WAKE_ROUTES: settings::Routes = T::WAKE_ROUTES;
59    const COORDS: usize = <T as executor::raw::App<'d>>::COORDS;
60
61    fn select_park() -> Option<Self::ParkPlan> {
62        <T as executor::raw::App<'d>>::select_park()
63    }
64
65    fn prepare_park(
66        app: pin::Pin<&Self>,
67        plan: &mut Self::ParkPlan,
68    ) -> Option<executor::raw::Count> {
69        <T as executor::raw::App<'d>>::prepare_park(lending::raw::Project::shared(app), plan)
70    }
71
72    unsafe fn park<'app, 'driver, 'turn, 'root>(
73        app: pin::Pin<&'app mut Self>,
74        plan: &mut Self::ParkPlan,
75        park: executor::raw::Park<'driver, 'turn, 'root, 'd>,
76    ) where
77        'd: 'driver + 'turn + 'root,
78    {
79        // SAFETY: this owner preserves the same prepared plan and pinned projection.
80        unsafe { forward::park(app, plan, park) }
81    }
82
83    unsafe fn activate<'app, 'driver, 'turn, 'root>(
84        app: pin::Pin<&'app mut Self>,
85        activate: executor::raw::Activate<'driver, 'turn, 'root, 'd>,
86    ) -> bool
87    where
88        'd: 'driver + 'turn + 'root,
89    {
90        // SAFETY: this owner retains the installed application and its wake routes.
91        unsafe { forward::activate(app, activate) }
92    }
93
94    fn admit(
95        app: pin::Pin<&Self>,
96        needs: &mut settings::claim::Needs,
97    ) -> Result<(), settings::errors::Claim> {
98        T::admit(lending::raw::Project::shared(app), needs)
99    }
100
101    fn released(released: executor::raw::Released<'_, Self>) -> executor::raw::Released<'_, Self> {
102        // SAFETY: this wrapper retains the exact original pinned application.
103        unsafe { released.visit(lending::raw::Project::exclusive) }
104    }
105
106    fn install<'app, 'owner>(
107        call: executor::raw::Install<'app, 'owner, 'd, Self>,
108    ) -> executor::raw::Install<'app, 'owner, 'd, Self> {
109        forward::install(call)
110    }
111
112    fn dispatch<'app, 'driver, 'turn, 'root>(
113        call: executor::raw::Dispatch<'app, 'driver, 'turn, 'root, 'd, Self>,
114    ) -> ops::ControlFlow<io::Event<'d>>
115    where
116        'd: 'root,
117        Self: 'root,
118    {
119        forward::dispatch(call)
120    }
121
122    fn shutdown<'app, 'turn, 'driver, 'owner>(
123        call: executor::raw::Shutdown<'app, 'turn, 'driver, 'owner, 'd, Self>,
124    ) -> executor::raw::Shutdown<'app, 'turn, 'driver, 'owner, 'd, Self>
125    where
126        'd: 'owner,
127    {
128        forward::shutdown(call)
129    }
130
131    fn finish<'app, 'finish, 'owner, 'epoch>(
132        call: executor::raw::Finish<'app, 'finish, 'owner, 'epoch, 'd, Self>,
133    ) -> executor::raw::Finish<'app, 'finish, 'owner, 'epoch, 'd, Self> {
134        <Self as executor::raw::Finishes<'d>>::call(call)
135    }
136
137    fn progress(
138        app: pin::Pin<&Self>,
139        view: executor::raw::Progress<'_, '_, 'd>,
140    ) -> schedule::Progress<'d> {
141        T::progress(lending::raw::Project::shared(app), view)
142    }
143
144    fn stopping(
145        app: pin::Pin<&Self>,
146        view: executor::raw::Progress<'_, '_, 'd>,
147    ) -> schedule::Progress<'d> {
148        T::stopping(lending::raw::Project::shared(app), view)
149    }
150}
151
152impl<'d, T> executor::raw::Finishes<'d, Self> for lending::raw::Borrowed<'_, T>
153where
154    T: executor::raw::App<'d>,
155{
156    fn call<'app, 'finish, 'owner, 'epoch>(
157        call: executor::raw::Finish<'app, 'finish, 'owner, 'epoch, 'd, Self>,
158    ) -> executor::raw::Finish<'app, 'finish, 'owner, 'epoch, 'd, Self> {
159        forward::finish(call)
160    }
161}
162
163impl<'d, T> executor::raw::Finishes<'d, Self> for Owner<mem::ManuallyDrop<T>, T>
164where
165    T: executor::raw::App<'d>,
166{
167    fn call<'app, 'finish, 'owner, 'epoch>(
168        call: executor::raw::Finish<'app, 'finish, 'owner, 'epoch, 'd, Self>,
169    ) -> executor::raw::Finish<'app, 'finish, 'owner, 'epoch, 'd, Self> {
170        let (mut app, install, finish) = forward::finish(call).into_parts();
171        // SAFETY: final traversal completed and this private lifecycle wrapper
172        // is never projected again before its enclosing application is destroyed.
173        unsafe { mem::ManuallyDrop::drop(app.as_mut().project().stored.get_unchecked_mut()) };
174        executor::raw::Finish::new(app, install, finish)
175    }
176}
177
178// SAFETY: every drain call projects the same pinned application; its Drain
179// contract preserves the admitted owners and route claims.
180unsafe impl<'d, S, T> executor::raw::Drain<'d> for Owner<S, T>
181where
182    S: lending::raw::Project<App = T>,
183    T: executor::raw::Drain<'d>,
184    Self: executor::raw::Finishes<'d, Self>,
185{
186    fn begin(
187        self: pin::Pin<&mut Self>,
188        turn: schedule::Turn<'_, 'd>,
189        driver: &mut retained::Context<'_, '_, 'd>,
190    ) {
191        executor::raw::Drain::begin(lending::raw::Project::exclusive(self), turn, driver);
192    }
193
194    fn progress(
195        self: pin::Pin<&Self>,
196        region: &region::Token<region::Identity<'d>>,
197    ) -> schedule::Progress<'d> {
198        executor::raw::Drain::progress(lending::raw::Project::shared(self), region)
199    }
200
201    fn force(
202        self: pin::Pin<&mut Self>,
203        turn: schedule::Turn<'_, 'd>,
204        driver: &mut retained::Context<'_, '_, 'd>,
205    ) {
206        executor::raw::Drain::force(lending::raw::Project::exclusive(self), turn, driver);
207    }
208}