From b5c146284f92d4aae8bff4c0eaa43ea4543f6d88 Mon Sep 17 00:00:00 2001 From: Mathias Kraus Date: Tue, 21 Jun 2022 23:04:35 +0200 Subject: [PATCH] iox-#23 Refine publisher API --- examples/publisher_simple.rs | 15 ++---- src/error.rs | 4 +- src/pb/mod.rs | 4 +- src/pb/publisher.rs | 101 ++++++++++++++++++++++++++++++----- src/pb/topic.rs | 70 ------------------------ src/tests/basic_pub_sub.rs | 9 ++-- 6 files changed, 100 insertions(+), 103 deletions(-) delete mode 100644 src/pb/topic.rs diff --git a/examples/publisher_simple.rs b/examples/publisher_simple.rs index 9b9876d..ccfe90b 100644 --- a/examples/publisher_simple.rs +++ b/examples/publisher_simple.rs @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: © Contributors to the iceoryx-rs project // SPDX-FileContributor: Mathias Kraus -use iceoryx_rs::pb::{TopicBuilder, POD}; +use iceoryx_rs::pb::{PublisherBuilder, POD}; use iceoryx_rs::Runtime; use std::error::Error; @@ -10,23 +10,16 @@ use std::thread; use std::time::Duration; #[repr(C)] -struct CounterTopic { +struct Counter { counter: u32, } -unsafe impl POD for CounterTopic {} +unsafe impl POD for Counter {} fn main() -> Result<(), Box> { Runtime::init("publisher_simple"); - let topic = TopicBuilder::::new("Radar", "FrontLeft", "Counter").build()?; - - let publisher = topic.offer(); - - // wait until RouDi runs the discovery loop - while !publisher.is_offered() { - thread::sleep(Duration::from_millis(10)); - } + let publisher = PublisherBuilder::::new("Radar", "FrontLeft", "Counter").create()?; let mut counter = 0u32; loop { diff --git a/src/error.rs b/src/error.rs index 05310aa..0371154 100644 --- a/src/error.rs +++ b/src/error.rs @@ -8,8 +8,8 @@ use thiserror::Error; pub enum IceOryxError { #[error("could not alloce a chunk")] ChunkAllocationFailed, - #[error("could not create a publisher topic")] - PublisherTopicCreationFailed, + #[error("could not create a publisher")] + PublisherCreationFailed, #[error("number of allowed chunks to hold is exhausted")] TooManyChunksHoldInParallel, } diff --git a/src/pb/mod.rs b/src/pb/mod.rs index 129c0cb..8dcff78 100644 --- a/src/pb/mod.rs +++ b/src/pb/mod.rs @@ -6,10 +6,8 @@ mod ffi; mod publisher; mod publisher_options; mod sample; -mod topic; -pub use publisher::Publisher; +pub use publisher::{PublisherBuilder, InactivePublisher, Publisher}; pub use sample::POD; -pub use topic::{Topic, TopicBuilder}; use publisher_options::PublisherOptions; diff --git a/src/pb/publisher.rs b/src/pb/publisher.rs index 0291680..aee7b7a 100644 --- a/src/pb/publisher.rs +++ b/src/pb/publisher.rs @@ -2,45 +2,122 @@ // SPDX-FileCopyrightText: © Contributors to the iceoryx-rs project // SPDX-FileContributor: Mathias Kraus -use super::{sample::SampleMut, Topic, POD}; +use super::{ffi::Publisher as FfiPublisher, sample::SampleMut, PublisherOptions, POD}; use crate::IceOryxError; +use std::marker::PhantomData; + +pub struct PublisherBuilder<'a, T: POD> { + service: &'a str, + instance: &'a str, + event: &'a str, + options: PublisherOptions, + phantom: PhantomData, +} + +impl<'a, T: POD> PublisherBuilder<'a, T> { + pub fn new(service: &'a str, instance: &'a str, event: &'a str) -> Self { + Self { + service, + instance, + event, + options: PublisherOptions::default(), + phantom: PhantomData, + } + } + + pub fn history_capacity(mut self, history_capacity: u64) -> Self { + self.options.history_capacity = history_capacity; + self + } + + pub fn node_name(mut self, node_name: String) -> Self { + self.options.node_name = node_name; + self + } + + pub fn create(mut self) -> Result, IceOryxError> { + self.options.offer_on_create = true; + let ffi_pub = FfiPublisher::new(self.service, self.instance, self.event, &self.options) + .ok_or(IceOryxError::PublisherCreationFailed)?; + + Ok(Publisher { + ffi_pub, + phantom: PhantomData, + }) + } + + pub fn create_without_offer(mut self) -> Result, IceOryxError> { + self.options.offer_on_create = false; + let ffi_pub = FfiPublisher::new(self.service, self.instance, self.event, &self.options) + .ok_or(IceOryxError::PublisherCreationFailed)?; + + Ok(InactivePublisher { + ffi_pub, + phantom: PhantomData, + }) + } +} + +pub struct InactivePublisher { + ffi_pub: Box, + phantom: PhantomData, +} + +impl InactivePublisher { + fn new_from_publisher(publisher: Publisher) -> Self { + Self { + ffi_pub: publisher.ffi_pub, + phantom: PhantomData, + } + } + + pub fn offer(self) -> Publisher { + self.ffi_pub.offer(); + Publisher::new_from_inactive_publisher(self) + } +} + pub struct Publisher { - publisher: Topic, + ffi_pub: Box, + phantom: PhantomData, } impl Publisher { - pub(super) fn new(publisher: Topic) -> Self { - Publisher { publisher } + fn new_from_inactive_publisher(publisher: InactivePublisher) -> Self { + Self { + ffi_pub: publisher.ffi_pub, + phantom: PhantomData, + } } pub fn is_offered(&self) -> bool { - self.publisher.ffi_pub.is_offered() + self.ffi_pub.is_offered() } - pub fn stop(self) -> Topic { - self.publisher.ffi_pub.stop_offer(); - self.publisher + pub fn stop(self) -> InactivePublisher { + self.ffi_pub.stop_offer(); + InactivePublisher::new_from_publisher(self) } pub fn has_subscribers(&self) -> bool { - self.publisher.ffi_pub.has_subscribers() + self.ffi_pub.has_subscribers() } pub fn allocate_sample(&self) -> Result, IceOryxError> { Ok(SampleMut { - data: Some(self.publisher.ffi_pub.allocate_chunk()?), + data: Some(self.ffi_pub.allocate_chunk()?), service: self, }) } pub fn publish(&self, mut sample: SampleMut) { if let Some(chunk) = sample.data.take() { - sample.service.publisher.ffi_pub.send_chunk(chunk) + sample.service.ffi_pub.send_chunk(chunk) } } pub(super) fn release_chunk(&self, chunk: Box) { - self.publisher.ffi_pub.free_chunk(chunk); + self.ffi_pub.free_chunk(chunk); } } diff --git a/src/pb/topic.rs b/src/pb/topic.rs deleted file mode 100644 index cb9befe..0000000 --- a/src/pb/topic.rs +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: © Contributors to the iceoryx-rs project -// SPDX-FileContributor: Mathias Kraus - -use super::{ffi::Publisher as FfiPublisher, Publisher, PublisherOptions, POD}; -use crate::IceOryxError; - -use std::marker::PhantomData; - -pub struct TopicBuilder<'a, T: POD> { - service: &'a str, - instance: &'a str, - event: &'a str, - options: PublisherOptions, - phantom: PhantomData, -} - -impl<'a, T: POD> TopicBuilder<'a, T> { - pub fn new(service: &'a str, instance: &'a str, event: &'a str) -> Self { - Self { - service, - instance, - event, - options: PublisherOptions::default(), - phantom: PhantomData, - } - } - - pub fn history_capacity(mut self, history_capacity: u64) -> Self { - self.options.history_capacity = history_capacity; - self - } - - pub fn node_name(mut self, node_name: String) -> Self { - self.options.node_name = node_name; - self - } - - pub fn offer_on_create(mut self, offer_on_create: bool) -> Self { - self.options.offer_on_create = offer_on_create; - self - } - - pub fn build(self) -> Result, IceOryxError> { - let ffi_pub = FfiPublisher::new(self.service, self.instance, self.event, &self.options); - - Ok(Topic { - ffi_pub: ffi_pub.ok_or(IceOryxError::PublisherTopicCreationFailed)?, - phantom: PhantomData, - }) - } -} - -pub struct Topic { - pub(super) ffi_pub: Box, - phantom: PhantomData, -} - -impl Topic { - pub fn offer(self) -> Publisher { - self.ffi_pub.offer(); - Publisher::new(self) - } -} - -impl Drop for Topic { - fn drop(&mut self) { - self.ffi_pub.stop_offer(); - } -} diff --git a/src/tests/basic_pub_sub.rs b/src/tests/basic_pub_sub.rs index c72b97c..d90eec1 100644 --- a/src/tests/basic_pub_sub.rs +++ b/src/tests/basic_pub_sub.rs @@ -10,11 +10,11 @@ use crate::Runtime; use anyhow::{anyhow, Result}; #[repr(C)] -struct CounterTopic { +struct Counter { counter: u32, } -unsafe impl POD for CounterTopic {} +unsafe impl POD for Counter {} #[test] fn basic_pub_sub() -> Result<()> { @@ -22,15 +22,14 @@ fn basic_pub_sub() -> Result<()> { Runtime::init("basic_pub_sub"); - let topic = sb::TopicBuilder::::new("Test", "BasicPubSub", "Counter") + let topic = sb::TopicBuilder::::new("Test", "BasicPubSub", "Counter") .queue_capacity(5) .build(); let (subscriber, sample_receive_token) = topic.subscribe(); - let topic = pb::TopicBuilder::::new("Test", "BasicPubSub", "Counter").build()?; + let publisher = pb::PublisherBuilder::::new("Test", "BasicPubSub", "Counter").create()?; - let publisher = topic.offer(); let mut sample = publisher.allocate_sample()?; const SEND_COUNTER: u32 = 42;