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