crb_send/
notifier.rs

1//! A module with notifiers.
2
3use crate::sender::{Recipient, Sender};
4use anyhow::{Result, anyhow as err};
5use std::sync::{Arc, Mutex};
6
7/// An abstract notifier.
8pub trait Notifier: Send + Sync {
9    /// Send a notification to the recipient.
10    fn notify(&self) -> Result<()>;
11
12    fn typeless(self) -> TypelessNotifier
13    where
14        Self: Sized + 'static,
15    {
16        TypelessNotifier {
17            notifier: Arc::new(self),
18        }
19    }
20}
21
22/// A notifier without a particular type.
23pub struct TypelessNotifier {
24    notifier: Arc<dyn Notifier>,
25}
26
27impl Notifier for TypelessNotifier {
28    fn notify(&self) -> Result<()> {
29        self.notifier.notify()
30    }
31}
32
33pub struct DropNotifier {
34    notifier: TypelessNotifier,
35}
36
37impl Drop for DropNotifier {
38    fn drop(&mut self) {
39        self.notifier.notify().ok();
40    }
41}
42
43pub struct TypedNotifier<M> {
44    message: M,
45    sender: Recipient<M>,
46}
47
48impl<M> TypedNotifier<M> {
49    /// Create a new notifier instance.
50    pub fn new<S>(sender: S, message: M) -> Self
51    where
52        S: Sender<M> + 'static,
53    {
54        let sender = Recipient::new(sender);
55        Self { message, sender }
56    }
57
58    pub fn once(self) -> OnceNotifier<M> {
59        OnceNotifier {
60            notifier: Mutex::new(Some(self)),
61        }
62    }
63
64    pub fn notify_once(self) -> Result<()> {
65        self.sender.send(self.message)
66    }
67}
68
69impl<M> Notifier for TypedNotifier<M>
70where
71    M: Clone + Send + Sync + 'static,
72{
73    fn notify(&self) -> Result<()> {
74        self.sender.send(self.message.clone())
75    }
76}
77
78pub struct OnceNotifier<M> {
79    notifier: Mutex<Option<TypedNotifier<M>>>,
80}
81
82impl<M> OnceNotifier<M>
83where
84    M: Send + Sync + 'static,
85{
86    pub fn into_drop_notifier(self) -> DropNotifier {
87        DropNotifier {
88            notifier: self.typeless(),
89        }
90    }
91}
92
93impl<M> Notifier for OnceNotifier<M>
94where
95    M: Send + Sync + 'static,
96{
97    fn notify(&self) -> Result<()> {
98        self.notifier
99            .lock()
100            .map_err(|_| err!("Can't get access to a notifier"))?
101            .take()
102            .ok_or_else(|| err!("Notification has already sent"))?
103            .notify_once()
104    }
105}