4646//!
4747//! [paper]: https://whileydave.com/publications/pk07_jea/
4848#![ cfg_attr( docsrs, feature( doc_cfg) ) ]
49- use std:: backtrace:: Backtrace ;
5049use std:: cell:: RefCell ;
5150use std:: fmt;
5251use std:: marker:: PhantomData ;
5352use std:: ops:: Deref ;
5453use std:: ops:: DerefMut ;
5554use std:: sync:: atomic:: AtomicUsize ;
5655use std:: sync:: atomic:: Ordering ;
57- use std:: sync:: Arc ;
5856use std:: sync:: Mutex ;
5957use std:: sync:: MutexGuard ;
6058use std:: sync:: OnceLock ;
@@ -66,6 +64,8 @@ pub use lock_api;
6664#[ cfg( feature = "parkinglot" ) ]
6765#[ cfg_attr( docsrs, doc( cfg( feature = "parkinglot" ) ) ) ]
6866pub use parking_lot;
67+ use reporting:: Dep ;
68+ use reporting:: Reportable ;
6969
7070use crate :: graph:: DiGraph ;
7171
@@ -76,6 +76,7 @@ pub mod lockapi;
7676#[ cfg( feature = "parkinglot" ) ]
7777#[ cfg_attr( docsrs, doc( cfg( feature = "parkinglot" ) ) ) ]
7878pub mod parkinglot;
79+ mod reporting;
7980pub mod stdsync;
8081
8182thread_local ! {
@@ -143,24 +144,14 @@ impl MutexId {
143144 if let Some ( & previous) = locks. borrow ( ) . last ( ) {
144145 let mut graph = get_dependency_graph ( ) ;
145146
146- graph
147- . add_edge ( previous, self . value ( ) , MutexDep :: capture)
148- . err ( )
147+ graph. add_edge ( previous, self . value ( ) , Dep :: capture) . err ( )
149148 } else {
150149 None
151150 }
152151 } ) ;
153152
154153 if let Some ( cycle) = opt_cycle {
155- // Panic without holding the lock to avoid needlessly poisoning it
156- let mut message = String :: from ( "Found cycle in mutex dependency graph:\n " ) ;
157-
158- for entry in cycle {
159- use std:: fmt:: Write ;
160- let _ = writeln ! ( message, "{entry}" ) ;
161- }
162-
163- panic ! ( "{message}" ) ;
154+ panic ! ( "{}" , Dep :: panic_message( & cycle) )
164155 }
165156
166157 HELD_LOCKS . with ( |locks| locks. borrow_mut ( ) . push ( self . value ( ) ) ) ;
@@ -270,24 +261,9 @@ impl<'a> Drop for BorrowedMutex<'a> {
270261 }
271262}
272263
273- #[ derive( Clone ) ]
274- struct MutexDep ( Arc < Backtrace > ) ;
275-
276- impl MutexDep {
277- pub fn capture ( ) -> Self {
278- Self ( Arc :: new ( Backtrace :: capture ( ) ) )
279- }
280- }
281-
282- impl fmt:: Display for MutexDep {
283- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
284- self . 0 . fmt ( f)
285- }
286- }
287-
288264/// Get a reference to the current dependency graph
289- fn get_dependency_graph ( ) -> impl DerefMut < Target = DiGraph < usize , MutexDep > > {
290- static DEPENDENCY_GRAPH : OnceLock < Mutex < DiGraph < usize , MutexDep > > > = OnceLock :: new ( ) ;
265+ fn get_dependency_graph ( ) -> impl DerefMut < Target = DiGraph < usize , Dep > > {
266+ static DEPENDENCY_GRAPH : OnceLock < Mutex < DiGraph < usize , Dep > > > = OnceLock :: new ( ) ;
291267
292268 DEPENDENCY_GRAPH
293269 . get_or_init ( Default :: default)
@@ -318,17 +294,11 @@ mod tests {
318294 let c = LazyMutexId :: new ( ) ;
319295
320296 let mut graph = get_dependency_graph ( ) ;
321- assert ! ( graph
322- . add_edge( a. value( ) , b. value( ) , MutexDep :: capture)
323- . is_ok( ) ) ;
324- assert ! ( graph
325- . add_edge( b. value( ) , c. value( ) , MutexDep :: capture)
326- . is_ok( ) ) ;
297+ assert ! ( graph. add_edge( a. value( ) , b. value( ) , Dep :: capture) . is_ok( ) ) ;
298+ assert ! ( graph. add_edge( b. value( ) , c. value( ) , Dep :: capture) . is_ok( ) ) ;
327299
328300 // Creating an edge c → a should fail as it introduces a cycle.
329- assert ! ( graph
330- . add_edge( c. value( ) , a. value( ) , MutexDep :: capture)
331- . is_err( ) ) ;
301+ assert ! ( graph. add_edge( c. value( ) , a. value( ) , Dep :: capture) . is_err( ) ) ;
332302
333303 // Drop graph handle so we can drop vertices without deadlocking
334304 drop ( graph) ;
@@ -337,7 +307,7 @@ mod tests {
337307
338308 // If b's destructor correctly ran correctly we can now add an edge from c to a.
339309 assert ! ( get_dependency_graph( )
340- . add_edge( c. value( ) , a. value( ) , MutexDep :: capture)
310+ . add_edge( c. value( ) , a. value( ) , Dep :: capture)
341311 . is_ok( ) ) ;
342312 }
343313
0 commit comments