fix pointer release list
This commit is contained in:
parent
c1c4648add
commit
ce05cb91c0
|
@ -71,8 +71,6 @@ pub fn prepare_pyo3_library() {
|
||||||
START_PYO3.call_once(|| unsafe {
|
START_PYO3.call_once(|| unsafe {
|
||||||
// initialize release pool
|
// initialize release pool
|
||||||
POINTERS = Box::into_raw(Box::new(Pointers::new()));
|
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 {
|
struct Pointers {
|
||||||
|
rc: usize,
|
||||||
owned: Vec<*mut ffi::PyObject>,
|
owned: Vec<*mut ffi::PyObject>,
|
||||||
borrowed: Vec<*mut ffi::PyObject>,
|
borrowed: Vec<*mut ffi::PyObject>,
|
||||||
pointers: *mut Vec<*mut ffi::PyObject>,
|
pointers: *mut Vec<*mut ffi::PyObject>,
|
||||||
|
@ -120,16 +119,13 @@ struct Pointers {
|
||||||
impl Pointers {
|
impl Pointers {
|
||||||
fn new() -> Pointers {
|
fn new() -> Pointers {
|
||||||
Pointers {
|
Pointers {
|
||||||
|
rc: 0,
|
||||||
owned: Vec::with_capacity(250),
|
owned: Vec::with_capacity(250),
|
||||||
borrowed: Vec::with_capacity(250),
|
borrowed: Vec::with_capacity(250),
|
||||||
pointers: Box::into_raw(Box::new(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) {
|
unsafe fn release_pointers(&mut self) {
|
||||||
let mut v = self.p.lock();
|
let mut v = self.p.lock();
|
||||||
|
@ -161,6 +157,8 @@ impl Pointers {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.release_pointers();
|
self.release_pointers();
|
||||||
|
|
||||||
|
self.rc -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,9 +174,18 @@ impl Pool {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn new() -> Pool {
|
pub unsafe fn new() -> Pool {
|
||||||
let p: &'static mut Pointers = mem::transmute(POINTERS);
|
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(),
|
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 {
|
unsafe {
|
||||||
let gstate = ffi::PyGILState_Ensure(); // acquire GIL
|
let gstate = ffi::PyGILState_Ensure(); // acquire GIL
|
||||||
let pool: &'static mut Pointers = mem::transmute(POINTERS);
|
let pool: &'static mut Pointers = mem::transmute(POINTERS);
|
||||||
|
pool.rc += 1;
|
||||||
|
|
||||||
GILGuard { owned: pool.owned.len(),
|
GILGuard { owned: pool.owned.len(),
|
||||||
borrowed: pool.borrowed.len(),
|
borrowed: pool.borrowed.len(),
|
||||||
|
|
|
@ -279,7 +279,7 @@ unsafe extern "C" fn tp_dealloc_callback<T>(obj: *mut ffi::PyObject)
|
||||||
debug!("DEALLOC: {:?} - {:?}", obj,
|
debug!("DEALLOC: {:?} - {:?}", obj,
|
||||||
CStr::from_ptr((*(*obj).ob_type).tp_name).to_string_lossy());
|
CStr::from_ptr((*(*obj).ob_type).tp_name).to_string_lossy());
|
||||||
let guard = AbortOnDrop("Cannot unwind out of tp_dealloc");
|
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 py = Python::assume_gil_acquired();
|
||||||
let r = <T as PyObjectAlloc<T>>::dealloc(py, obj);
|
let r = <T as PyObjectAlloc<T>>::dealloc(py, obj);
|
||||||
mem::forget(guard);
|
mem::forget(guard);
|
||||||
|
|
|
@ -62,13 +62,9 @@ fn class_with_docstr() {
|
||||||
{
|
{
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
println!("TEST1");
|
|
||||||
let typeobj = py.get_type::<ClassWithDocs>();
|
let typeobj = py.get_type::<ClassWithDocs>();
|
||||||
println!("TEST2");
|
|
||||||
py_run!(py, typeobj, "assert typeobj.__doc__ == 'Line1\\nLine2\\n Line3'");
|
py_run!(py, typeobj, "assert typeobj.__doc__ == 'Line1\\nLine2\\n Line3'");
|
||||||
println!("TEST3");
|
|
||||||
}
|
}
|
||||||
println!("TEST4");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[py::class(name=CustomName)]
|
#[py::class(name=CustomName)]
|
||||||
|
@ -177,19 +173,27 @@ struct ClassWithFreelist{token: PyToken}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn class_with_freelist() {
|
fn class_with_freelist() {
|
||||||
let gil = Python::acquire_gil();
|
let ptr;
|
||||||
let py = gil.python();
|
{
|
||||||
|
let gil = Python::acquire_gil();
|
||||||
|
let py = gil.python();
|
||||||
|
|
||||||
let inst = Py::new(py, |t| ClassWithFreelist{token: t}).unwrap();
|
let inst = Py::new(py, |t| ClassWithFreelist{token: t}).unwrap();
|
||||||
let inst2 = Py::new(py, |t| ClassWithFreelist{token: t}).unwrap();
|
let inst2 = Py::new(py, |t| ClassWithFreelist{token: t}).unwrap();
|
||||||
let ptr = inst.as_ptr();
|
ptr = inst.as_ptr();
|
||||||
drop(inst);
|
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();
|
let inst3 = Py::new(py, |t| ClassWithFreelist{token: t}).unwrap();
|
||||||
assert_ne!(ptr, inst4.as_ptr())
|
assert_eq!(ptr, inst3.as_ptr());
|
||||||
|
|
||||||
|
let inst4 = Py::new(py, |t| ClassWithFreelist{token: t}).unwrap();
|
||||||
|
assert_ne!(ptr, inst4.as_ptr())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TestDropCall {
|
struct TestDropCall {
|
||||||
|
@ -210,19 +214,22 @@ struct DataIsDropped {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn data_is_dropped() {
|
fn data_is_dropped() {
|
||||||
let gil = Python::acquire_gil();
|
|
||||||
let py = gil.python();
|
|
||||||
|
|
||||||
let drop_called1 = Arc::new(AtomicBool::new(false));
|
let drop_called1 = Arc::new(AtomicBool::new(false));
|
||||||
let drop_called2 = 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() },
|
let gil = Python::acquire_gil();
|
||||||
token: t
|
let py = gil.python();
|
||||||
}).unwrap();
|
let inst = py.init(|t| DataIsDropped{
|
||||||
assert!(drop_called1.load(Ordering::Relaxed) == false);
|
member1: TestDropCall { drop_called: drop_called1.clone() },
|
||||||
assert!(drop_called2.load(Ordering::Relaxed) == false);
|
member2: TestDropCall { drop_called: drop_called2.clone() },
|
||||||
drop(inst);
|
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_called1.load(Ordering::Relaxed) == true);
|
||||||
assert!(drop_called2.load(Ordering::Relaxed) == true);
|
assert!(drop_called2.load(Ordering::Relaxed) == true);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue