iceoryx2 0.9.0

iceoryx2: Lock-Free Zero-Copy Interprocess Communication
Documentation
// Copyright (c) 2023 Contributors to the Eclipse Foundation
//
// See the NOTICE file(s) distributed with this work for additional
// information regarding copyright ownership.
//
// This program and the accompanying materials are made available under the
// terms of the Apache Software License 2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license
// which is available at https://opensource.org/licenses/MIT.
//
// SPDX-License-Identifier: Apache-2.0 OR MIT

//! # Examples
//!
//! ```
//! use iceoryx2::prelude::*;
//!
//! # fn main() -> Result<(), Box<dyn core::error::Error>> {
//! let node = NodeBuilder::new().create::<ipc::Service>()?;
//! let event = node.service_builder(&"MyEventName".try_into()?)
//!     .event()
//!     .open_or_create()?;
//!
//! println!("name:                         {:?}", event.name());
//! println!("service id:                   {:?}", event.service_hash());
//! println!("deadline:                     {:?}", event.static_config().deadline());
//! println!("max listeners:                {:?}", event.static_config().max_listeners());
//! println!("max notifiers:                {:?}", event.static_config().max_notifiers());
//! println!("number of active listeners:   {:?}", event.dynamic_config().number_of_listeners());
//! println!("number of active notifiers:   {:?}", event.dynamic_config().number_of_notifiers());
//!
//! let listener = event.listener_builder().create()?;
//! let notifier = event.notifier_builder().create()?;
//! # Ok(())
//! # }
//! ```
extern crate alloc;
use alloc::sync::Arc;

use core::ptr::NonNull;

use super::listener::PortFactoryListener;
use super::nodes;
use super::notifier::PortFactoryNotifier;
use crate::identifiers::UniqueServiceId;
use crate::node::NodeListFailure;
use crate::service::attribute::AttributeSet;
use crate::service::port_factory::blocking_cleanup_dead_nodes_in_service;
use crate::service::service_hash::ServiceHash;
use crate::service::{self, NoResource, ServiceState, SharedServiceState, static_config};
use crate::service::{ServiceName, dynamic_config};
use iceoryx2_bb_elementary::CallbackProgression;
use iceoryx2_bb_elementary_traits::non_null::NonNullCompat;
use iceoryx2_bb_elementary_traits::testing::abandonable::Abandonable;
use iceoryx2_cal::dynamic_storage::DynamicStorage;

/// The factory for
/// [`MessagingPattern::Event`](crate::service::messaging_pattern::MessagingPattern::Event). It can
/// acquire dynamic and static service informations and create [`crate::port::notifier::Notifier`]
/// or [`crate::port::listener::Listener`] ports.
#[derive(Debug)]
pub struct PortFactory<Service: service::Service> {
    pub(crate) service: SharedServiceState<Service, NoResource>,
}

unsafe impl<Service: service::Service> Send for PortFactory<Service> {}
unsafe impl<Service: service::Service> Sync for PortFactory<Service> {}

impl<Service: service::Service> Abandonable for PortFactory<Service> {
    unsafe fn abandon_in_place(mut this: NonNull<Self>) {
        let this = unsafe { this.as_mut() };
        unsafe { SharedServiceState::abandon_in_place(NonNull::iox2_from_mut(&mut this.service)) };
    }
}

impl<Service: service::Service> crate::service::port_factory::PortFactory for PortFactory<Service> {
    type Service = Service;
    type StaticConfig = static_config::event::StaticConfig;
    type DynamicConfig = dynamic_config::event::DynamicConfig;

    fn name(&self) -> &ServiceName {
        self.service.static_config().name()
    }

    fn unique_service_id(&self) -> UniqueServiceId {
        self.service.static_config().unique_service_id()
    }

    fn service_hash(&self) -> &ServiceHash {
        self.service.static_config().service_hash()
    }

    fn attributes(&self) -> &AttributeSet {
        self.service.static_config().attributes()
    }

    fn static_config(&self) -> &static_config::event::StaticConfig {
        self.service.static_config().event()
    }

    fn dynamic_config(&self) -> &dynamic_config::event::DynamicConfig {
        self.service.dynamic_storage().get().event()
    }

    fn nodes<F: FnMut(crate::node::NodeState<Service>) -> CallbackProgression>(
        &self,
        callback: F,
    ) -> Result<(), NodeListFailure> {
        nodes(
            self.service.dynamic_storage().get(),
            self.service.shared_node().config(),
            callback,
        )
    }
}

impl<Service: service::Service> PortFactory<Service> {
    pub(crate) fn new(service: ServiceState<Service, NoResource>) -> Self {
        let shared_node = service.shared_node.clone();
        let new_self = Self {
            service: SharedServiceState {
                state: Arc::new(service),
            },
        };

        if shared_node
            .config()
            .global
            .service
            .cleanup_dead_nodes_on_open
        {
            blocking_cleanup_dead_nodes_in_service(
                &new_self,
                shared_node.config().global.creation_timeout,
            );
        }

        new_self
    }

    /// Returns a [`PortFactoryNotifier`] to create a new [`crate::port::notifier::Notifier`] port
    ///
    /// # Example
    ///
    /// ```
    /// use iceoryx2::prelude::*;
    ///
    /// # fn main() -> Result<(), Box<dyn core::error::Error>> {
    /// let node = NodeBuilder::new().create::<ipc::Service>()?;
    /// let event = node.service_builder(&"MyEventName".try_into()?)
    ///     .event()
    ///     .open_or_create()?;
    ///
    /// let notifier = event.notifier_builder().create()?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn notifier_builder(&self) -> PortFactoryNotifier<'_, Service> {
        PortFactoryNotifier::new(self)
    }

    /// Returns a [`PortFactoryListener`] to create a new [`crate::port::listener::Listener`] port
    ///
    /// # Example
    ///
    /// ```
    /// use iceoryx2::prelude::*;
    ///
    /// # fn main() -> Result<(), Box<dyn core::error::Error>> {
    /// let node = NodeBuilder::new().create::<ipc::Service>()?;
    /// let event = node.service_builder(&"MyEventName".try_into()?)
    ///     .event()
    ///     .open_or_create()?;
    ///
    /// let listener = event.listener_builder().create()?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn listener_builder(&self) -> PortFactoryListener<'_, Service> {
        PortFactoryListener { factory: self }
    }
}