summaryrefslogtreecommitdiffstats
path: root/src/input/src/sender.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/input/src/sender.rs')
-rw-r--r--src/input/src/sender.rs90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/input/src/sender.rs b/src/input/src/sender.rs
new file mode 100644
index 0000000..15fe229
--- /dev/null
+++ b/src/input/src/sender.rs
@@ -0,0 +1,90 @@
+use std::{
+ borrow::BorrowMut,
+ collections::VecDeque,
+ sync::{
+ atomic::{AtomicBool, Ordering},
+ Arc,
+ },
+};
+
+use anyhow::{anyhow, Error, Result};
+use parking_lot::Mutex;
+
+use crate::{event_action::EventAction, Event};
+
+fn map_send_err(_: crossbeam_channel::SendError<EventAction>) -> Error {
+ anyhow!("Unable to send data")
+}
+
+/// Represents a message sender and receiver for passing actions between threads.
+#[derive(Clone, Debug)]
+pub struct Sender {
+ poisoned: Arc<AtomicBool>,
+ sender: crossbeam_channel::Sender<EventAction>,
+ event_queue: Arc<Mutex<VecDeque<Event>>>,
+}
+
+impl Sender {
+ /// Create a new instance.
+ #[inline]
+ #[must_use]
+ pub fn new(sender: crossbeam_channel::Sender<EventAction>) -> Self {
+ Self {
+ poisoned: Arc::new(AtomicBool::new(false)),
+ sender,
+ event_queue: Arc::new(Mutex::new(VecDeque::new())),
+ }
+ }
+
+ /// Clone the poisoned flag.
+ #[inline]
+ #[must_use]
+ pub fn clone_poisoned(&self) -> Arc<AtomicBool> {
+ Arc::clone(&self.poisoned)
+ }
+
+ /// Is the sender poisoned, and not longer accepting actions.
+ #[inline]
+ #[must_use]
+ pub fn is_poisoned(&self) -> bool {
+ self.poisoned.load(Ordering::Relaxed)
+ }
+
+ #[inline]
+ pub(crate) fn clone_event_queue(&self) -> Arc<Mutex<VecDeque<Event>>> {
+ Arc::clone(&self.event_queue)
+ }
+
+ /// Queue an end action.
+ ///
+ /// # Errors
+ /// Results in an error if the sender has been closed.
+ #[inline]
+ pub fn end(&self) -> Result<()> {
+ self.sender.send(EventAction::End).map_err(map_send_err)
+ }
+
+ /// Read an event from the queue
+ #[inline]
+ pub fn read_event(&mut self) -> Event {
+ self.event_queue.lock().borrow_mut().pop_front().unwrap_or(Event::None)
+ }
+
+ /// Add an event after existing events.
+ ///
+ /// # Errors
+ /// Results in an error if the sender has been closed.
+ #[inline]
+ pub fn enqueue_event(&self, event: Event) -> Result<()> {
+ self.sender.send(EventAction::EnqueueEvent(event)).map_err(map_send_err)
+ }
+
+ /// Add an event before existing events.
+ ///
+ /// # Errors
+ /// Results in an error if the sender has been closed.
+ #[inline]
+ pub fn push_event(&self, event: Event) -> Result<()> {
+ self.sender.send(EventAction::PushEvent(event)).map_err(map_send_err)
+ }
+}