diff --git a/crates/fsevent/src/fsevent.rs b/crates/fsevent/src/fsevent.rs index 95171f835c..efd498efed 100644 --- a/crates/fsevent/src/fsevent.rs +++ b/crates/fsevent/src/fsevent.rs @@ -22,11 +22,24 @@ pub struct Event { pub struct EventStream { stream: fs::FSEventStreamRef, - state: Arc>, - callback: Box>, + lifecycle: Arc>, + state: Box, } -type RunCallback = Box) -> bool>; +struct State { + latency: Duration, + paths: cf::CFMutableArrayRef, + callback: Option) -> bool>>, + last_valid_event_id: Option, +} + +impl Drop for State { + fn drop(&mut self) { + unsafe { + cf::CFRelease(self.paths); + } + } +} enum Lifecycle { New, @@ -42,15 +55,6 @@ unsafe impl Send for Lifecycle {} impl EventStream { pub fn new(paths: &[&Path], latency: Duration) -> (Self, Handle) { unsafe { - let callback = Box::new(None); - let stream_context = fs::FSEventStreamContext { - version: 0, - info: callback.as_ref() as *const _ as *mut c_void, - retain: None, - release: None, - copy_description: None, - }; - let cf_paths = cf::CFArrayCreateMutable(cf::kCFAllocatorDefault, 0, &cf::kCFTypeArrayCallBacks); assert!(!cf_paths.is_null()); @@ -69,6 +73,19 @@ impl EventStream { cf::CFRelease(cf_url); } + let state = Box::new(State { + latency, + paths: cf_paths, + callback: None, + last_valid_event_id: None, + }); + let stream_context = fs::FSEventStreamContext { + version: 0, + info: state.as_ref() as *const _ as *mut c_void, + retain: None, + release: None, + copy_description: None, + }; let stream = fs::FSEventStreamCreate( cf::kCFAllocatorDefault, Self::trampoline, @@ -80,17 +97,15 @@ impl EventStream { | fs::kFSEventStreamCreateFlagNoDefer | fs::kFSEventStreamCreateFlagWatchRoot, ); - cf::CFRelease(cf_paths); - - let state = Arc::new(Mutex::new(Lifecycle::New)); + let lifecycle = Arc::new(Mutex::new(Lifecycle::New)); ( EventStream { stream, - state: state.clone(), - callback, + lifecycle: lifecycle.clone(), + state, }, - Handle(state), + Handle(lifecycle), ) } } @@ -99,11 +114,11 @@ impl EventStream { where F: FnMut(Vec) -> bool + 'static, { - *self.callback = Some(Box::new(f)); + self.state.callback = Some(Box::new(f)); unsafe { let run_loop = cf::CFRunLoopGetCurrent(); { - let mut state = self.state.lock(); + let mut state = self.lifecycle.lock(); match *state { Lifecycle::New => *state = Lifecycle::Running(run_loop), Lifecycle::Running(_) => unreachable!(), @@ -129,8 +144,8 @@ impl EventStream { let event_paths = event_paths as *const *const ::std::os::raw::c_char; let e_ptr = event_flags as *mut u32; let i_ptr = event_ids as *mut u64; - let callback_ptr = (info as *mut Option).as_mut().unwrap(); - let callback = if let Some(callback) = callback_ptr.as_mut() { + let state = (info as *mut State).as_mut().unwrap(); + let callback = if let Some(callback) = state.callback.as_mut() { callback } else { return;