Use Unsendable alias instead of Phantomdata<Rc<()>>

This commit is contained in:
kngwyu 2019-10-27 18:03:01 +09:00
parent fe229753fb
commit 7977fe68e2
4 changed files with 25 additions and 18 deletions

View File

@ -3,11 +3,12 @@
//! Interaction with python's global interpreter lock //! Interaction with python's global interpreter lock
use crate::ffi; use crate::ffi;
use crate::internal_tricks::Unsendable;
use crate::types::PyAny; use crate::types::PyAny;
use crate::Python; use crate::Python;
use spin; use spin;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::{any, marker, rc, sync}; use std::{any, sync};
static START: sync::Once = sync::Once::new(); static START: sync::Once = sync::Once::new();
static START_PYO3: sync::Once = sync::Once::new(); static START_PYO3: sync::Once = sync::Once::new();
@ -101,9 +102,8 @@ pub struct GILGuard {
owned: usize, owned: usize,
borrowed: usize, borrowed: usize,
gstate: ffi::PyGILState_STATE, gstate: ffi::PyGILState_STATE,
// hack to opt out of Send on stable rust, which doesn't // Stable solution for impl !Send
// have negative impls no_send: Unsendable,
no_send: marker::PhantomData<rc::Rc<()>>,
} }
/// The Drop implementation for `GILGuard` will release the GIL. /// The Drop implementation for `GILGuard` will release the GIL.
@ -181,7 +181,7 @@ pub struct GILPool<'p> {
owned: usize, owned: usize,
borrowed: usize, borrowed: usize,
pointers: bool, pointers: bool,
no_send: marker::PhantomData<rc::Rc<()>>, no_send: Unsendable,
} }
impl<'p> GILPool<'p> { impl<'p> GILPool<'p> {
@ -193,7 +193,7 @@ impl<'p> GILPool<'p> {
owned: p.owned.len(), owned: p.owned.len(),
borrowed: p.borrowed.len(), borrowed: p.borrowed.len(),
pointers: true, pointers: true,
no_send: marker::PhantomData, no_send: Unsendable::default(),
} }
} }
#[inline] #[inline]
@ -204,7 +204,7 @@ impl<'p> GILPool<'p> {
owned: p.owned.len(), owned: p.owned.len(),
borrowed: p.borrowed.len(), borrowed: p.borrowed.len(),
pointers: false, pointers: false,
no_send: marker::PhantomData, no_send: Unsendable::default(),
} }
} }
} }
@ -260,7 +260,7 @@ impl GILGuard {
owned: pool.owned.len(), owned: pool.owned.len(),
borrowed: pool.borrowed.len(), borrowed: pool.borrowed.len(),
gstate, gstate,
no_send: marker::PhantomData, no_send: Unsendable::default(),
} }
} }
} }

View File

@ -2,6 +2,7 @@
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::gil; use crate::gil;
use crate::instance; use crate::instance;
use crate::internal_tricks::Unsendable;
use crate::object::PyObject; use crate::object::PyObject;
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;
use crate::type_object::PyTypeCreate; use crate::type_object::PyTypeCreate;
@ -13,7 +14,6 @@ use std::marker::PhantomData;
use std::mem; use std::mem;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::ptr::NonNull; use std::ptr::NonNull;
use std::rc::Rc;
/// Types that are built into the python interpreter. /// Types that are built into the python interpreter.
/// ///
@ -55,7 +55,7 @@ pub unsafe trait PyNativeType: Sized {
/// py.run("assert p.length() == 12", None, Some(d)).unwrap(); /// py.run("assert p.length() == 12", None, Some(d)).unwrap();
/// ``` /// ```
#[derive(Debug)] #[derive(Debug)]
pub struct PyRef<'a, T: PyTypeInfo>(&'a T, PhantomData<Rc<()>>); pub struct PyRef<'a, T: PyTypeInfo>(&'a T, Unsendable);
#[allow(clippy::cast_ptr_alignment)] #[allow(clippy::cast_ptr_alignment)]
fn ref_to_ptr<T>(t: &T) -> *mut ffi::PyObject fn ref_to_ptr<T>(t: &T) -> *mut ffi::PyObject
@ -67,7 +67,7 @@ where
impl<'a, T: PyTypeInfo> PyRef<'a, T> { impl<'a, T: PyTypeInfo> PyRef<'a, T> {
pub(crate) fn from_ref(r: &'a T) -> Self { pub(crate) fn from_ref(r: &'a T) -> Self {
PyRef(r, PhantomData) PyRef(r, Unsendable::default())
} }
} }
@ -143,11 +143,11 @@ where
/// py.run("assert p.length() == 100", None, Some(d)).unwrap(); /// py.run("assert p.length() == 100", None, Some(d)).unwrap();
/// ``` /// ```
#[derive(Debug)] #[derive(Debug)]
pub struct PyRefMut<'a, T: PyTypeInfo>(&'a mut T, PhantomData<Rc<()>>); pub struct PyRefMut<'a, T: PyTypeInfo>(&'a mut T, Unsendable);
impl<'a, T: PyTypeInfo> PyRefMut<'a, T> { impl<'a, T: PyTypeInfo> PyRefMut<'a, T> {
pub(crate) fn from_mut(t: &'a mut T) -> Self { pub(crate) fn from_mut(t: &'a mut T) -> Self {
PyRefMut(t, PhantomData) PyRefMut(t, Unsendable::default())
} }
} }
@ -267,7 +267,7 @@ pub trait AsPyRef<T: PyTypeInfo>: Sized {
/// `Py<T>` is thread-safe, because any python related operations require a Python<'p> token. /// `Py<T>` is thread-safe, because any python related operations require a Python<'p> token.
#[derive(Debug)] #[derive(Debug)]
#[repr(transparent)] #[repr(transparent)]
pub struct Py<T>(NonNull<ffi::PyObject>, std::marker::PhantomData<T>); pub struct Py<T>(NonNull<ffi::PyObject>, PhantomData<T>);
unsafe impl<T> Send for Py<T> {} unsafe impl<T> Send for Py<T> {}
@ -295,7 +295,7 @@ impl<T> Py<T> {
!ptr.is_null() && ffi::Py_REFCNT(ptr) > 0, !ptr.is_null() && ffi::Py_REFCNT(ptr) > 0,
format!("REFCNT: {:?} - {:?}", ptr, ffi::Py_REFCNT(ptr)) format!("REFCNT: {:?} - {:?}", ptr, ffi::Py_REFCNT(ptr))
); );
Py(NonNull::new_unchecked(ptr), std::marker::PhantomData) Py(NonNull::new_unchecked(ptr), PhantomData)
} }
/// Creates a `Py<T>` instance for the given FFI pointer. /// Creates a `Py<T>` instance for the given FFI pointer.
@ -304,7 +304,7 @@ impl<T> Py<T> {
#[inline] #[inline]
pub unsafe fn from_owned_ptr_or_panic(ptr: *mut ffi::PyObject) -> Py<T> { pub unsafe fn from_owned_ptr_or_panic(ptr: *mut ffi::PyObject) -> Py<T> {
match NonNull::new(ptr) { match NonNull::new(ptr) {
Some(nonnull_ptr) => Py(nonnull_ptr, std::marker::PhantomData), Some(nonnull_ptr) => Py(nonnull_ptr, PhantomData),
None => { None => {
crate::err::panic_after_error(); crate::err::panic_after_error();
} }
@ -317,7 +317,7 @@ impl<T> Py<T> {
/// Unsafe because the pointer might be invalid. /// Unsafe because the pointer might be invalid.
pub unsafe fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<Py<T>> { pub unsafe fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<Py<T>> {
match NonNull::new(ptr) { match NonNull::new(ptr) {
Some(nonnull_ptr) => Ok(Py(nonnull_ptr, std::marker::PhantomData)), Some(nonnull_ptr) => Ok(Py(nonnull_ptr, PhantomData)),
None => Err(PyErr::fetch(py)), None => Err(PyErr::fetch(py)),
} }
} }
@ -332,7 +332,7 @@ impl<T> Py<T> {
format!("REFCNT: {:?} - {:?}", ptr, ffi::Py_REFCNT(ptr)) format!("REFCNT: {:?} - {:?}", ptr, ffi::Py_REFCNT(ptr))
); );
ffi::Py_INCREF(ptr); ffi::Py_INCREF(ptr);
Py(NonNull::new_unchecked(ptr), std::marker::PhantomData) Py(NonNull::new_unchecked(ptr), PhantomData)
} }
/// Gets the reference count of the ffi::PyObject pointer. /// Gets the reference count of the ffi::PyObject pointer.

6
src/internal_tricks.rs Normal file
View File

@ -0,0 +1,6 @@
use std::marker::PhantomData;
use std::rc::Rc;
/// A marker type that makes the type !Send.
/// Temporal hack until https://github.com/rust-lang/rust/issues/13231 is resolved.
pub(crate) type Unsendable = PhantomData<Rc<()>>;

View File

@ -161,6 +161,7 @@ pub mod exceptions;
pub mod freelist; pub mod freelist;
mod gil; mod gil;
mod instance; mod instance;
mod internal_tricks;
pub mod marshal; pub mod marshal;
mod object; mod object;
mod objectprotocol; mod objectprotocol;