Skip to content

Commit

Permalink
Implement Send and Sync for OSX's FsWatcher and Windows' ReadDirector…
Browse files Browse the repository at this point in the history
…yChangesWatcher (closes notify-rs#82)
  • Loading branch information
julienw committed Jun 28, 2016
1 parent 6da24d6 commit 7f74764
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/fsevent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ pub struct FsEventWatcher {
context: Option<Box<StreamContextInfo>>,
}

// CFMutableArrayRef is a type alias to *mut libc::c_void, so FsEventWatcher is not Send/Sync
// automatically.
// It's Send because the pointer is not used in other threads.
unsafe impl Send for FsEventWatcher {}
// It's Sync because all methods that change the mutable state use `&mut self`.
unsafe impl Sync for FsEventWatcher {}

fn translate_flags(flags: fse::StreamFlags) -> op::Op {
let mut ret = op::Op::empty();
if flags.contains(fse::ITEM_XATTR_MOD) {
Expand Down
6 changes: 6 additions & 0 deletions src/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,3 +436,9 @@ impl Drop for ReadDirectoryChangesWatcher {
self.wakeup_server();
}
}

// `ReadDirectoryChangesWatcher` is not Send/Sync because of the semaphore Handle.
// As said elsewhere it's perfectly safe to send it accross threads.
unsafe impl Send for ReadDirectoryChangesWatcher {}
// Because all public methods are `&mut self` it's also perfectly safe to share references.
unsafe impl Sync for ReadDirectoryChangesWatcher {}
28 changes: 28 additions & 0 deletions tests/notify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,3 +230,31 @@ fn new_recommended() {
Err(_) => assert!(false)
}
}

// if this test builds, it means RecommendedWatcher is Send.
#[test]
fn test_watcher_send() {
let (tx, _) = channel();

let mut watcher: RecommendedWatcher = Watcher::new(tx).unwrap();

thread::spawn(move || {
watcher.watch(".").unwrap();
}).join().unwrap();
}

// if this test builds, it means RecommendedWatcher is Sync.
#[test]
fn test_watcher_sync() {
use std::sync::{ Arc, RwLock };

let (tx, _) = channel();

let watcher: RecommendedWatcher = Watcher::new(tx).unwrap();
let watcher = Arc::new(RwLock::new(watcher));

thread::spawn(move || {
let mut watcher = watcher.write().unwrap();
watcher.watch(".").unwrap();
}).join().unwrap();
}

0 comments on commit 7f74764

Please sign in to comment.