fix pointer release list

This commit is contained in:
Nikolay Kim 2017-07-10 00:37:20 +06:00
parent c1c4648add
commit ce05cb91c0
3 changed files with 50 additions and 35 deletions

View File

@ -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<Pool> {
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(),

View File

@ -279,7 +279,7 @@ unsafe extern "C" fn tp_dealloc_callback<T>(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 = <T as PyObjectAlloc<T>>::dealloc(py, obj);
mem::forget(guard);

View File

@ -62,13 +62,9 @@ fn class_with_docstr() {
{
let gil = Python::acquire_gil();
let py = gil.python();
println!("TEST1");
let typeobj = py.get_type::<ClassWithDocs>();
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);
}