@@ -167,7 +167,7 @@ use std::{
167167 env, io,
168168 path:: { Path , PathBuf } ,
169169 process:: { Child , Command , ExitStatus } ,
170- sync:: { Arc , Mutex , mpsc} ,
170+ sync:: { Arc , Mutex , MutexGuard , PoisonError , mpsc} ,
171171 thread,
172172 time:: { Duration , Instant } ,
173173} ;
@@ -306,19 +306,11 @@ impl Watch {
306306 /// This can be used as a binary semaphore between two execution paths that must not overlap.
307307 ///
308308 /// Workspace's `target` directory and hidden paths are excluded by default.
309- pub fn run_with_lock (
310- self ,
311- commands : impl Into < CommandList > ,
312- lock : Arc < Mutex < ( ) > > ,
313- ) -> Result < ( ) > {
309+ pub fn run_with_lock ( self , commands : impl Into < CommandList > , lock : Lock ) -> Result < ( ) > {
314310 self . run_inner ( commands, Some ( lock) )
315311 }
316312
317- fn run_inner (
318- mut self ,
319- commands : impl Into < CommandList > ,
320- lock : Option < Arc < Mutex < ( ) > > > ,
321- ) -> Result < ( ) > {
313+ fn run_inner ( mut self , commands : impl Into < CommandList > , lock : Option < Lock > ) -> Result < ( ) > {
322314 let metadata = metadata ( ) ;
323315 let list = commands. into ( ) ;
324316
@@ -384,7 +376,7 @@ impl Watch {
384376 log:: info!( "Re-running command" ) ;
385377 let mut current_child = current_child. clone ( ) ;
386378 let mut list = list. clone ( ) ;
387- let lock = lock. as_ref ( ) . map ( Arc :: clone) ;
379+ let lock = lock. clone ( ) ;
388380 thread:: spawn ( move || {
389381 let mut status = ExitStatus :: default ( ) ;
390382 let mut run_batch = || {
@@ -403,7 +395,7 @@ impl Watch {
403395 } ;
404396
405397 if let Some ( lock) = lock {
406- let _guard = lock. lock ( ) . expect ( "not poisoned" ) ;
398+ let _guard = lock. lock ( ) ;
407399 run_batch ( ) ;
408400 } else {
409401 run_batch ( ) ;
@@ -707,6 +699,27 @@ impl CommandList {
707699 }
708700}
709701
702+ /// A synchronization primitive shared between watch-driven command execution and
703+ /// external code that must not run concurrently.
704+ ///
705+ /// Clone this type to share the same lock across threads/components.
706+ #[ derive( Clone , Debug , Default ) ]
707+ pub struct Lock ( Arc < Mutex < ( ) > > ) ;
708+
709+ impl Lock {
710+ /// Create a new lock instance.
711+ pub fn new ( ) -> Self {
712+ Self :: default ( )
713+ }
714+
715+ /// Acquire the lock, blocking the current thread until it is available.
716+ ///
717+ /// The lock is released when the returned guard is dropped.
718+ pub fn lock ( & self ) -> Result < MutexGuard < ' _ , ( ) > , PoisonError < MutexGuard < ' _ , ( ) > > > {
719+ self . 0 . lock ( )
720+ }
721+ }
722+
710723#[ cfg( test) ]
711724mod test {
712725 use super :: * ;
0 commit comments