pub struct Watch { /* private fields */ }Expand description
A watch on one content directory.
Holds the platform watcher, which stops when this is dropped.
Implementations§
Source§impl Watch
impl Watch
Sourcepub fn on(dir: &Path, content_name: &str) -> Result<Self>
pub fn on(dir: &Path, content_name: &str) -> Result<Self>
Watch dir for changes to content_name and to anything beside it.
Non-recursive: the content directory has no subdirectories of this tool’s making, and an application that creates one has still created a sibling, which is the signal either way.
§Errors
Where the platform watcher cannot be created or cannot watch dir.
Sourcepub fn drain(&self) -> impl Iterator<Item = Change> + '_
pub fn drain(&self) -> impl Iterator<Item = Change> + '_
Every change that has arrived, without waiting.
Sourcepub fn next_change(&self, within: Duration) -> Option<Change>
pub fn next_change(&self, within: Duration) -> Option<Change>
Wait up to within for the next change.
Trait Implementations§
Source§impl Drop for Watch
The stop is waited for, and this is the fix for a measured hang.
impl Drop for Watch
The stop is waited for, and this is the fix for a measured hang.
notify’s watcher drop is fire-and-forget: it posts Action::Stop, wakes
its server thread and returns, leaving that thread inside stop_watch.
Whatever removes the watched directory next therefore races a watch that is
still stopping, and on Windows that pair deadlocks — stop_watch waits
INFINITE for a semaphore its own completion routine does not post when it
re-arms ReadDirectoryChangesW, and the re-armed read does not return while
a remove_dir_all is walking the same directory.
Measured 2026-09-07 before this existed: a diagnostic that drops a watch and
then removes the directory wedged 9 runs in 20, one instance parked with
zero CPU for over ten minutes; Opened::close, which removes first and
drops after, wedged past a 300-second timeout with the same two stacks.
docs/windows-save-test-hang.md has both, and the ordering alone was never
the cure: the 9-in-20 case already dropped the watch first.
So the watcher goes, and then this waits for the backend to say the watch
has actually stopped, which is the guarantee the caller needs before
removing anything. [STOP_WAIT] bounds the wait so that a stop which never
finishes is a delay rather than a second hang.