diff options
Diffstat (limited to 'helix-event')
-rw-r--r-- | helix-event/Cargo.toml | 15 | ||||
-rw-r--r-- | helix-event/src/lib.rs | 8 | ||||
-rw-r--r-- | helix-event/src/redraw.rs | 49 |
3 files changed, 72 insertions, 0 deletions
diff --git a/helix-event/Cargo.toml b/helix-event/Cargo.toml new file mode 100644 index 00000000..5cd95558 --- /dev/null +++ b/helix-event/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "helix-event" +version = "0.6.0" +authors = ["Blaž Hrastnik <blaz@mxxn.io>"] +edition = "2021" +license = "MPL-2.0" +categories = ["editor"] +repository = "https://github.com/helix-editor/helix" +homepage = "https://helix-editor.com" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +tokio = { version = "1", features = ["rt", "rt-multi-thread", "time", "sync", "parking_lot"] } +parking_lot = { version = "0.12", features = ["send_guard"] } diff --git a/helix-event/src/lib.rs b/helix-event/src/lib.rs new file mode 100644 index 00000000..9c082b93 --- /dev/null +++ b/helix-event/src/lib.rs @@ -0,0 +1,8 @@ +//! `helix-event` contains systems that allow (often async) communication between +//! different editor components without strongly coupling them. Currently this +//! crate only contains some smaller facilities but the intend is to add more +//! functionality in the future ( like a generic hook system) + +pub use redraw::{lock_frame, redraw_requested, request_redraw, start_frame, RenderLockGuard}; + +mod redraw; diff --git a/helix-event/src/redraw.rs b/helix-event/src/redraw.rs new file mode 100644 index 00000000..a9915223 --- /dev/null +++ b/helix-event/src/redraw.rs @@ -0,0 +1,49 @@ +//! Signals that control when/if the editor redraws + +use std::future::Future; + +use parking_lot::{RwLock, RwLockReadGuard}; +use tokio::sync::Notify; + +/// A `Notify` instance that can be used to (asynchronously) request +/// the editor the render a new frame. +static REDRAW_NOTIFY: Notify = Notify::const_new(); + +/// A `RwLock` that prevents the next frame from being +/// drawn until an exclusive (write) lock can be acquired. +/// This allows asynchsonous tasks to acquire `non-exclusive` +/// locks (read) to prevent the next frame from being drawn +/// until a certain computation has finished. +static RENDER_LOCK: RwLock<()> = RwLock::new(()); + +pub type RenderLockGuard = RwLockReadGuard<'static, ()>; + +/// Requests that the editor is redrawn. The redraws are debounced (currently to +/// 30FPS) so this can be called many times without causing a ton of frames to +/// be rendered. +pub fn request_redraw() { + REDRAW_NOTIFY.notify_one(); +} + +/// Returns a future that will yield once a redraw has been asynchronously +/// requested using [`request_redraw`]. +pub fn redraw_requested() -> impl Future<Output = ()> { + REDRAW_NOTIFY.notified() +} + +/// Wait until all locks acquired with [`lock_frame`] have been released. +/// This function is called before rendering and is intended to allow the frame +/// to wait for async computations that should be included in the current frame. +pub fn start_frame() { + drop(RENDER_LOCK.write()); + // exhaust any leftover redraw notifications + let notify = REDRAW_NOTIFY.notified(); + tokio::pin!(notify); + notify.enable(); +} + +/// Acquires the render lock which will prevent the next frame from being drawn +/// until the returned guard is dropped. +pub fn lock_frame() -> RenderLockGuard { + RENDER_LOCK.read() +} |