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 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}