@@ -1441,6 +1441,36 @@ mod tests {
14411441 } ) ;
14421442 }
14431443
1444+ #[ cfg( not( target_arch = "wasm32" ) ) ] // We are building wasm Python with pthreads disabled
1445+ #[ test]
1446+ fn test_critical_section_mutex2_same_object_no_deadlock ( ) {
1447+ let barrier = Barrier :: new ( 2 ) ;
1448+
1449+ let m = PyMutex :: new ( false ) ;
1450+
1451+ std:: thread:: scope ( |s| {
1452+ s. spawn ( || {
1453+ Python :: attach ( |py| {
1454+ with_critical_section_mutex2 ( py, & m, & m, |b1, b2| {
1455+ barrier. wait ( ) ;
1456+ std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 10 ) ) ;
1457+ unsafe { ( * b1. get ( ) ) = true } ;
1458+ assert ! ( unsafe { * b2. get( ) } ) ;
1459+ } ) ;
1460+ } ) ;
1461+ } ) ;
1462+ s. spawn ( || {
1463+ barrier. wait ( ) ;
1464+ Python :: attach ( |py| {
1465+ // this blocks until the other thread's critical section finishes
1466+ with_critical_section_mutex ( py, & m, |b| {
1467+ assert ! ( unsafe { * b. get( ) } ) ;
1468+ } ) ;
1469+ } ) ;
1470+ } ) ;
1471+ } ) ;
1472+ }
1473+
14441474 #[ cfg( feature = "macros" ) ]
14451475 #[ cfg( not( target_arch = "wasm32" ) ) ] // We are building wasm Python with pthreads disabled
14461476 #[ test]
@@ -1496,6 +1526,53 @@ mod tests {
14961526 } ) ;
14971527 }
14981528
1529+ #[ cfg( not( target_arch = "wasm32" ) ) ] // We are building wasm Python with pthreads disabled
1530+ #[ test]
1531+ fn test_critical_section_mutex2_two_containers ( ) {
1532+ let ( m1, m2) = ( PyMutex :: new ( vec ! [ 1 , 2 , 3 ] ) , PyMutex :: new ( vec ! [ 4 , 5 ] ) ) ;
1533+
1534+ std:: thread:: scope ( |s| {
1535+ s. spawn ( || {
1536+ Python :: attach ( |py| {
1537+ with_critical_section_mutex2 ( py, & m1, & m2, |v1, v2| {
1538+ // v1.extend(v1)
1539+ let vec1 = unsafe { & mut * v1. get ( ) } ;
1540+ let vec2 = unsafe { & * v2. get ( ) } ;
1541+ vec1. extend ( vec2. iter ( ) ) ;
1542+ } )
1543+ } ) ;
1544+ } ) ;
1545+ s. spawn ( || {
1546+ Python :: attach ( |py| {
1547+ with_critical_section_mutex2 ( py, & m1, & m2, |v1, v2| {
1548+ // v2.extend(v1)
1549+ let vec1 = unsafe { & * v1. get ( ) } ;
1550+ let vec2 = unsafe { & mut * v2. get ( ) } ;
1551+ vec2. extend ( vec1. iter ( ) ) ;
1552+ } )
1553+ } ) ;
1554+ } ) ;
1555+ } ) ;
1556+
1557+ // execution order is not guaranteed, so we need to check both
1558+ // NB: extend should be atomic, items must not be interleaved
1559+ // v1.extend(v2)
1560+ // v2.extend(v1)
1561+ let expected1_vec1 = vec ! [ 1 , 2 , 3 , 4 , 5 ] ;
1562+ let expected1_vec2 = vec ! [ 4 , 5 , 1 , 2 , 3 , 4 , 5 ] ;
1563+ // v2.extend(v1)
1564+ // v1.extend(v2)
1565+ let expected2_vec1 = vec ! [ 1 , 2 , 3 , 4 , 5 , 1 , 2 , 3 ] ;
1566+ let expected2_vec2 = vec ! [ 4 , 5 , 1 , 2 , 3 ] ;
1567+
1568+ let v1 = m1. lock ( ) . unwrap ( ) ;
1569+ let v2 = m2. lock ( ) . unwrap ( ) ;
1570+ assert ! (
1571+ ( ( * v1) . eq( & expected1_vec1) && ( * v2) . eq( & expected1_vec2) )
1572+ || ( ( * v1) . eq( & expected2_vec1) && ( * v2) . eq( & expected2_vec2) )
1573+ ) ;
1574+ }
1575+
14991576 #[ test]
15001577 #[ cfg( not( target_arch = "wasm32" ) ) ] // We are building wasm Python with pthreads disabled
15011578 fn test_once_ext ( ) {
0 commit comments