dope_core/io/fd/
outbound.rs1use core::marker::PhantomData;
2use std::mem;
3
4use o3::{
5 depot::arena::slab::Vacancy,
6 mem::{Lease, Return},
7};
8
9use crate::{
10 driver,
11 driver::{
12 route,
13 route::{indices, kind, table},
14 },
15 io::fd::{domain, handles},
16};
17
18fn descriptors(driver: driver::Reference<'_>) -> &domain::Domain {
19 driver.ready().arena().descriptors()
20}
21
22#[derive(Clone, Copy)]
23#[repr(transparent)]
24pub(crate) struct Context<'d>(driver::Reference<'d>);
25
26impl<'d> Context<'d> {
27 pub(crate) const fn new(driver: driver::Reference<'d>) -> Self {
28 Self(driver)
29 }
30
31 pub(crate) fn try_reserve<B: route::Tag>(
32 &self,
33 count: table::Capacity,
34 ) -> Result<Reserved<'d, B>, Error> {
35 domain::Outbound::try_map::<B>(self.0, count)
36 }
37
38 pub(crate) fn acquire(
39 self,
40 key: route::OutboundKey,
41 local: indices::SlotIndex,
42 ) -> Result<handles::SocketSlot<'d>, Vacancy> {
43 let id = domain::Outbound::from(descriptors(self.0)).acquire(key, local)?;
44 Ok(handles::SocketSlot::from_claim(id, self.0))
45 }
46
47 pub(crate) fn creation(
48 self,
49 target: route::Erased<'d, kind::Socket>,
50 ) -> Option<domain::Creation> {
51 let key = route::OutboundKey::from_raw(u32::from(target.route().app()?.raw()))?;
52 domain::Outbound::from(descriptors(self.0)).creation(key, target.slot())
53 }
54
55 pub(crate) fn begin_create(self, slot: handles::OutboundSlot) {
56 domain::Outbound::from(descriptors(self.0)).begin_create(slot);
57 }
58
59 pub(crate) fn complete(self, creation: domain::Creation) -> domain::Create {
60 domain::Outbound::from(descriptors(self.0)).created(creation)
61 }
62
63 pub(crate) fn fail_create(self, creation: domain::Creation) {
64 domain::Outbound::from(descriptors(self.0)).failed(creation);
65 }
66
67 pub(crate) fn activate(self, slot: handles::OutboundSlot) {
68 domain::Outbound::from(descriptors(self.0)).activate(slot);
69 }
70
71 pub(crate) fn retire(self, key: route::OutboundKey) {
72 domain::Outbound::from(descriptors(self.0)).retire(key);
73 }
74}
75
76const _: () = {
77 assert!(std::mem::size_of::<Context<'_>>() == std::mem::size_of::<driver::Reference<'_>>());
78 assert!(std::mem::align_of::<Context<'_>>() == std::mem::align_of::<driver::Reference<'_>>());
79 assert!(std::mem::size_of::<domain::Create>() == std::mem::size_of::<u8>());
80 assert!(std::mem::align_of::<domain::Create>() == std::mem::align_of::<u8>());
81};
82
83#[derive(Clone, Copy, Debug, PartialEq, Eq)]
85pub enum Error {
86 Empty,
87 Occupied,
88 Capacity { requested: usize, available: usize },
89 Retiring { requested: usize, available: usize },
90}
91
92pub struct Reserved<'d, B: route::Tag> {
94 inner: Lease<Release<'d, B>>,
95}
96
97struct Release<'d, B: route::Tag> {
98 brand: PhantomData<B>,
99 driver: driver::Reference<'d>,
100}
101
102impl<B: route::Tag> Return for Release<'_, B> {
103 type Item = ();
104
105 fn return_item(self, (): Self::Item) {
106 self.driver
107 .outbound()
108 .retire(route::OutboundKey::for_tag::<B>());
109 }
110}
111
112impl<'d, B: route::Tag> Reserved<'d, B> {
113 pub fn try_new(
115 driver: &driver::Context<'_, 'd>,
116 count: table::Capacity,
117 ) -> Result<Self, Error> {
118 driver.driver_ref().outbound().try_reserve::<B>(count)
119 }
120
121 pub(crate) fn new(driver: driver::Reference<'d>) -> Self {
122 Self {
123 inner: Lease::new(
124 Release {
125 driver,
126 brand: PhantomData,
127 },
128 (),
129 ),
130 }
131 }
132
133 pub fn bind(
139 &self,
140 target: route::Target<'d, B>,
141 ) -> Result<route::Bound<'d, B, handles::SocketSlot<'d>>, Vacancy> {
142 let release = self.inner.sink();
143 let key = route::OutboundKey::for_tag::<B>();
144 let slot = release.driver.outbound().acquire(key, target.slot())?;
145 Ok(target.bind(slot))
146 }
147}
148
149const _: () = {
150 assert!(
151 mem::size_of::<Reserved<'_, route::KeyTag<0>>>() == mem::size_of::<driver::Reference<'_>>()
152 );
153 assert!(
154 mem::align_of::<Reserved<'_, route::KeyTag<0>>>()
155 == mem::align_of::<driver::Reference<'_>>()
156 );
157};