@@ -5,12 +5,10 @@ use crate::pyobject::{PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue};
5
5
use crate :: vm:: VirtualMachine ;
6
6
7
7
use parking_lot:: {
8
- lock_api:: { GetThreadId , RawMutex as RawMutexT , RawMutexTimed } ,
8
+ lock_api:: { RawMutex as RawMutexT , RawMutexTimed , RawReentrantMutex } ,
9
9
RawMutex , RawThreadId ,
10
10
} ;
11
- use std:: cell:: Cell ;
12
11
use std:: fmt;
13
- use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
14
12
use std:: time:: Duration ;
15
13
16
14
#[ cfg( not( target_os = "windows" ) ) ]
@@ -21,44 +19,6 @@ const PY_TIMEOUT_MAX: isize = 0xffffffff * 1_000_000;
21
19
22
20
const TIMEOUT_MAX : f64 = ( PY_TIMEOUT_MAX / 1_000_000_000 ) as f64 ;
23
21
24
- #[ pyimpl]
25
- trait LockProtocol : PyValue {
26
- type RawMutex : RawMutexT + RawMutexTimed < Duration = Duration > ;
27
- fn mutex ( & self ) -> & Self :: RawMutex ;
28
-
29
- #[ pymethod]
30
- #[ pymethod( name = "acquire_lock" ) ]
31
- #[ pymethod( name = "__enter__" ) ]
32
- #[ allow( clippy:: float_cmp, clippy:: match_bool) ]
33
- fn acquire ( & self , args : AcquireArgs , vm : & VirtualMachine ) -> PyResult < bool > {
34
- let mu = self . mutex ( ) ;
35
- match args. waitflag {
36
- true if args. timeout == -1.0 => {
37
- mu. lock ( ) ;
38
- Ok ( true )
39
- }
40
- true if args. timeout < 0.0 => {
41
- Err ( vm. new_value_error ( "timeout value must be positive" . to_owned ( ) ) )
42
- }
43
- true => Ok ( mu. try_lock_for ( Duration :: from_secs_f64 ( args. timeout ) ) ) ,
44
- false if args. timeout != -1.0 => {
45
- Err ( vm
46
- . new_value_error ( "can't specify a timeout for a non-blocking call" . to_owned ( ) ) )
47
- }
48
- false => Ok ( mu. try_lock ( ) ) ,
49
- }
50
- }
51
- #[ pymethod]
52
- #[ pymethod( name = "release_lock" ) ]
53
- fn release ( & self ) {
54
- self . mutex ( ) . unlock ( )
55
- }
56
-
57
- #[ pymethod( magic) ]
58
- fn exit ( & self , _args : PyFuncArgs ) {
59
- self . release ( )
60
- }
61
- }
62
22
#[ derive( FromArgs ) ]
63
23
struct AcquireArgs {
64
24
#[ pyarg( positional_or_keyword, default = "true" ) ]
@@ -84,98 +44,43 @@ impl fmt::Debug for PyLock {
84
44
}
85
45
}
86
46
87
- impl LockProtocol for PyLock {
88
- type RawMutex = RawMutex ;
89
- fn mutex ( & self ) -> & RawMutex {
90
- & self . mu
91
- }
92
- }
93
-
94
- #[ pyimpl( with( LockProtocol ) ) ]
47
+ #[ pyimpl]
95
48
impl PyLock {
96
- // TODO: locked(), might require something to change in parking_lot
97
- }
98
-
99
- // Copied from lock_api
100
- // TODO: open a PR to make this public in lock_api
101
- struct RawReentrantMutex < R , G > {
102
- owner : AtomicUsize ,
103
- lock_count : Cell < usize > ,
104
- mutex : R ,
105
- get_thread_id : G ,
106
- }
107
-
108
- impl < R : RawMutexT , G : GetThreadId > RawReentrantMutex < R , G > {
109
- #[ inline]
110
- fn lock_internal < F : FnOnce ( ) -> bool > ( & self , try_lock : F ) -> bool {
111
- let id = self . get_thread_id . nonzero_thread_id ( ) . get ( ) ;
112
- if self . owner . load ( Ordering :: Relaxed ) == id {
113
- self . lock_count . set (
114
- self . lock_count
115
- . get ( )
116
- . checked_add ( 1 )
117
- . expect ( "ReentrantMutex lock count overflow" ) ,
118
- ) ;
119
- } else {
120
- if !try_lock ( ) {
121
- return false ;
49
+ #[ pymethod]
50
+ #[ pymethod( name = "acquire_lock" ) ]
51
+ #[ pymethod( name = "__enter__" ) ]
52
+ #[ allow( clippy:: float_cmp, clippy:: match_bool) ]
53
+ fn acquire ( & self , args : AcquireArgs , vm : & VirtualMachine ) -> PyResult < bool > {
54
+ match args. waitflag {
55
+ true if args. timeout == -1.0 => {
56
+ self . mu . lock ( ) ;
57
+ Ok ( true )
58
+ }
59
+ true if args. timeout < 0.0 => {
60
+ Err ( vm. new_value_error ( "timeout value must be positive" . to_owned ( ) ) )
61
+ }
62
+ true => Ok ( self . mu . try_lock_for ( Duration :: from_secs_f64 ( args. timeout ) ) ) ,
63
+ false if args. timeout != -1.0 => {
64
+ Err ( vm
65
+ . new_value_error ( "can't specify a timeout for a non-blocking call" . to_owned ( ) ) )
122
66
}
123
- self . owner . store ( id, Ordering :: Relaxed ) ;
124
- debug_assert_eq ! ( self . lock_count. get( ) , 0 ) ;
125
- self . lock_count . set ( 1 ) ;
67
+ false => Ok ( self . mu . try_lock ( ) ) ,
126
68
}
127
- true
128
69
}
129
- }
130
-
131
- unsafe impl < R : RawMutexT + Send , G : GetThreadId + Send > Send for RawReentrantMutex < R , G > { }
132
- unsafe impl < R : RawMutexT + Sync , G : GetThreadId + Sync > Sync for RawReentrantMutex < R , G > { }
133
-
134
- unsafe impl < R : RawMutexT , G : GetThreadId > RawMutexT for RawReentrantMutex < R , G > {
135
- const INIT : Self = RawReentrantMutex {
136
- owner : AtomicUsize :: new ( 0 ) ,
137
- lock_count : Cell :: new ( 0 ) ,
138
- mutex : R :: INIT ,
139
- get_thread_id : G :: INIT ,
140
- } ;
141
-
142
- type GuardMarker = R :: GuardMarker ;
143
-
144
- #[ inline]
145
- fn lock ( & self ) {
146
- self . lock_internal ( || {
147
- self . mutex . lock ( ) ;
148
- true
149
- } ) ;
150
- }
151
-
152
- #[ inline]
153
- fn try_lock ( & self ) -> bool {
154
- self . lock_internal ( || self . mutex . try_lock ( ) )
70
+ #[ pymethod]
71
+ #[ pymethod( name = "release_lock" ) ]
72
+ fn release ( & self ) {
73
+ self . mu . unlock ( )
155
74
}
156
75
157
- #[ inline]
158
- fn unlock ( & self ) {
159
- let lock_count = self . lock_count . get ( ) - 1 ;
160
- self . lock_count . set ( lock_count) ;
161
- if lock_count == 0 {
162
- self . owner . store ( 0 , Ordering :: Relaxed ) ;
163
- self . mutex . unlock ( ) ;
164
- }
165
- }
166
- }
167
-
168
- unsafe impl < R : RawMutexTimed , G : GetThreadId > RawMutexTimed for RawReentrantMutex < R , G > {
169
- type Instant = R :: Instant ;
170
- type Duration = R :: Duration ;
171
- #[ inline]
172
- fn try_lock_until ( & self , timeout : R :: Instant ) -> bool {
173
- self . lock_internal ( || self . mutex . try_lock_until ( timeout) )
76
+ #[ pymethod( magic) ]
77
+ fn exit ( & self , _args : PyFuncArgs ) {
78
+ self . release ( )
174
79
}
175
80
176
- #[ inline ]
177
- fn try_lock_for ( & self , timeout : R :: Duration ) -> bool {
178
- self . lock_internal ( || self . mutex . try_lock_for ( timeout ) )
81
+ #[ pymethod ]
82
+ fn locked ( & self ) -> bool {
83
+ self . mu . is_locked ( )
179
84
}
180
85
}
181
86
@@ -197,14 +102,7 @@ impl fmt::Debug for PyRLock {
197
102
}
198
103
}
199
104
200
- impl LockProtocol for PyRLock {
201
- type RawMutex = RawRMutex ;
202
- fn mutex ( & self ) -> & Self :: RawMutex {
203
- & self . mu
204
- }
205
- }
206
-
207
- #[ pyimpl( with( LockProtocol ) ) ]
105
+ #[ pyimpl]
208
106
impl PyRLock {
209
107
#[ pyslot]
210
108
fn tp_new ( cls : PyClassRef , vm : & VirtualMachine ) -> PyResult < PyRef < Self > > {
@@ -213,6 +111,38 @@ impl PyRLock {
213
111
}
214
112
. into_ref_with_type ( vm, cls)
215
113
}
114
+
115
+ #[ pymethod]
116
+ #[ pymethod( name = "acquire_lock" ) ]
117
+ #[ pymethod( name = "__enter__" ) ]
118
+ #[ allow( clippy:: float_cmp, clippy:: match_bool) ]
119
+ fn acquire ( & self , args : AcquireArgs , vm : & VirtualMachine ) -> PyResult < bool > {
120
+ match args. waitflag {
121
+ true if args. timeout == -1.0 => {
122
+ self . mu . lock ( ) ;
123
+ Ok ( true )
124
+ }
125
+ true if args. timeout < 0.0 => {
126
+ Err ( vm. new_value_error ( "timeout value must be positive" . to_owned ( ) ) )
127
+ }
128
+ true => Ok ( self . mu . try_lock_for ( Duration :: from_secs_f64 ( args. timeout ) ) ) ,
129
+ false if args. timeout != -1.0 => {
130
+ Err ( vm
131
+ . new_value_error ( "can't specify a timeout for a non-blocking call" . to_owned ( ) ) )
132
+ }
133
+ false => Ok ( self . mu . try_lock ( ) ) ,
134
+ }
135
+ }
136
+ #[ pymethod]
137
+ #[ pymethod( name = "release_lock" ) ]
138
+ fn release ( & self ) {
139
+ self . mu . unlock ( )
140
+ }
141
+
142
+ #[ pymethod( magic) ]
143
+ fn exit ( & self , _args : PyFuncArgs ) {
144
+ self . release ( )
145
+ }
216
146
}
217
147
218
148
fn get_ident ( ) -> u64 {
0 commit comments