Fix threading
This commit is contained in:
parent
335913e273
commit
61acf98aec
|
@ -79,9 +79,9 @@ impl <'p, 's, T : PythonObject<'p>> ToPyObject<'p, 's> for T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'p, 'a, T : PythonObject<'p>> FromPyObject<'p, 'a> for &'a T {
|
impl <'p, 's, T : PythonObject<'p>> FromPyObject<'p, 's> for &'s T {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_py_object(s: &'a PyObject<'p>) -> PyResult<'p, &'a T> {
|
fn from_py_object(s: &'s PyObject<'p>) -> PyResult<'p, &'s T> {
|
||||||
s.downcast()
|
s.downcast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,23 +100,24 @@ impl <'p, 's, T : PythonObject<'p>> ToPyObject<'p, 's> for PyPtr<'p, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'p, 'a, T : PythonObject<'p>> FromPyObject<'p, 'a> for PyPtr<'p, T> {
|
impl <'p, 's, T : PythonObject<'p>> FromPyObject<'p, 's> for PyPtr<'p, T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_py_object(s : &'a PyObject<'p>) -> PyResult<'p, PyPtr<'p, T>> {
|
fn from_py_object(s : &'s PyObject<'p>) -> PyResult<'p, PyPtr<'p, T>> {
|
||||||
PyPtr::new(s).downcast_into()
|
PyPtr::new(s).downcast_into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// bool
|
// bool
|
||||||
|
|
||||||
/*
|
|
||||||
impl <'p, T : PythonObject<'p>> ToPyObject<'p> for bool {
|
impl <'p, 's> ToPyObject<'p, 's> for bool {
|
||||||
type PointerType = &'p PyObject<'p>;
|
type PointerType = &'p PyObject<'p>;
|
||||||
|
|
||||||
fn to_py_object(&self, py: Python<'p>) -> PyResult<'p, Self::PointerType>;
|
#[inline]
|
||||||
if *self { py.True() } else { py.False() }
|
fn to_py_object(&'s self, py: Python<'p>) -> PyResult<'p, &'p PyObject<'p>> {
|
||||||
|
Ok(if *self { py.True() } else { py.False() })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
impl <'p, 'a> FromPyObject<'p, 'a> for bool {
|
impl <'p, 'a> FromPyObject<'p, 'a> for bool {
|
||||||
fn from_py_object(s: &'a PyObject<'p>) -> PyResult<'p, bool> {
|
fn from_py_object(s: &'a PyObject<'p>) -> PyResult<'p, bool> {
|
||||||
|
|
|
@ -91,7 +91,6 @@ pub fn error_on_minusone(py : Python, result : libc::c_int) -> PyResult<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[allow(experimental)]
|
|
||||||
mod tests {
|
mod tests {
|
||||||
use {Python, PyType, PyErr};
|
use {Python, PyType, PyErr};
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#![allow(unused_imports, dead_code, unused_variables)]
|
#![allow(unused_imports, dead_code, unused_variables)]
|
||||||
#![feature(associated_types)]
|
#![feature(associated_types)]
|
||||||
#![feature(globs)]
|
#![feature(globs)]
|
||||||
|
#![feature(slicing_syntax)]
|
||||||
|
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate "libpython27-sys" as ffi;
|
extern crate "libpython27-sys" as ffi;
|
||||||
|
|
|
@ -7,15 +7,34 @@ static START: Once = ONCE_INIT;
|
||||||
|
|
||||||
/// Prepares the use of python in a free-threaded context.
|
/// Prepares the use of python in a free-threaded context.
|
||||||
pub fn prepare_freethreaded_python() {
|
pub fn prepare_freethreaded_python() {
|
||||||
|
// Protect against race conditions when python is not yet initialized
|
||||||
|
// and multiple threads concurrently call 'prepare_freethreaded_python()'.
|
||||||
|
// Note that we do not protect against concurrent initialization of the python runtime
|
||||||
|
// by other users of the python C API.
|
||||||
START.call_once(|| unsafe {
|
START.call_once(|| unsafe {
|
||||||
::ffi::Py_InitializeEx(0);
|
if ffi::Py_IsInitialized() != 0 {
|
||||||
if ::ffi::PyEval_ThreadsInitialized() == 0 {
|
// If python is already initialized, we expect python threading to also be initialized,
|
||||||
::ffi::PyEval_InitThreads();
|
// as we can't make the existing python main thread acquire the GIL.
|
||||||
// InitThreads() will acquire the GIL,
|
assert!(ffi::PyEval_ThreadsInitialized() != 0);
|
||||||
// but we don't want to acquire it at this point
|
} else {
|
||||||
|
// If python isn't initialized yet, we expect that python threading isn't initialized either.
|
||||||
|
assert!(ffi::PyEval_ThreadsInitialized() == 0);
|
||||||
|
// Initialize python.
|
||||||
|
// We use Py_InitializeEx() with initsigs=0 to disable Python signal handling.
|
||||||
|
// Signal handling depends on the notion of a 'main thread', which doesn't exist in this case.
|
||||||
|
// Note that the 'main thread' notion in python isn't documented properly;
|
||||||
|
// and running python without one is not officially supported.
|
||||||
|
ffi::Py_InitializeEx(0);
|
||||||
|
ffi::PyEval_InitThreads();
|
||||||
|
// PyEval_InitThreads() will acquire the GIL,
|
||||||
|
// but we don't want to hold it at this point
|
||||||
// (it's not acquired in the other code paths)
|
// (it's not acquired in the other code paths)
|
||||||
::ffi::PyEval_ReleaseLock();
|
// So immediately release the GIL:
|
||||||
|
let _thread_state = ffi::PyEval_SaveThread();
|
||||||
|
// Note that the PyThreadState returned by PyEval_SaveThread is also held in TLS by the python runtime,
|
||||||
|
// and will be restored by PyGILState_Ensure.
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue