trying own signal handler impl

This commit is contained in:
Erica Z 2024-11-03 11:57:55 +01:00
parent 3f6909128d
commit 40db5b1b18
2 changed files with 90 additions and 0 deletions

View file

@ -19,6 +19,9 @@ pub mod subsonic_vala;
mod playbin2; mod playbin2;
mod signal;
pub use signal::{Signal, SignalHandler};
use gettextrs::{bind_textdomain_codeset, bindtextdomain, setlocale, textdomain, LocaleCategory}; use gettextrs::{bind_textdomain_codeset, bindtextdomain, setlocale, textdomain, LocaleCategory};
use gtk::prelude::*; use gtk::prelude::*;
use gtk::{gio, glib}; use gtk::{gio, glib};

87
src/signal.rs Normal file
View file

@ -0,0 +1,87 @@
use std::cell::{Cell, RefCell};
use std::rc::{Rc, Weak};
#[derive(Default)]
pub struct Signal<T> {
handlers: RefCell<Vec<Box<dyn FnMut(T) -> bool>>>,
just_connected: RefCell<Vec<Box<dyn FnMut(T) -> bool>>>,
}
pub struct SignalHandler(Weak<Cell<bool>>);
impl SignalHandler {
pub fn disconnect(self) -> bool {
match self.0.upgrade() {
None => false,
Some(cell) => {
cell.set(true);
true
}
}
}
}
impl<T> Signal<T> {
fn connect_impl(&self, f: impl FnMut(T) -> bool + 'static) {
self.just_connected.borrow_mut().push(Box::new(f));
}
pub fn connect(&self, mut f: impl FnMut(T) -> bool + 'static) -> SignalHandler {
let disconnect = Rc::new(Cell::new(false));
let disconnect_weak = Rc::downgrade(&disconnect);
self.connect_impl(move |t| match disconnect.get() {
false => false,
true => {
f(t);
true
}
});
SignalHandler(disconnect_weak)
}
pub fn connect_listener<L: 'static>(
&self,
listener: &Rc<L>,
mut f: impl FnMut(Rc<L>, T) -> bool + 'static,
) -> SignalHandler {
let listener = Rc::downgrade(listener);
self.connect(move |t| match listener.upgrade() {
None => false,
Some(listener) => f(listener, t),
})
}
}
impl<T> Signal<T>
where
T: Clone,
{
pub fn emit(&self, t: T) {
let mut handlers = self
.handlers
.try_borrow_mut()
.expect("tried to re-emit signal during emission");
handlers.append(self.just_connected.borrow_mut().as_mut());
let mut i = 0;
let mut skip = 0;
loop {
if handlers[i + skip](t.clone()) {
i += 1;
} else {
skip += 1;
}
if i + skip == handlers.len() {
break;
}
handlers.swap(i, i + skip);
}
handlers.truncate(i);
}
}