use super::AttachError;
use crate::control::cluster::error::{CpError, ResourceScope};
#[repr(transparent)]
pub struct SessionKit<'cfg, T, U, C, const MAX_RV: usize = 4>
where
T: crate::transport::Transport + 'cfg,
U: crate::runtime::consts::LabelUniverse + 'cfg,
C: crate::runtime::config::Clock + 'cfg,
{
pub(super) inner: crate::control::cluster::core::SessionCluster<'cfg, T, U, C, MAX_RV>,
_cfg: core::marker::PhantomData<crate::endpoint::carrier::SessionCfg<Self>>,
_local_only: crate::local::LocalOnly,
}
pub struct SessionKitStorage<
'cfg,
T,
U = crate::runtime::consts::DefaultLabelUniverse,
C = crate::runtime::config::CounterClock,
const MAX_RV: usize = 4,
> where
T: crate::transport::Transport + 'cfg,
U: crate::runtime::consts::LabelUniverse + 'cfg,
C: crate::runtime::config::Clock + 'cfg,
{
storage: core::mem::MaybeUninit<SessionKit<'cfg, T, U, C, MAX_RV>>,
initialized: bool,
}
pub struct RendezvousKit<'kit, 'cfg, T, U, C, const HAS_SESSION: bool, const MAX_RV: usize>
where
T: crate::transport::Transport + 'cfg,
U: crate::runtime::consts::LabelUniverse + 'cfg,
C: crate::runtime::config::Clock + 'cfg,
{
pub(super) kit: &'kit SessionKit<'cfg, T, U, C, MAX_RV>,
pub(super) rv: crate::control::types::RendezvousId,
pub(super) sid: crate::integration::ids::SessionId,
}
pub struct RoleKit<
'kit,
'cfg,
'prog,
const ROLE: u8,
T,
U,
C,
const HAS_SESSION: bool,
const MAX_RV: usize,
> where
T: crate::transport::Transport + 'cfg,
U: crate::runtime::consts::LabelUniverse + 'cfg,
C: crate::runtime::config::Clock + 'cfg,
{
pub(super) kit: &'kit SessionKit<'cfg, T, U, C, MAX_RV>,
pub(super) rv: crate::control::types::RendezvousId,
pub(super) sid: crate::integration::ids::SessionId,
pub(super) program: &'prog crate::integration::program::RoleProgram<ROLE>,
pub(super) binding: Option<&'kit mut dyn crate::integration::binding::EndpointSlot>,
}
impl<'cfg, T, U, C, const MAX_RV: usize> SessionKitStorage<'cfg, T, U, C, MAX_RV>
where
T: crate::transport::Transport + 'cfg,
U: crate::runtime::consts::LabelUniverse + 'cfg,
C: crate::runtime::config::Clock + 'cfg,
{
pub const fn uninit() -> Self {
Self {
storage: core::mem::MaybeUninit::uninit(),
initialized: false,
}
}
pub fn init(&mut self) -> &SessionKit<'cfg, T, U, C, MAX_RV> {
assert!(
!self.initialized,
"SessionKitStorage must not be initialized twice"
);
unsafe {
SessionKit::init_empty(self.storage.as_mut_ptr());
}
self.initialized = true;
unsafe {
&*self.storage.as_ptr()
}
}
}
impl<'cfg, T, U, C, const MAX_RV: usize> Drop for SessionKitStorage<'cfg, T, U, C, MAX_RV>
where
T: crate::transport::Transport + 'cfg,
U: crate::runtime::consts::LabelUniverse + 'cfg,
C: crate::runtime::config::Clock + 'cfg,
{
fn drop(&mut self) {
if self.initialized {
unsafe {
core::ptr::drop_in_place(self.storage.as_mut_ptr());
}
}
}
}
impl<'cfg, T, U, C, const MAX_RV: usize> SessionKit<'cfg, T, U, C, MAX_RV>
where
T: crate::transport::Transport + 'cfg,
U: crate::runtime::consts::LabelUniverse + 'cfg,
C: crate::runtime::config::Clock + 'cfg,
{
unsafe fn init_empty(dst: *mut Self) {
unsafe {
crate::control::cluster::core::SessionCluster::init_empty(core::ptr::addr_of_mut!(
(*dst).inner
));
core::ptr::addr_of_mut!((*dst)._cfg).write(core::marker::PhantomData);
core::ptr::addr_of_mut!((*dst)._local_only).write(crate::local::LocalOnly::new());
}
}
#[inline]
#[track_caller]
pub fn rendezvous(
&self,
config: crate::integration::runtime::Config<'cfg, U, C>,
transport: T,
) -> Result<RendezvousKit<'_, 'cfg, T, U, C, false, MAX_RV>, AttachError> {
let location = crate::control::cluster::error::ErrorLocation::caller();
let rv = self
.inner
.register_rendezvous(config, transport)
.map_err(|error| {
AttachError::control(error).with_operation(
crate::control::cluster::error::AttachOp::Rendezvous,
location,
)
})?;
Ok(RendezvousKit {
kit: self,
rv,
sid: crate::integration::ids::SessionId::new(0),
})
}
#[inline(never)]
#[track_caller]
pub(super) fn enter_attached<'r, const ROLE: u8>(
&'r self,
rv: crate::control::types::RendezvousId,
sid: crate::integration::ids::SessionId,
program: &crate::integration::program::RoleProgram<ROLE>,
binding: Option<&'r mut dyn crate::binding::EndpointSlot>,
) -> Result<crate::Endpoint<'r, ROLE>, AttachError>
where
'cfg: 'r,
{
let location = crate::control::cluster::error::ErrorLocation::caller();
let binding = match binding {
Some(binding) => crate::binding::BindingHandle::Borrowed(binding),
None => crate::binding::BindingHandle::None(crate::binding::NoBinding),
};
Self::enter_endpoint(self, rv, sid, program, binding).map_err(|error| {
error.with_operation(crate::control::cluster::error::AttachOp::Enter, location)
})
}
#[inline(never)]
fn enter_endpoint<'r, const ROLE: u8>(
&'r self,
rv: crate::control::types::RendezvousId,
sid: crate::integration::ids::SessionId,
program: &crate::integration::program::RoleProgram<ROLE>,
binding: crate::binding::BindingHandle<'r>,
) -> Result<crate::Endpoint<'r, ROLE>, AttachError>
where
'cfg: 'r,
{
let (slot, generation) = self.inner.enter::<ROLE>(rv, sid, program, binding)?;
let ptr = self
.inner
.public_endpoint_header_ptr(rv, slot, generation)
.ok_or(AttachError::control(CpError::resource_exhausted(
ResourceScope::EndpointHeader,
)))?;
let handle = crate::endpoint::carrier::PackedEndpointHandle::new(rv, slot, generation);
Ok(crate::endpoint::Endpoint::from_handle(ptr, handle))
}
#[inline]
#[track_caller]
pub(super) fn set_role_resolver<const POLICY: u16, const ROLE: u8>(
&self,
rv: crate::control::types::RendezvousId,
program: &crate::integration::program::RoleProgram<ROLE>,
resolver: crate::integration::policy::ResolverRef<'cfg>,
) -> Result<(), crate::integration::policy::ResolverError> {
let location = crate::control::cluster::core::ResolverErrorLocation::caller();
self.inner
.set_resolver::<POLICY, ROLE>(rv, program, resolver)
.map_err(|error| {
crate::integration::policy::ResolverError::control(error).with_operation_at(
crate::control::cluster::core::ResolverOp::SetResolver,
location,
)
})
}
}