Use NonNull in release pool

This commit is contained in:
kngwyu 2018-11-14 15:39:07 +09:00
parent 0890f24391
commit 6d442e5969
3 changed files with 78 additions and 71 deletions

View File

@ -33,6 +33,12 @@ impl PyObject {
PyObject(ptr)
}
pub(crate) unsafe fn into_nonnull(self) -> NonNull<ffi::PyObject> {
let res = self.0;
std::mem::forget(self); // Avoid Drop
res
}
/// Creates a `PyObject` instance for the given FFI pointer.
/// This moves ownership over the pointer into the `PyObject`.
/// Undefined behavior if the pointer is NULL or invalid.

View File

@ -14,6 +14,7 @@ use crate::types::{PyDict, PyModule, PyObjectRef, PyType};
use std;
use std::ffi::CString;
use std::marker::PhantomData;
use std::ptr::NonNull;
use std::os::raw::c_int;
/// Marker type that indicates that the GIL is currently held.
@ -308,7 +309,7 @@ impl<'p> Python<'p> {
{
let p;
unsafe {
p = pythonrun::register_owned(self, obj.into_ptr());
p = pythonrun::register_owned(self, obj.into_nonnull());
}
<T as PyTryFrom>::try_from(p)
}
@ -318,17 +319,15 @@ impl<'p> Python<'p> {
where
T: PyTypeInfo,
{
let p = pythonrun::register_owned(self, obj.into_ptr());
let p = pythonrun::register_owned(self, obj.into_nonnull());
self.unchecked_downcast(p)
}
/// Register `ffi::PyObject` pointer in release pool
pub unsafe fn from_borrowed_ptr_to_obj(self, ptr: *mut ffi::PyObject) -> &'p PyObjectRef {
if ptr.is_null() {
crate::err::panic_after_error();
} else {
pythonrun::register_borrowed(self, ptr)
match NonNull::new(ptr) {
Some(p) => pythonrun::register_borrowed(self, p),
None => crate::err::panic_after_error(),
}
}
@ -339,11 +338,12 @@ impl<'p> Python<'p> {
where
T: PyTypeInfo,
{
if ptr.is_null() {
crate::err::panic_after_error();
} else {
let p = pythonrun::register_owned(self, ptr);
self.unchecked_downcast(p)
match NonNull::new(ptr) {
Some(p) => {
let p = pythonrun::register_owned(self, p);
self.unchecked_downcast(p)
}
None => crate::err::panic_after_error(),
}
}
@ -353,56 +353,58 @@ impl<'p> Python<'p> {
where
T: PyTypeInfo,
{
if ptr.is_null() {
crate::err::panic_after_error();
} else {
let p = pythonrun::register_owned(self, ptr);
self.unchecked_mut_downcast(p)
match NonNull::new(ptr) {
Some(p) => {
let p = pythonrun::register_owned(self, p);
self.unchecked_mut_downcast(p)
}
None => crate::err::panic_after_error(),
}
}
/// Register owned `ffi::PyObject` pointer in release pool.
/// Returns `Err(PyErr)` if the pointer is `null`.
/// do unchecked downcast to specific type.
pub unsafe fn from_owned_ptr_or_err<T>(self, ptr: *mut ffi::PyObject) -> PyResult<&'p T>
where
T: PyTypeInfo,
{
if ptr.is_null() {
Err(PyErr::fetch(self))
} else {
let p = pythonrun::register_owned(self, ptr);
Ok(self.unchecked_downcast(p))
match NonNull::new(ptr) {
Some(p) => {
let p = pythonrun::register_owned(self, p);
Ok(self.unchecked_downcast(p))
}
None => Err(PyErr::fetch(self)),
}
}
/// Register owned `ffi::PyObject` pointer in release pool.
/// Returns `None` if the pointer is `null`.
/// do unchecked downcast to specific type.
pub unsafe fn from_owned_ptr_or_opt<T>(self, ptr: *mut ffi::PyObject) -> Option<&'p T>
where
T: PyTypeInfo,
{
if ptr.is_null() {
None
} else {
let p = pythonrun::register_owned(self, ptr);
Some(self.unchecked_downcast(p))
}
NonNull::new(ptr).map(|p| {
let p = pythonrun::register_owned(self, p);
self.unchecked_downcast(p)
})
}
/// Register borrowed `ffi::PyObject` pointer in release pool.
/// Panics if the pointer is `null`.
/// do unchecked downcast to specific type.
pub unsafe fn from_borrowed_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'p T
where
T: PyTypeInfo,
{
let p = pythonrun::register_borrowed(self, ptr);
self.unchecked_downcast(p)
match NonNull::new(ptr) {
Some(p) => {
let p = pythonrun::register_borrowed(self, p);
self.unchecked_downcast(p)
}
None => crate::err::panic_after_error(),
}
}
/// Register borrowed `ffi::PyObject` pointer in release pool.
@ -412,44 +414,42 @@ impl<'p> Python<'p> {
where
T: PyTypeInfo,
{
if ptr.is_null() {
crate::err::panic_after_error();
} else {
let p = pythonrun::register_borrowed(self, ptr);
self.unchecked_mut_downcast(p)
match NonNull::new(ptr) {
Some(p) => {
let p = pythonrun::register_borrowed(self, p);
self.unchecked_mut_downcast(p)
}
None => crate::err::panic_after_error(),
}
}
/// Register borrowed `ffi::PyObject` pointer in release pool.
/// Returns `Err(PyErr)` if the pointer is `null`.
/// do unchecked downcast to specific type.
pub unsafe fn from_borrowed_ptr_or_err<T>(self, ptr: *mut ffi::PyObject) -> PyResult<&'p T>
where
T: PyTypeInfo,
{
if ptr.is_null() {
Err(PyErr::fetch(self))
} else {
let p = pythonrun::register_borrowed(self, ptr);
Ok(self.unchecked_downcast(p))
match NonNull::new(ptr) {
Some(p) => {
let p = pythonrun::register_borrowed(self, p);
Ok(self.unchecked_downcast(p))
}
None => Err(PyErr::fetch(self)),
}
}
/// Register borrowed `ffi::PyObject` pointer in release pool.
/// Returns `None` if the pointer is `null`.
/// do unchecked downcast to specific `T`.
pub unsafe fn from_borrowed_ptr_or_opt<T>(self, ptr: *mut ffi::PyObject) -> Option<&'p T>
where
T: PyTypeInfo,
{
if ptr.is_null() {
None
} else {
let p = pythonrun::register_borrowed(self, ptr);
Some(self.unchecked_downcast(p))
}
NonNull::new(ptr).map(|p| {
let p = pythonrun::register_borrowed(self, p);
self.unchecked_downcast(p)
})
}
#[doc(hidden)]

View File

@ -108,11 +108,11 @@ impl Drop for GILGuard {
/// Release pool
struct ReleasePool {
owned: Vec<*mut ffi::PyObject>,
borrowed: Vec<*mut ffi::PyObject>,
pointers: *mut Vec<*mut ffi::PyObject>,
owned: Vec<NonNull<ffi::PyObject>>,
borrowed: Vec<NonNull<ffi::PyObject>>,
pointers: *mut Vec<NonNull<ffi::PyObject>>,
obj: Vec<Box<any::Any>>,
p: spin::Mutex<*mut Vec<*mut ffi::PyObject>>,
p: spin::Mutex<*mut Vec<NonNull<ffi::PyObject>>>,
}
impl ReleasePool {
@ -131,7 +131,7 @@ impl ReleasePool {
// vec of pointers
let ptr = *v;
let vec: &'static mut Vec<*mut ffi::PyObject> = &mut *ptr;
let vec: &'static mut Vec<_> = &mut *ptr;
if vec.is_empty() {
return;
}
@ -143,7 +143,7 @@ impl ReleasePool {
// release py objects
for ptr in vec.iter_mut() {
ffi::Py_DECREF(*ptr);
ffi::Py_DECREF(ptr.as_ptr());
}
vec.set_len(0);
}
@ -152,7 +152,7 @@ impl ReleasePool {
let len = self.owned.len();
if owned < len {
for ptr in &mut self.owned[owned..len] {
ffi::Py_DECREF(*ptr);
ffi::Py_DECREF(ptr.as_ptr());
}
self.owned.set_len(owned);
}
@ -235,20 +235,20 @@ pub unsafe fn register_pointer(obj: NonNull<ffi::PyObject>) {
let pool: &'static mut ReleasePool = &mut *POOL;
let mut v = pool.p.lock();
let pool: &'static mut Vec<*mut ffi::PyObject> = &mut *(*v);
pool.push(obj.as_ptr());
let pool: &'static mut Vec<_> = &mut *(*v);
pool.push(obj);
}
pub unsafe fn register_owned(_py: Python, obj: *mut ffi::PyObject) -> &PyObjectRef {
pub unsafe fn register_owned(_py: Python, obj: NonNull<ffi::PyObject>) -> &PyObjectRef {
let pool: &'static mut ReleasePool = &mut *POOL;
pool.owned.push(obj);
&*(&pool.owned[pool.owned.len() - 1] as *const *mut ffi::PyObject as *const PyObjectRef)
&*(&pool.owned[pool.owned.len() - 1] as *const _ as *const PyObjectRef)
}
pub unsafe fn register_borrowed(_py: Python, obj: *mut ffi::PyObject) -> &PyObjectRef {
pub unsafe fn register_borrowed(_py: Python, obj: NonNull<ffi::PyObject>) -> &PyObjectRef {
let pool: &'static mut ReleasePool = &mut *POOL;
pool.borrowed.push(obj);
&*(&pool.borrowed[pool.borrowed.len() - 1] as *const *mut ffi::PyObject as *const PyObjectRef)
&*(&pool.borrowed[pool.borrowed.len() - 1] as *const _ as *const PyObjectRef)
}
impl GILGuard {
@ -280,7 +280,7 @@ impl GILGuard {
#[cfg(test)]
mod test {
use super::{GILPool, ReleasePool, POOL};
use super::{GILPool, ReleasePool, POOL, NonNull};
use crate::conversion::ToPyObject;
use crate::object::PyObject;
use crate::python::{Python, ToPyPointer};
@ -311,7 +311,7 @@ mod test {
empty = ffi::PyTuple_New(0);
cnt = ffi::Py_REFCNT(empty) - 1;
let _ = pythonrun::register_owned(py, empty);
let _ = pythonrun::register_owned(py, NonNull::new_unchecked(empty));
assert_eq!(p.owned.len(), 1);
}
@ -341,14 +341,15 @@ mod test {
// empty tuple is singleton
empty = ffi::PyTuple_New(0);
cnt = ffi::Py_REFCNT(empty) - 1;
let _ = pythonrun::register_owned(py, empty);
let _ = pythonrun::register_owned(py, NonNull::new_unchecked(empty));
assert_eq!(p.owned.len(), 1);
{
let _pool = GILPool::new();
let empty = ffi::PyTuple_New(0);
let _ = pythonrun::register_owned(py, empty);
let _ = pythonrun::register_owned(py, NonNull::new_unchecked(empty));
assert_eq!(p.owned.len(), 2);
}
assert_eq!(p.owned.len(), 1);
@ -376,7 +377,7 @@ mod test {
assert_eq!(p.borrowed.len(), 0);
cnt = ffi::Py_REFCNT(obj_ptr);
pythonrun::register_borrowed(py, obj_ptr);
pythonrun::register_borrowed(py, NonNull::new_unchecked(obj_ptr));
assert_eq!(p.borrowed.len(), 1);
assert_eq!(ffi::Py_REFCNT(obj_ptr), cnt);
@ -405,7 +406,7 @@ mod test {
assert_eq!(p.borrowed.len(), 0);
cnt = ffi::Py_REFCNT(obj_ptr);
pythonrun::register_borrowed(py, obj_ptr);
pythonrun::register_borrowed(py, NonNull::new_unchecked(obj_ptr));
assert_eq!(p.borrowed.len(), 1);
assert_eq!(ffi::Py_REFCNT(obj_ptr), cnt);
@ -413,7 +414,7 @@ mod test {
{
let _pool = GILPool::new();
assert_eq!(p.borrowed.len(), 1);
pythonrun::register_borrowed(py, obj_ptr);
pythonrun::register_borrowed(py, NonNull::new_unchecked(obj_ptr));
assert_eq!(p.borrowed.len(), 2);
}