From ce05cb91c0129c3247007589cbe903ed46dca4ad Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Mon, 10 Jul 2017 00:37:20 +0600 Subject: [PATCH] fix pointer release list --- src/pythonrun.rs | 26 ++++++++++++++------- src/typeob.rs | 2 +- tests/test_class.rs | 57 +++++++++++++++++++++++++-------------------- 3 files changed, 50 insertions(+), 35 deletions(-) diff --git a/src/pythonrun.rs b/src/pythonrun.rs index 7b41c512..4c8bb885 100644 --- a/src/pythonrun.rs +++ b/src/pythonrun.rs @@ -71,8 +71,6 @@ pub fn prepare_pyo3_library() { START_PYO3.call_once(|| unsafe { // initialize release pool POINTERS = Box::into_raw(Box::new(Pointers::new())); - let p: &'static mut Pointers = mem::transmute(POINTERS); - p.init(); }); } @@ -111,6 +109,7 @@ impl Drop for GILGuard { struct Pointers { + rc: usize, owned: Vec<*mut ffi::PyObject>, borrowed: Vec<*mut ffi::PyObject>, pointers: *mut Vec<*mut ffi::PyObject>, @@ -120,16 +119,13 @@ struct Pointers { impl Pointers { fn new() -> Pointers { Pointers { + rc: 0, owned: Vec::with_capacity(250), borrowed: Vec::with_capacity(250), pointers: Box::into_raw(Box::new(Vec::with_capacity(250))), - p: spin::Mutex::new(0 as *mut _), + p: spin::Mutex::new(Box::into_raw(Box::new(Vec::with_capacity(250)))), } } - fn init(&mut self) { - let v = Box::into_raw(Box::new(Vec::with_capacity(250))); - *self.p.lock() = v; - } unsafe fn release_pointers(&mut self) { let mut v = self.p.lock(); @@ -161,6 +157,8 @@ impl Pointers { } self.release_pointers(); + + self.rc -= 1; } } @@ -176,9 +174,18 @@ impl Pool { #[inline] pub unsafe fn new() -> Pool { let p: &'static mut Pointers = mem::transmute(POINTERS); - Pool{ owned: p.owned.len(), + p.rc += 1; + Pool {owned: p.owned.len(), borrowed: p.borrowed.len(), - no_send: marker::PhantomData } + no_send: marker::PhantomData} + } + pub unsafe fn new_if_needed() -> Option { + let p: &'static mut Pointers = mem::transmute(POINTERS); + if p.rc == 0 { + Some(Pool::new()) + } else { + None + } } } @@ -226,6 +233,7 @@ impl GILGuard { unsafe { let gstate = ffi::PyGILState_Ensure(); // acquire GIL let pool: &'static mut Pointers = mem::transmute(POINTERS); + pool.rc += 1; GILGuard { owned: pool.owned.len(), borrowed: pool.borrowed.len(), diff --git a/src/typeob.rs b/src/typeob.rs index b3a92e0c..cee38889 100644 --- a/src/typeob.rs +++ b/src/typeob.rs @@ -279,7 +279,7 @@ unsafe extern "C" fn tp_dealloc_callback(obj: *mut ffi::PyObject) debug!("DEALLOC: {:?} - {:?}", obj, CStr::from_ptr((*(*obj).ob_type).tp_name).to_string_lossy()); let guard = AbortOnDrop("Cannot unwind out of tp_dealloc"); - let _pool = pythonrun::Pool::new(); + let _pool = pythonrun::Pool::new_if_needed(); let py = Python::assume_gil_acquired(); let r = >::dealloc(py, obj); mem::forget(guard); diff --git a/tests/test_class.rs b/tests/test_class.rs index 234c1955..9eb8282c 100644 --- a/tests/test_class.rs +++ b/tests/test_class.rs @@ -62,13 +62,9 @@ fn class_with_docstr() { { let gil = Python::acquire_gil(); let py = gil.python(); - println!("TEST1"); let typeobj = py.get_type::(); - println!("TEST2"); py_run!(py, typeobj, "assert typeobj.__doc__ == 'Line1\\nLine2\\n Line3'"); - println!("TEST3"); } - println!("TEST4"); } #[py::class(name=CustomName)] @@ -177,19 +173,27 @@ struct ClassWithFreelist{token: PyToken} #[test] fn class_with_freelist() { - let gil = Python::acquire_gil(); - let py = gil.python(); + let ptr; + { + let gil = Python::acquire_gil(); + let py = gil.python(); - let inst = Py::new(py, |t| ClassWithFreelist{token: t}).unwrap(); - let inst2 = Py::new(py, |t| ClassWithFreelist{token: t}).unwrap(); - let ptr = inst.as_ptr(); - drop(inst); + let inst = Py::new(py, |t| ClassWithFreelist{token: t}).unwrap(); + let inst2 = Py::new(py, |t| ClassWithFreelist{token: t}).unwrap(); + ptr = inst.as_ptr(); + drop(inst); + } - let inst3 = Py::new(py, |t| ClassWithFreelist{token: t}).unwrap(); - assert_eq!(ptr, inst3.as_ptr()); + { + let gil = Python::acquire_gil(); + let py = gil.python(); - let inst4 = Py::new(py, |t| ClassWithFreelist{token: t}).unwrap(); - assert_ne!(ptr, inst4.as_ptr()) + let inst3 = Py::new(py, |t| ClassWithFreelist{token: t}).unwrap(); + assert_eq!(ptr, inst3.as_ptr()); + + let inst4 = Py::new(py, |t| ClassWithFreelist{token: t}).unwrap(); + assert_ne!(ptr, inst4.as_ptr()) + } } struct TestDropCall { @@ -210,19 +214,22 @@ struct DataIsDropped { #[test] fn data_is_dropped() { - let gil = Python::acquire_gil(); - let py = gil.python(); - let drop_called1 = Arc::new(AtomicBool::new(false)); let drop_called2 = Arc::new(AtomicBool::new(false)); - let inst = py.init(|t| DataIsDropped{ - member1: TestDropCall { drop_called: drop_called1.clone() }, - member2: TestDropCall { drop_called: drop_called2.clone() }, - token: t - }).unwrap(); - assert!(drop_called1.load(Ordering::Relaxed) == false); - assert!(drop_called2.load(Ordering::Relaxed) == false); - drop(inst); + + { + let gil = Python::acquire_gil(); + let py = gil.python(); + let inst = py.init(|t| DataIsDropped{ + member1: TestDropCall { drop_called: drop_called1.clone() }, + member2: TestDropCall { drop_called: drop_called2.clone() }, + token: t + }).unwrap(); + assert!(drop_called1.load(Ordering::Relaxed) == false); + assert!(drop_called2.load(Ordering::Relaxed) == false); + drop(inst); + } + assert!(drop_called1.load(Ordering::Relaxed) == true); assert!(drop_called2.load(Ordering::Relaxed) == true); }