Show More
@@ -86,7 +86,7 b' py_class!(pub class Dirs |py| {' | |||||
86 | }) |
|
86 | }) | |
87 | } |
|
87 | } | |
88 | def __iter__(&self) -> PyResult<DirsMultisetKeysIterator> { |
|
88 | def __iter__(&self) -> PyResult<DirsMultisetKeysIterator> { | |
89 | let (leak_handle, leaked_ref) = self.leak_immutable(py)?; |
|
89 | let (leak_handle, leaked_ref) = unsafe { self.leak_immutable(py)? }; | |
90 | DirsMultisetKeysIterator::create_instance( |
|
90 | DirsMultisetKeysIterator::create_instance( | |
91 | py, |
|
91 | py, | |
92 | RefCell::new(Some(leak_handle)), |
|
92 | RefCell::new(Some(leak_handle)), |
@@ -319,7 +319,7 b' py_class!(pub class DirstateMap |py| {' | |||||
319 | } |
|
319 | } | |
320 |
|
320 | |||
321 | def keys(&self) -> PyResult<DirstateMapKeysIterator> { |
|
321 | def keys(&self) -> PyResult<DirstateMapKeysIterator> { | |
322 | let (leak_handle, leaked_ref) = self.leak_immutable(py)?; |
|
322 | let (leak_handle, leaked_ref) = unsafe { self.leak_immutable(py)? }; | |
323 | DirstateMapKeysIterator::from_inner( |
|
323 | DirstateMapKeysIterator::from_inner( | |
324 | py, |
|
324 | py, | |
325 | Some(leak_handle), |
|
325 | Some(leak_handle), | |
@@ -328,7 +328,7 b' py_class!(pub class DirstateMap |py| {' | |||||
328 | } |
|
328 | } | |
329 |
|
329 | |||
330 | def items(&self) -> PyResult<DirstateMapItemsIterator> { |
|
330 | def items(&self) -> PyResult<DirstateMapItemsIterator> { | |
331 | let (leak_handle, leaked_ref) = self.leak_immutable(py)?; |
|
331 | let (leak_handle, leaked_ref) = unsafe { self.leak_immutable(py)? }; | |
332 | DirstateMapItemsIterator::from_inner( |
|
332 | DirstateMapItemsIterator::from_inner( | |
333 | py, |
|
333 | py, | |
334 | Some(leak_handle), |
|
334 | Some(leak_handle), | |
@@ -337,7 +337,7 b' py_class!(pub class DirstateMap |py| {' | |||||
337 | } |
|
337 | } | |
338 |
|
338 | |||
339 | def __iter__(&self) -> PyResult<DirstateMapKeysIterator> { |
|
339 | def __iter__(&self) -> PyResult<DirstateMapKeysIterator> { | |
340 | let (leak_handle, leaked_ref) = self.leak_immutable(py)?; |
|
340 | let (leak_handle, leaked_ref) = unsafe { self.leak_immutable(py)? }; | |
341 | DirstateMapKeysIterator::from_inner( |
|
341 | DirstateMapKeysIterator::from_inner( | |
342 | py, |
|
342 | py, | |
343 | Some(leak_handle), |
|
343 | Some(leak_handle), | |
@@ -434,7 +434,7 b' py_class!(pub class DirstateMap |py| {' | |||||
434 | } |
|
434 | } | |
435 |
|
435 | |||
436 | def copymapiter(&self) -> PyResult<CopyMapKeysIterator> { |
|
436 | def copymapiter(&self) -> PyResult<CopyMapKeysIterator> { | |
437 | let (leak_handle, leaked_ref) = self.leak_immutable(py)?; |
|
437 | let (leak_handle, leaked_ref) = unsafe { self.leak_immutable(py)? }; | |
438 | CopyMapKeysIterator::from_inner( |
|
438 | CopyMapKeysIterator::from_inner( | |
439 | py, |
|
439 | py, | |
440 | Some(leak_handle), |
|
440 | Some(leak_handle), | |
@@ -443,7 +443,7 b' py_class!(pub class DirstateMap |py| {' | |||||
443 | } |
|
443 | } | |
444 |
|
444 | |||
445 | def copymapitemsiter(&self) -> PyResult<CopyMapItemsIterator> { |
|
445 | def copymapitemsiter(&self) -> PyResult<CopyMapItemsIterator> { | |
446 | let (leak_handle, leaked_ref) = self.leak_immutable(py)?; |
|
446 | let (leak_handle, leaked_ref) = unsafe { self.leak_immutable(py)? }; | |
447 | CopyMapItemsIterator::from_inner( |
|
447 | CopyMapItemsIterator::from_inner( | |
448 | py, |
|
448 | py, | |
449 | Some(leak_handle), |
|
449 | Some(leak_handle), |
@@ -58,7 +58,12 b' impl PySharedState {' | |||||
58 | /// Return a reference to the wrapped data with an artificial static |
|
58 | /// Return a reference to the wrapped data with an artificial static | |
59 | /// lifetime. |
|
59 | /// lifetime. | |
60 | /// We need to be protected by the GIL for thread-safety. |
|
60 | /// We need to be protected by the GIL for thread-safety. | |
61 | pub fn leak_immutable<T>( |
|
61 | /// | |
|
62 | /// # Safety | |||
|
63 | /// | |||
|
64 | /// This is highly unsafe since the lifetime of the given data can be | |||
|
65 | /// extended. Do not call this function directly. | |||
|
66 | pub unsafe fn leak_immutable<T>( | |||
62 | &self, |
|
67 | &self, | |
63 | py: Python, |
|
68 | py: Python, | |
64 | data: &PySharedRefCell<T>, |
|
69 | data: &PySharedRefCell<T>, | |
@@ -72,10 +77,14 b' impl PySharedState {' | |||||
72 | } |
|
77 | } | |
73 | let ptr = data.as_ptr(); |
|
78 | let ptr = data.as_ptr(); | |
74 | self.leak_count.replace(self.leak_count.get() + 1); |
|
79 | self.leak_count.replace(self.leak_count.get() + 1); | |
75 |
|
|
80 | Ok(&*ptr) | |
76 | } |
|
81 | } | |
77 |
|
82 | |||
78 | pub fn decrease_leak_count(&self, _py: Python, mutable: bool) { |
|
83 | /// # Safety | |
|
84 | /// | |||
|
85 | /// It's unsafe to update the reference count without knowing the | |||
|
86 | /// reference is deleted. Do not call this function directly. | |||
|
87 | pub unsafe fn decrease_leak_count(&self, _py: Python, mutable: bool) { | |||
79 | self.leak_count |
|
88 | self.leak_count | |
80 | .replace(self.leak_count.get().saturating_sub(1)); |
|
89 | .replace(self.leak_count.get().saturating_sub(1)); | |
81 | if mutable { |
|
90 | if mutable { | |
@@ -123,6 +132,8 b" pub struct PyRefMut<'a, T> {" | |||||
123 | } |
|
132 | } | |
124 |
|
133 | |||
125 | impl<'a, T> PyRefMut<'a, T> { |
|
134 | impl<'a, T> PyRefMut<'a, T> { | |
|
135 | // Must be constructed by PySharedState after checking its leak_count. | |||
|
136 | // Otherwise, drop() would incorrectly update the state. | |||
126 | fn new( |
|
137 | fn new( | |
127 | _py: Python<'a>, |
|
138 | _py: Python<'a>, | |
128 | inner: RefMut<'a, T>, |
|
139 | inner: RefMut<'a, T>, | |
@@ -152,7 +163,9 b" impl<'a, T> Drop for PyRefMut<'a, T> {" | |||||
152 | fn drop(&mut self) { |
|
163 | fn drop(&mut self) { | |
153 | let gil = Python::acquire_gil(); |
|
164 | let gil = Python::acquire_gil(); | |
154 | let py = gil.python(); |
|
165 | let py = gil.python(); | |
155 | self.py_shared_state.decrease_leak_count(py, true); |
|
166 | unsafe { | |
|
167 | self.py_shared_state.decrease_leak_count(py, true); | |||
|
168 | } | |||
156 | } |
|
169 | } | |
157 | } |
|
170 | } | |
158 |
|
171 | |||
@@ -223,7 +236,7 b' macro_rules! py_shared_ref {' | |||||
223 | /// It's up to you to make sure that the management object lives |
|
236 | /// It's up to you to make sure that the management object lives | |
224 | /// longer than the leaked reference. Otherwise, you'll get a |
|
237 | /// longer than the leaked reference. Otherwise, you'll get a | |
225 | /// dangling reference. |
|
238 | /// dangling reference. | |
226 | fn leak_immutable<'a>( |
|
239 | unsafe fn leak_immutable<'a>( | |
227 | &'a self, |
|
240 | &'a self, | |
228 | py: Python<'a>, |
|
241 | py: Python<'a>, | |
229 | ) -> PyResult<($leaked, &'static $inner_struct)> { |
|
242 | ) -> PyResult<($leaked, &'static $inner_struct)> { | |
@@ -247,7 +260,9 b' macro_rules! py_shared_ref {' | |||||
247 | } |
|
260 | } | |
248 |
|
261 | |||
249 | impl $leaked { |
|
262 | impl $leaked { | |
250 | fn new(py: Python, inner: &$name) -> Self { |
|
263 | // Marked as unsafe so client code wouldn't construct $leaked | |
|
264 | // struct by mistake. Its drop() is unsafe. | |||
|
265 | unsafe fn new(py: Python, inner: &$name) -> Self { | |||
251 | Self { |
|
266 | Self { | |
252 | inner: inner.clone_ref(py), |
|
267 | inner: inner.clone_ref(py), | |
253 | } |
|
268 | } | |
@@ -258,9 +273,10 b' macro_rules! py_shared_ref {' | |||||
258 | fn drop(&mut self) { |
|
273 | fn drop(&mut self) { | |
259 | let gil = Python::acquire_gil(); |
|
274 | let gil = Python::acquire_gil(); | |
260 | let py = gil.python(); |
|
275 | let py = gil.python(); | |
261 | self.inner |
|
276 | let state = self.inner.py_shared_state(py); | |
262 | .py_shared_state(py) |
|
277 | unsafe { | |
263 | .decrease_leak_count(py, false); |
|
278 | state.decrease_leak_count(py, false); | |
|
279 | } | |||
264 | } |
|
280 | } | |
265 | } |
|
281 | } | |
266 | }; |
|
282 | }; | |
@@ -346,7 +362,7 b' macro_rules! py_shared_iterator_impl {' | |||||
346 | /// data py_shared_state: PySharedState; |
|
362 | /// data py_shared_state: PySharedState; | |
347 | /// |
|
363 | /// | |
348 | /// def __iter__(&self) -> PyResult<MyTypeItemsIterator> { |
|
364 | /// def __iter__(&self) -> PyResult<MyTypeItemsIterator> { | |
349 | /// let (leak_handle, leaked_ref) = self.leak_immutable(py)?; |
|
365 | /// let (leak_handle, leaked_ref) = unsafe { self.leak_immutable(py)? }; | |
350 | /// MyTypeItemsIterator::create_instance( |
|
366 | /// MyTypeItemsIterator::create_instance( | |
351 | /// py, |
|
367 | /// py, | |
352 | /// RefCell::new(Some(leak_handle)), |
|
368 | /// RefCell::new(Some(leak_handle)), |
General Comments 0
You need to be logged in to leave comments.
Login now