Skip to main content

dope_uring/raw/
create.rs

1use dope_sys::{
2    engine::ring::Backend as _,
3    io::socket::option::tuning::Create as _,
4    probe::{Build as _, Context as _, Validate as _, receive::Validate as _},
5    ring::create::{Acquire as _, Retain as _},
6    table::permit::Create as _,
7};
8
9use crate::{
10    Admission, Built, Cause, Created, Engine, Host, Primary, Range, Ready, Recovery, Rejection,
11    Removal, Removed, Retained, Ring, Session, Update, Uring, Validate, config, engine, host,
12    memory, num, permit, probe, ready, receive, session,
13};
14
15impl<C, G> engine::raw::Create<C, G> for Uring
16where
17    C: config::Config<G>,
18    C::Layout: memory::raw::Canary,
19    Host<C>: probe::Build<Update>,
20    Cause<C>: From<Primary> + From<memory::Error> + From<Admission>,
21    Ring<C::Token>: probe::Validate<
22            C::Layout,
23            Cause<C>,
24            Probe = <Host<C> as host::Context>::Probe,
25            Cleanup = Recovery<C>,
26        > + Validate<
27            C::Layout,
28            Cause<C>,
29            Removal<C>,
30            Range = Range,
31            Probe = <Host<C> as host::Context>::Probe,
32            Update = Update,
33            Cleanup = Recovery<C>,
34            Release = Removed<C>,
35        >,
36    Session<C::Token, C::Layout>: session::Create<Cause<C>, Ring = Ring<C::Token>, Cleanup = Retained<C>>
37        + receive::Validate<
38            Cause<C>,
39            Removal<C>,
40            Update = Update,
41            Cleanup = Recovery<C>,
42            Release = Removed<C>,
43        >,
44{
45    type Receive = <Self as permit::Source>::Queue<C::Key, C::Index>;
46    type Error = Created<C>;
47
48    unsafe fn try_new(config: &G) -> Result<Built<C, G>, Self::Error> {
49        let config = C::config(config);
50        let receive = Self::Receive::try_new(config.files.get() as usize)
51            .map_err(Created::<C>::Allocation)?;
52        let count = num::NonZero::<u32>::MIN.saturating_add(config.files.get() - 1);
53        let tuning = C::Tuning::try_new(count).map_err(Created::<C>::Allocation)?;
54        let (ring, range) = Ring::<C::Token>::acquire::<_, Removed<C>>(
55            config.submit,
56            config.complete,
57            config.defer,
58            config.files,
59            config.range,
60        )?;
61        let recover =
62            |result: Recovery<C>| Created::<C>::from(result.map_err(Retained::<C>::probe));
63        let reject = |error: Rejection<Recovery<C>, Removed<C>>| match error {
64            Rejection::Cleanup(result) => recover(result),
65            Rejection::Release(result) => Created::<C>::Release(result),
66        };
67        let ring = ring.support().map_err(recover)?;
68        let session = <Session<C::Token, C::Layout> as session::Create<Cause<C>>>::try_new(ring)
69            .map_err(Created::<C>::from)?;
70        let session = session::Create::socket(session).map_err(Created::<C>::from)?;
71        let session = session.receive(Host::<C>::remove).map_err(reject)?;
72        let ring = session::Create::finish(session).map_err(Created::<C>::from)?;
73        let ring = match range {
74            Some(range) => Validate::accept(ring, range, Host::<C>::release).map_err(reject)?,
75            None => ring,
76        };
77        let ring = ring.empty(Host::<C>::RING).map_err(recover)?;
78        // SAFETY: the caller retains this exact returned Context beside the
79        // backend through quiescence and destruction. Failed registration
80        // retains its Context inside the complete native cleanup owner.
81        let (ring, context) = unsafe {
82            <Ready<C::Token, C::Layout> as ready::raw::Bind<Cause<C>>>::bind(ring, config.receive)
83        }
84        .map_err(Created::<C>::from)?;
85        Ok((Engine::new(ring, tuning), context, receive))
86    }
87}