diff --git a/cosmic-config/Cargo.toml b/cosmic-config/Cargo.toml index 800e410..38cf3e4 100644 --- a/cosmic-config/Cargo.toml +++ b/cosmic-config/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] atomicwrites = "0.4.0" +calloop = { version = "0.10.5", optional = true } dirs = "4.0.0" notify = "5.1.0" ron = "0.8.0" diff --git a/cosmic-config/src/calloop.rs b/cosmic-config/src/calloop.rs new file mode 100644 index 0000000..cd188a0 --- /dev/null +++ b/cosmic-config/src/calloop.rs @@ -0,0 +1,63 @@ +// TODO If possible, calloop could poll inotify/kqueue without a thread + +use calloop::channel; + +use crate::{Config, Error}; + +pub struct ConfigWatchSource { + channel: channel::Channel<(Config, Vec)>, + _watcher: notify::RecommendedWatcher, +} + +impl ConfigWatchSource { + pub fn new(config: &Config) -> Result { + let (sender, channel) = channel::sync_channel(32); + let _watcher = config.watch(move |config, keys| { + let _ = sender.send((config.clone(), keys.to_owned())); + })?; + Ok(Self { channel, _watcher }) + } +} + +impl calloop::EventSource for ConfigWatchSource { + type Event = (Config, Vec); + type Metadata = (); + type Ret = (); + type Error = calloop::channel::ChannelError; + + fn process_events( + &mut self, + readiness: calloop::Readiness, + token: calloop::Token, + mut cb: F, + ) -> Result + where + F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret, + { + self.channel + .process_events(readiness, token, |event, ()| match event { + calloop::channel::Event::Msg(msg) => cb(msg, &mut ()), + calloop::channel::Event::Closed => {} + }) + } + + fn register( + &mut self, + poll: &mut calloop::Poll, + token_factory: &mut calloop::TokenFactory, + ) -> Result<(), calloop::Error> { + self.channel.register(poll, token_factory) + } + + fn reregister( + &mut self, + poll: &mut calloop::Poll, + token_factory: &mut calloop::TokenFactory, + ) -> Result<(), calloop::Error> { + self.channel.reregister(poll, token_factory) + } + + fn unregister(&mut self, poll: &mut calloop::Poll) -> Result<(), calloop::Error> { + self.channel.unregister(poll) + } +} diff --git a/cosmic-config/src/lib.rs b/cosmic-config/src/lib.rs index 49f30ea..e4b237a 100644 --- a/cosmic-config/src/lib.rs +++ b/cosmic-config/src/lib.rs @@ -7,6 +7,9 @@ use std::{ sync::Mutex, }; +#[cfg(feature = "calloop")] +pub mod calloop; + #[derive(Debug)] pub enum Error { AtomicWrites(atomicwrites::Error),