33//! Checks the `watch`ed paths periodically to detect changes. This implementation only uses
44//! Rust stdlib APIs and should work on all of the platforms it supports.
55
6- use crate :: { Config , EventHandler , RecursiveMode , Watcher } ;
6+ use crate :: { Config , EventHandler , RecursiveMode , Watcher , Sender , unbounded , Receiver , Error } ;
77use std:: {
88 collections:: HashMap ,
99 path:: { Path , PathBuf } ,
@@ -22,7 +22,6 @@ pub type ScanEvent = crate::Result<PathBuf>;
2222/// Very much the same as [EventHandler], but including the Result.
2323///
2424/// See the full example for more information.
25- /// ```
2625pub trait ScanEventHandler : Send + ' static {
2726 /// Handles an event.
2827 fn handle_event ( & mut self , event : ScanEvent ) ;
@@ -477,7 +476,10 @@ pub struct PollWatcher {
477476 watches : Arc < Mutex < HashMap < PathBuf , WatchData > > > ,
478477 data_builder : Arc < Mutex < DataBuilder > > ,
479478 want_to_stop : Arc < AtomicBool > ,
480- delay : Duration ,
479+ /// channel to the poll loop
480+ /// currently used only for active polling
481+ message_channel : Sender < ( ) > ,
482+ delay : Option < Duration > ,
481483}
482484
483485impl PollWatcher {
@@ -486,6 +488,12 @@ impl PollWatcher {
486488 Self :: with_opt :: < _ , ( ) > ( event_handler, config, None )
487489 }
488490
491+ /// Actively poll for changes. Can be combined with a timeout of 0 to perform only manual polling.
492+ pub fn poll ( & self ) -> crate :: Result < ( ) > {
493+ self . message_channel . send ( ( ) ) . map_err ( |_|Error :: generic ( "failed to send poll message" ) ) ?;
494+ Ok ( ( ) )
495+ }
496+
489497 /// Create a new [PollWatcher] with an scan event handler.
490498 ///
491499 /// `scan_fallback` is called on the initial scan with all files seen by the pollwatcher.
@@ -497,7 +505,7 @@ impl PollWatcher {
497505 Self :: with_opt ( event_handler, config, Some ( scan_callback) )
498506 }
499507
500- /// create a new pollwatcher with all options
508+ /// create a new PollWatcher with all options
501509 fn with_opt < F : EventHandler , G : ScanEventHandler > (
502510 event_handler : F ,
503511 config : Config ,
@@ -506,19 +514,22 @@ impl PollWatcher {
506514 let data_builder =
507515 DataBuilder :: new ( event_handler, config. compare_contents ( ) , scan_callback) ;
508516
517+ let ( tx, rx) = unbounded ( ) ;
518+
509519 let poll_watcher = PollWatcher {
510520 watches : Default :: default ( ) ,
511521 data_builder : Arc :: new ( Mutex :: new ( data_builder) ) ,
512522 want_to_stop : Arc :: new ( AtomicBool :: new ( false ) ) ,
513- delay : config. poll_interval ( ) ,
523+ delay : config. poll_interval_v2 ( ) ,
524+ message_channel : tx,
514525 } ;
515526
516- poll_watcher. run ( ) ;
527+ poll_watcher. run ( rx ) ;
517528
518529 Ok ( poll_watcher)
519530 }
520531
521- fn run ( & self ) {
532+ fn run ( & self , rx : Receiver < ( ) > ) {
522533 let watches = Arc :: clone ( & self . watches ) ;
523534 let data_builder = Arc :: clone ( & self . data_builder ) ;
524535 let want_to_stop = Arc :: clone ( & self . want_to_stop ) ;
@@ -546,18 +557,12 @@ impl PollWatcher {
546557 watch_data. rescan ( & mut data_builder) ;
547558 }
548559 }
549-
550- // QUESTION: `actual_delay == process_time + delay`. Is it intended to?
551- //
552- // If not, consider fix it to:
553- //
554- // ```rust
555- // let still_need_to_delay = delay.checked_sub(data_builder.now.elapsed());
556- // if let Some(delay) = still_need_to_delay {
557- // thread::sleep(delay);
558- // }
559- // ```
560- thread:: sleep ( delay) ;
560+ // TODO: v7.0 use delay - (Instant::now().saturating_duration_since(start))
561+ if let Some ( delay) = delay {
562+ let _ = rx. recv_timeout ( delay) ;
563+ } else {
564+ let _ = rx. recv ( ) ;
565+ }
561566 }
562567 } ) ;
563568 }
0 commit comments