Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-event/src/debounce.rs')
-rw-r--r--helix-event/src/debounce.rs70
1 files changed, 0 insertions, 70 deletions
diff --git a/helix-event/src/debounce.rs b/helix-event/src/debounce.rs
deleted file mode 100644
index 5971f72b..00000000
--- a/helix-event/src/debounce.rs
+++ /dev/null
@@ -1,70 +0,0 @@
-//! Utilities for declaring an async (usually debounced) hook
-
-use std::time::Duration;
-
-use futures_executor::block_on;
-use tokio::sync::mpsc::{self, error::TrySendError, Sender};
-use tokio::time::Instant;
-
-/// Async hooks provide a convenient framework for implementing (debounced)
-/// async event handlers. Most synchronous event hooks will likely need to
-/// debounce their events, coordinate multiple different hooks and potentially
-/// track some state. `AsyncHooks` facilitate these use cases by running as
-/// a background tokio task that waits for events (usually an enum) to be
-/// sent through a channel.
-pub trait AsyncHook: Sync + Send + 'static + Sized {
- type Event: Sync + Send + 'static;
- /// Called immediately whenever an event is received, this function can
- /// consume the event immediately or debounce it. In case of debouncing,
- /// it can either define a new debounce timeout or continue the current one
- fn handle_event(&mut self, event: Self::Event, timeout: Option<Instant>) -> Option<Instant>;
-
- /// Called whenever the debounce timeline is reached
- fn finish_debounce(&mut self);
-
- fn spawn(self) -> mpsc::Sender<Self::Event> {
- // the capacity doesn't matter too much here, unless the cpu is totally overwhelmed
- // the cap will never be reached since we always immediately drain the channel
- // so it should only be reached in case of total CPU overload.
- // However, a bounded channel is much more efficient so it's nice to use here
- let (tx, rx) = mpsc::channel(128);
- // only spawn worker if we are inside runtime to avoid having to spawn a runtime for unrelated unit tests
- if tokio::runtime::Handle::try_current().is_ok() {
- tokio::spawn(run(self, rx));
- }
- tx
- }
-}
-
-async fn run<Hook: AsyncHook>(mut hook: Hook, mut rx: mpsc::Receiver<Hook::Event>) {
- let mut deadline = None;
- loop {
- let event = match deadline {
- Some(deadline_) => {
- let res = tokio::time::timeout_at(deadline_, rx.recv()).await;
- match res {
- Ok(event) => event,
- Err(_) => {
- hook.finish_debounce();
- deadline = None;
- continue;
- }
- }
- }
- None => rx.recv().await,
- };
- let Some(event) = event else {
- break;
- };
- deadline = hook.handle_event(event, deadline);
- }
-}
-
-pub fn send_blocking<T>(tx: &Sender<T>, data: T) {
- // block_on has some overhead and in practice the channel should basically
- // never be full anyway so first try sending without blocking
- if let Err(TrySendError::Full(data)) = tx.try_send(data) {
- // set a timeout so that we just drop a message instead of freezing the editor in the worst case
- let _ = block_on(tx.send_timeout(data, Duration::from_millis(10)));
- }
-}