use std::sync::Arc;
use crate::api::handlers::IntoHandler;
pub fn locked<T>(fnmut: impl FnMut(T)) -> impl Fn(T) {
let lock = std::sync::Mutex::new(fnmut);
move |x| zlock!(lock)(x)
}
pub trait CallbackParameter: 'static {
type Message<'a>;
fn from_message(msg: Self::Message<'_>) -> Self;
}
trait CallbackImpl<T>: Send + Sync {
fn call(&self, t: T);
fn call_with_message(&self, msg: T::Message<'_>)
where
T: CallbackParameter,
{
self.call(T::from_message(msg))
}
}
impl<T, F: Fn(T) + Send + Sync> CallbackImpl<T> for F {
fn call(&self, t: T) {
self(t)
}
}
struct Dropper<F>
where
F: FnOnce() + Send + Sync,
{
drop: Option<F>,
}
impl<F> Drop for Dropper<F>
where
F: FnOnce() + Send + Sync,
{
fn drop(&mut self) {
if let Some(d) = self.drop.take() {
(d)()
}
}
}
trait DropperTrait {}
impl<F> DropperTrait for Dropper<F> where F: FnOnce() + Send + Sync {}
pub struct Callback<T> {
callable: Arc<dyn CallbackImpl<T>>,
drop: Option<Arc<dyn DropperTrait + Send + Sync>>,
}
impl<T> Clone for Callback<T> {
fn clone(&self) -> Self {
Self {
callable: self.callable.clone(),
drop: self.drop.clone(),
}
}
}
impl<T> Callback<T> {
pub fn new(cb: Arc<dyn Fn(T) + Send + Sync>) -> Self
where
T: 'static,
{
Self::from(move |msg| cb(msg))
}
#[inline]
pub fn call(&self, arg: T) {
self.callable.call(arg)
}
pub(crate) fn call_with_message(&self, msg: T::Message<'_>)
where
T: CallbackParameter,
{
self.callable.call_with_message(msg)
}
#[zenoh_macros::pub_visibility_if_internal]
pub(crate) fn set_on_drop(&mut self, drop: impl FnOnce() + Send + Sync + 'static) {
self.drop = Some(Arc::new(Dropper { drop: Some(drop) }));
}
}
impl<T, F: Fn(T) + Send + Sync + 'static> From<F> for Callback<T> {
fn from(value: F) -> Self {
Self {
callable: Arc::new(value),
drop: None,
}
}
}
impl<T> IntoHandler<T> for Callback<T> {
type Handler = ();
fn into_handler(self) -> (Callback<T>, Self::Handler) {
(self, ())
}
}
impl<T, F, H> IntoHandler<T> for (F, H)
where
F: Fn(T) + Send + Sync + 'static,
{
type Handler = H;
fn into_handler(self) -> (Callback<T>, Self::Handler) {
(Callback::from(self.0), self.1)
}
}
impl<T, H> IntoHandler<T> for (Callback<T>, H) {
type Handler = H;
fn into_handler(self) -> (Callback<T>, Self::Handler) {
self
}
}
impl<T: Send + 'static> IntoHandler<T> for (flume::Sender<T>, flume::Receiver<T>) {
type Handler = flume::Receiver<T>;
fn into_handler(self) -> (Callback<T>, Self::Handler) {
let (sender, receiver) = self;
(
Callback::from(move |t| {
if let Err(e) = sender.send(t) {
tracing::error!("{}", e)
}
}),
receiver,
)
}
}
pub struct CallbackDrop<Callback, DropFn>
where
DropFn: FnMut() + Send + Sync + 'static,
{
pub callback: Callback,
pub drop: DropFn,
}
impl<Callback, DropFn> Drop for CallbackDrop<Callback, DropFn>
where
DropFn: FnMut() + Send + Sync + 'static,
{
fn drop(&mut self) {
(self.drop)()
}
}
impl<OnEvent, Event, DropFn> IntoHandler<Event> for CallbackDrop<OnEvent, DropFn>
where
OnEvent: Fn(Event) + Send + Sync + 'static,
DropFn: FnMut() + Send + Sync + 'static,
{
type Handler = ();
fn into_handler(self) -> (Callback<Event>, Self::Handler) {
(move |evt| (self.callback)(evt), ()).into_handler()
}
}