cartel_sqlite/engine/conn/
raw.rs1use crate::{
2 api, catalogs,
3 conn::{
4 Installed,
5 phase::{Live, Phase},
6 },
7 runtime,
8};
9use api::stmt;
10use dope_core::driver::{schedule, settings};
11use dope_runtime::{executor, topology::lending};
12use std::{alloc::Layout, marker, pin, ptr};
13
14pub(crate) struct Vacant<'local, 'd: 'local, I: catalogs::Catalog> {
15 phase: ptr::NonNull<Phase<'local, 'd, I>>,
16 backing: marker::PhantomData<&'local mut Phase<'local, 'd, I>>,
17}
18
19impl<'local, 'd: 'local, I: catalogs::Catalog> Vacant<'local, 'd, I> {
20 pub(crate) const LAYOUT: Layout = Layout::new::<Phase<'local, 'd, I>>();
21
22 pub(crate) unsafe fn new(storage: &'local runtime::raw::Span) -> Self {
26 Self {
27 phase: storage.base().cast(),
28 backing: marker::PhantomData,
29 }
30 }
31
32 pub(crate) fn insert(self, state: api::State<'local, 'd, I>) -> Installed<'local, 'd, I> {
33 unsafe { self.phase.as_ptr().write(Phase::Live(Live::new(state))) };
35 Installed {
36 phase: self.phase,
37 ownership: marker::PhantomData,
38 }
39 }
40}
41
42impl<I: catalogs::Catalog> Drop for Installed<'_, '_, I> {
43 fn drop(&mut self) {
44 unsafe { self.phase.as_ptr().drop_in_place() };
47 }
48}
49
50unsafe impl<'local, 'd: 'local, I: catalogs::Catalog> lending::raw::Resume<'d>
55 for Installed<'local, 'd, I>
56{
57}
58
59impl<'local, 'd: 'local, I: catalogs::Catalog> executor::raw::Layout<'d>
60 for Installed<'local, 'd, I>
61{
62 type ParkPlan = ();
63}
64
65unsafe impl<'local, 'd: 'local, I: catalogs::Catalog> executor::raw::App<'d>
66 for Installed<'local, 'd, I>
67{
68 const ROUTES: settings::Routes = settings::Routes::EMPTY;
69 const COORDS: usize = 1;
70
71 fn select_park() -> Option<Self::ParkPlan> {
72 Some(())
73 }
74
75 fn released(
76 mut released: executor::raw::Released<'_, Self>,
77 ) -> executor::raw::Released<'_, Self> {
78 let app = released.owner();
79 let conn = app.as_ref().get_ref();
80 unsafe { &mut *conn.phase.as_ptr() }.released();
83 released
84 }
85
86 fn shutdown<'app, 'turn, 'driver, 'owner>(
87 shutdown: executor::raw::Shutdown<'app, 'turn, 'driver, 'owner, 'd, Self>,
88 ) -> executor::raw::Shutdown<'app, 'turn, 'driver, 'owner, 'd, Self>
89 where
90 'd: 'owner,
91 {
92 let (app, turn, driver) = shutdown.into_parts();
93 let conn = app.as_ref().get_ref();
94 unsafe { &*conn.phase.as_ptr() }.stop();
96 executor::raw::Shutdown::new(app, turn, driver)
97 }
98
99 fn finish<'app, 'finish, 'owner, 'epoch>(
100 finish: executor::raw::Finish<'app, 'finish, 'owner, 'epoch, 'd, Self>,
101 ) -> executor::raw::Finish<'app, 'finish, 'owner, 'epoch, 'd, Self> {
102 let (app, install, finish) = finish.into_parts();
103 if finish.is_forced() {
104 let conn = app.as_ref().get_ref();
105 unsafe { &mut *conn.phase.as_ptr() }.force();
107 }
108 executor::raw::Finish::new(app, install, finish)
109 }
110
111 fn progress(
112 app: pin::Pin<&Self>,
113 _: executor::raw::Progress<'_, '_, 'd>,
114 ) -> schedule::Progress<'d> {
115 unsafe { &*app.get_ref().phase.as_ptr() }.progress::<false>()
117 }
118
119 fn stopping(
120 app: pin::Pin<&Self>,
121 _: executor::raw::Progress<'_, '_, 'd>,
122 ) -> schedule::Progress<'d> {
123 unsafe { &*app.get_ref().phase.as_ptr() }.progress::<true>()
125 }
126
127 unsafe fn park<'app, 'driver, 'turn, 'root>(
130 app: pin::Pin<&'app mut Self>,
131 (): &mut Self::ParkPlan,
132 mut park: executor::raw::Park<'driver, 'turn, 'root, 'd>,
133 ) where
134 'd: 'driver + 'turn + 'root,
135 {
136 let conn = app.as_ref().get_ref();
137 let phase = unsafe { &*conn.phase.as_ptr() };
139 if let Phase::Live(live) = phase
140 && live.borrow.get().is_borrowed()
141 {
142 return;
143 }
144 let phase = unsafe { &mut *conn.phase.as_ptr() };
146 loop {
147 let (state, plan) = match phase {
148 Phase::Live(live) => {
149 let state = unsafe { &mut *live.state.get() };
151 let plan = state.maintenance(park.now());
152 (state, plan)
153 }
154 Phase::Closing(state) => {
155 let plan = state.maintenance(park.now());
156 if matches!(plan, api::Plan::Idle) {
157 phase.retire();
158 continue;
159 }
160 (state, plan)
161 }
162 Phase::Retiring(retiring) => {
163 if matches!(retiring.inventory(), stmt::Inventory::Empty) {
164 break;
165 }
166 if park.next_step().is_none() {
167 break;
168 }
169 retiring.retire_one();
170 continue;
171 }
172 Phase::Empty => break,
173 };
174 match plan {
175 api::Plan::Idle | api::Plan::Delayed => break,
176 api::Plan::Ready => {}
177 }
178 let Some(step) = park.next_step() else {
179 break;
180 };
181 if state.maintain(step.now()).is_pending() {
182 break;
183 }
184 }
185 }
186}