diff --git a/com-api-example/src/main.rs b/com-api-example/src/main.rs index fe4a89f..808d2a2 100644 --- a/com-api-example/src/main.rs +++ b/com-api-example/src/main.rs @@ -16,8 +16,8 @@ fn main() { #[cfg(test)] mod test { use com_api::{ - Builder, ConsumerDescriptor, InstanceSpecifier, Producer, SampleContainer, - SampleMaybeUninit, SampleMut, ServiceDiscovery, Subscriber, Subscription, + Builder, ConsumerDescriptor, InstanceSpecifier, OfferedProducer, Producer, Publisher, + SampleContainer, SampleMaybeUninit, SampleMut, ServiceDiscovery, Subscriber, Subscription, }; use com_api_sample_gen::{Tire, VehicleInterface}; @@ -34,6 +34,8 @@ mod test { let uninit_sample = offered_producer.left_tire.allocate().unwrap(); let sample = uninit_sample.write(Tire {}); sample.send().unwrap(); + + offered_producer.unoffer(); } #[test] diff --git a/com-api-sample-runtime/src/lib.rs b/com-api-sample-runtime/src/lib.rs index af38cd8..3eba6cd 100644 --- a/com-api-sample-runtime/src/lib.rs +++ b/com-api-sample-runtime/src/lib.rs @@ -144,7 +144,7 @@ where T: Reloc, { data: T, - _lifetime: PhantomData<&'a T>, + lifetime: PhantomData<&'a T>, } impl<'a, T> com_api::SampleMut for SampleMut<'a, T> @@ -187,7 +187,7 @@ where T: Reloc + Send, { data: MaybeUninit, - _lifetime: PhantomData<&'a T>, + lifetime: PhantomData<&'a T>, } impl<'a, T> com_api::SampleMaybeUninit for SampleMaybeUninit<'a, T> @@ -199,25 +199,29 @@ where fn write(self, val: T) -> SampleMut<'a, T> { SampleMut { data: val, - _lifetime: PhantomData, + lifetime: PhantomData, } } + fn as_mut_ptr(&mut self) -> *mut T { + self.data.as_mut_ptr() + } + unsafe fn assume_init(self) -> SampleMut<'a, T> { SampleMut { data: unsafe { self.data.assume_init() }, - _lifetime: PhantomData, + lifetime: PhantomData, } } } pub struct SubscribableImpl { - _data: PhantomData, + data: PhantomData, } impl Default for SubscribableImpl { fn default() -> Self { - Self { _data: PhantomData } + Self { data: PhantomData } } } @@ -305,11 +309,21 @@ where pub fn new() -> Self { Self { _data: PhantomData } } +} - pub fn allocate<'a>(&'a self) -> com_api::Result> { +impl com_api::Publisher for Publisher +where + T: Reloc + Send, +{ + type SampleMaybeUninit<'a> + = SampleMaybeUninit<'a, T> + where + Self: 'a; + + fn allocate<'a>(&'a self) -> com_api::Result> { Ok(SampleMaybeUninit { data: MaybeUninit::uninit(), - _lifetime: PhantomData, + lifetime: PhantomData, }) } } @@ -405,7 +419,7 @@ impl RuntimeBuilderImpl { #[cfg(test)] mod test { - use com_api::{SampleContainer, Subscription}; + use com_api::{Publisher, SampleContainer, SampleMaybeUninit, SampleMut, Subscription}; #[test] fn receive_stuff() { @@ -446,4 +460,12 @@ mod test { } }) } + + #[test] + fn send_stuff() { + let test_publisher = super::Publisher::::new(); + let sample = test_publisher.allocate().expect("Couldn't allocate sample"); + let sample = sample.write(42); + sample.send().expect("Send failed for sample"); + } } diff --git a/com-api/src/lib.rs b/com-api/src/lib.rs index 6d3ebf9..925690f 100644 --- a/com-api/src/lib.rs +++ b/com-api/src/lib.rs @@ -125,14 +125,12 @@ where fn send(self) -> Result<()>; } -/// A `SampleMaybeUninit` provides a reference to a memory buffer of an event with a `MaybeUninit` value. +/// A `SampleMaybeUninit` provides a reference to a memory buffer of an event whose data hasn't been +/// initialized yet. /// -/// Utilizing `DerefMut` on the buffer reveals a reference to the internal `MaybeUninit`. -/// The buffer can be assumed initialized with mutable access by calling `assume_init` which returns a `SampleMut`. +/// The buffer can be assumed initialized with mutable access by calling `assume_init` which returns +/// a `SampleMut`. /// The buffers with its data lives as long as there are references to it existing in the framework. -/// -/// TODO: Shall we also require DerefMut> from implementing types? How to deal -/// TODO: with the ambiguous assume_init() then? pub trait SampleMaybeUninit where T: Send + Reloc, @@ -145,12 +143,16 @@ where /// This corresponds to `MaybeUninit::write`. fn write(self, value: T) -> Self::SampleMut; + /// Get a mutable pointer to the internal maybe uninitialized `T`. + /// + /// The caller has to make sure to initialize the data in the buffer. + /// Reading from the received pointer before initialization is undefined behavior. + fn as_mut_ptr(&mut self) -> *mut T; + /// Render the buffer initialized for mutable access. /// /// This corresponds to `MaybeUninit::assume_init`. /// - /// TODO: Collision with MaybeUninit::assume_init() needs to be resolved. - /// /// # Safety /// /// The caller has to make sure to initialize the data in the buffer before calling this method. @@ -159,6 +161,7 @@ where pub trait Interface {} +#[must_use = "if a service is offered it will be unoffered and dropped immediately, causing unexpected behavior in the system"] pub trait OfferedProducer { type Interface: Interface; type Producer: Producer; @@ -173,6 +176,23 @@ pub trait Producer { fn offer(self) -> Result; } +pub trait Publisher +where + T: Reloc + Send, +{ + type SampleMaybeUninit<'a>: SampleMaybeUninit + 'a + where + Self: 'a; + + fn allocate<'a>(&'a self) -> Result>; + + fn send(&self, value: T) -> Result<()> { + let sample = self.allocate()?; + let init_sample = sample.write(value); + init_sample.send() + } +} + pub trait Consumer {} pub trait ProducerBuilder>: