various fixes and updates for satrs-core
1. Fix pools integration test to avoid occasional deadlocks 2. tmtc module: The `CcsdsPacketHandler` and `PusServiceProvider` do not require a send bound anymore. However, these traits now have an extension trait called `Sendable<DefaultName>` which requires the trait + Send. A blanket implementation is provided. The helper structs like `PusDistributor` and `CcsdsDistributor` require the new Sendable trait version to allow more ergnomic usage with threads.
This commit is contained in:
parent
4e361e4421
commit
40120dc83f
@ -99,7 +99,7 @@ use spacepackets::{ByteConversionError, CcsdsPacket, SizeMissmatch, SpHeader};
|
|||||||
/// This trait automatically implements the [downcast_rs::Downcast] to allow a more convenient API
|
/// This trait automatically implements the [downcast_rs::Downcast] to allow a more convenient API
|
||||||
/// to cast trait objects back to their concrete type after the handler was passed to the
|
/// to cast trait objects back to their concrete type after the handler was passed to the
|
||||||
/// distributor.
|
/// distributor.
|
||||||
pub trait CcsdsPacketHandler: Downcast + Send {
|
pub trait CcsdsPacketHandler: Downcast {
|
||||||
type Error;
|
type Error;
|
||||||
|
|
||||||
fn valid_apids(&self) -> &'static [u16];
|
fn valid_apids(&self) -> &'static [u16];
|
||||||
@ -114,12 +114,21 @@ pub trait CcsdsPacketHandler: Downcast + Send {
|
|||||||
|
|
||||||
downcast_rs::impl_downcast!(CcsdsPacketHandler assoc Error);
|
downcast_rs::impl_downcast!(CcsdsPacketHandler assoc Error);
|
||||||
|
|
||||||
|
pub trait SendableCcsdsPacketHandler: CcsdsPacketHandler + Send {}
|
||||||
|
|
||||||
|
impl<T: CcsdsPacketHandler + Send> SendableCcsdsPacketHandler for T {}
|
||||||
|
|
||||||
|
downcast_rs::impl_downcast!(SendableCcsdsPacketHandler assoc Error);
|
||||||
|
|
||||||
/// The CCSDS distributor dispatches received CCSDS packets to a user provided packet handler.
|
/// The CCSDS distributor dispatches received CCSDS packets to a user provided packet handler.
|
||||||
|
///
|
||||||
|
/// The passed APID handler is required to be [Send]able to allow more ergonomic usage with
|
||||||
|
/// threads.
|
||||||
pub struct CcsdsDistributor<E> {
|
pub struct CcsdsDistributor<E> {
|
||||||
/// User provided APID handler stored as a generic trait object.
|
/// User provided APID handler stored as a generic trait object.
|
||||||
/// It can be cast back to the original concrete type using the [Self::apid_handler_ref] or
|
/// It can be cast back to the original concrete type using the [Self::apid_handler_ref] or
|
||||||
/// the [Self::apid_handler_mut] method.
|
/// the [Self::apid_handler_mut] method.
|
||||||
pub apid_handler: Box<dyn CcsdsPacketHandler<Error = E>>,
|
pub apid_handler: Box<dyn SendableCcsdsPacketHandler<Error = E>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
@ -155,20 +164,20 @@ impl<E: 'static> ReceivesTcCore for CcsdsDistributor<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<E: 'static> CcsdsDistributor<E> {
|
impl<E: 'static> CcsdsDistributor<E> {
|
||||||
pub fn new(apid_handler: Box<dyn CcsdsPacketHandler<Error = E>>) -> Self {
|
pub fn new(apid_handler: Box<dyn SendableCcsdsPacketHandler<Error = E>>) -> Self {
|
||||||
CcsdsDistributor { apid_handler }
|
CcsdsDistributor { apid_handler }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function can be used to retrieve a reference to the concrete instance of the APID
|
/// This function can be used to retrieve a reference to the concrete instance of the APID
|
||||||
/// handler after it was passed to the distributor. See the
|
/// handler after it was passed to the distributor. See the
|
||||||
/// [module documentation][crate::tmtc::ccsds_distrib] for an fsrc-example.
|
/// [module documentation][crate::tmtc::ccsds_distrib] for an fsrc-example.
|
||||||
pub fn apid_handler_ref<T: CcsdsPacketHandler<Error = E>>(&self) -> Option<&T> {
|
pub fn apid_handler_ref<T: SendableCcsdsPacketHandler<Error = E>>(&self) -> Option<&T> {
|
||||||
self.apid_handler.downcast_ref::<T>()
|
self.apid_handler.downcast_ref::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function can be used to retrieve a mutable reference to the concrete instance of the
|
/// This function can be used to retrieve a mutable reference to the concrete instance of the
|
||||||
/// APID handler after it was passed to the distributor.
|
/// APID handler after it was passed to the distributor.
|
||||||
pub fn apid_handler_mut<T: CcsdsPacketHandler<Error = E>>(&mut self) -> Option<&mut T> {
|
pub fn apid_handler_mut<T: SendableCcsdsPacketHandler<Error = E>>(&mut self) -> Option<&mut T> {
|
||||||
self.apid_handler.downcast_mut::<T>()
|
self.apid_handler.downcast_mut::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,19 +63,20 @@ impl AddressableId {
|
|||||||
/// This trait is implemented by both the [crate::tmtc::pus_distrib::PusDistributor] and the
|
/// This trait is implemented by both the [crate::tmtc::pus_distrib::PusDistributor] and the
|
||||||
/// [crate::tmtc::ccsds_distrib::CcsdsDistributor] which allows to pass the respective packets in
|
/// [crate::tmtc::ccsds_distrib::CcsdsDistributor] which allows to pass the respective packets in
|
||||||
/// raw byte format into them.
|
/// raw byte format into them.
|
||||||
pub trait ReceivesTcCore: Send {
|
pub trait ReceivesTcCore {
|
||||||
type Error;
|
type Error;
|
||||||
fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error>;
|
fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extension trait of [ReceivesTcCore] which allows downcasting by implementing [Downcast]
|
/// Extension trait of [ReceivesTcCore] which allows downcasting by implementing [Downcast] and
|
||||||
|
/// is also sendable.
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub trait ReceivesTc: ReceivesTcCore + Downcast {}
|
pub trait ReceivesTc: ReceivesTcCore + Downcast + Send {}
|
||||||
|
|
||||||
/// Blanket implementation to automatically implement [ReceivesTc] when the [alloc] feature
|
/// Blanket implementation to automatically implement [ReceivesTc] when the [alloc] feature
|
||||||
/// is enabled.
|
/// is enabled.
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl<T> ReceivesTc for T where T: ReceivesTcCore + 'static {}
|
impl<T> ReceivesTc for T where T: ReceivesTcCore + Send + 'static {}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl_downcast!(ReceivesTc assoc Error);
|
impl_downcast!(ReceivesTc assoc Error);
|
||||||
|
@ -67,7 +67,7 @@ use spacepackets::ecss::{PusError, PusPacket};
|
|||||||
use spacepackets::tc::PusTc;
|
use spacepackets::tc::PusTc;
|
||||||
use spacepackets::SpHeader;
|
use spacepackets::SpHeader;
|
||||||
|
|
||||||
pub trait PusServiceProvider: Downcast + Send {
|
pub trait PusServiceProvider: Downcast {
|
||||||
type Error;
|
type Error;
|
||||||
fn handle_pus_tc_packet(
|
fn handle_pus_tc_packet(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -78,12 +78,22 @@ pub trait PusServiceProvider: Downcast + Send {
|
|||||||
}
|
}
|
||||||
downcast_rs::impl_downcast!(PusServiceProvider assoc Error);
|
downcast_rs::impl_downcast!(PusServiceProvider assoc Error);
|
||||||
|
|
||||||
|
pub trait SendablePusServiceProvider: PusServiceProvider + Send {}
|
||||||
|
|
||||||
|
impl<T: Send + PusServiceProvider> SendablePusServiceProvider for T {}
|
||||||
|
|
||||||
|
downcast_rs::impl_downcast!(SendablePusServiceProvider assoc Error);
|
||||||
|
|
||||||
|
/// Generic distributor object which dispatches received packets to a user provided handler.
|
||||||
|
///
|
||||||
|
/// This distributor expects the passed trait object to be [Send]able to allow more ergonomic
|
||||||
|
/// usage with threads.
|
||||||
pub struct PusDistributor<E> {
|
pub struct PusDistributor<E> {
|
||||||
pub service_provider: Box<dyn PusServiceProvider<Error = E>>,
|
pub service_provider: Box<dyn SendablePusServiceProvider<Error = E>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E> PusDistributor<E> {
|
impl<E> PusDistributor<E> {
|
||||||
pub fn new(service_provider: Box<dyn PusServiceProvider<Error = E>>) -> Self {
|
pub fn new(service_provider: Box<dyn SendablePusServiceProvider<Error = E>>) -> Self {
|
||||||
PusDistributor { service_provider }
|
PusDistributor { service_provider }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,11 +132,13 @@ impl<E: 'static> ReceivesEcssPusTc for PusDistributor<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<E: 'static> PusDistributor<E> {
|
impl<E: 'static> PusDistributor<E> {
|
||||||
pub fn service_provider_ref<T: PusServiceProvider<Error = E>>(&self) -> Option<&T> {
|
pub fn service_provider_ref<T: SendablePusServiceProvider<Error = E>>(&self) -> Option<&T> {
|
||||||
self.service_provider.downcast_ref::<T>()
|
self.service_provider.downcast_ref::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn service_provider_mut<T: PusServiceProvider<Error = E>>(&mut self) -> Option<&mut T> {
|
pub fn service_provider_mut<T: SendablePusServiceProvider<Error = E>>(
|
||||||
|
&mut self,
|
||||||
|
) -> Option<&mut T> {
|
||||||
self.service_provider.downcast_mut::<T>()
|
self.service_provider.downcast_mut::<T>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,14 +20,15 @@ fn threaded_usage() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let jh1 = thread::spawn(move || {
|
let jh1 = thread::spawn(move || {
|
||||||
let mut pool_access = shared_clone.write().unwrap();
|
|
||||||
let addr;
|
let addr;
|
||||||
{
|
{
|
||||||
addr = rx.recv().expect("Receiving store address failed");
|
addr = rx.recv().expect("Receiving store address failed");
|
||||||
|
let mut pool_access = shared_clone.write().unwrap();
|
||||||
let pg = PoolGuard::new(pool_access.deref_mut(), addr);
|
let pg = PoolGuard::new(pool_access.deref_mut(), addr);
|
||||||
let read_res = pg.read().expect("Reading failed");
|
let read_res = pg.read().expect("Reading failed");
|
||||||
assert_eq!(read_res, DUMMY_DATA);
|
assert_eq!(read_res, DUMMY_DATA);
|
||||||
}
|
}
|
||||||
|
let pool_access = shared_clone.read().unwrap();
|
||||||
assert!(!pool_access.has_element_at(&addr).expect("Invalid address"));
|
assert!(!pool_access.has_element_at(&addr).expect("Invalid address"));
|
||||||
});
|
});
|
||||||
jh0.join().unwrap();
|
jh0.join().unwrap();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user