2015-01-05 16:05:53 +00:00
|
|
|
use ffi;
|
|
|
|
|
2015-01-04 04:50:28 +00:00
|
|
|
use std::sync::{Once, ONCE_INIT};
|
|
|
|
use std::thread::Thread;
|
2015-01-05 16:05:53 +00:00
|
|
|
|
2015-01-04 04:50:28 +00:00
|
|
|
static START: Once = ONCE_INIT;
|
2015-01-05 16:05:53 +00:00
|
|
|
|
2015-01-04 04:50:28 +00:00
|
|
|
/// Prepares the use of python in a free-threaded context.
|
|
|
|
pub fn prepare_freethreaded_python() {
|
2015-01-04 19:11:18 +00:00
|
|
|
// 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.
|
2015-01-04 04:50:28 +00:00
|
|
|
START.call_once(|| unsafe {
|
2015-01-04 19:11:18 +00:00
|
|
|
if ffi::Py_IsInitialized() != 0 {
|
|
|
|
// If python is already initialized, we expect python threading to also be initialized,
|
|
|
|
// as we can't make the existing python main thread acquire the GIL.
|
|
|
|
assert!(ffi::PyEval_ThreadsInitialized() != 0);
|
|
|
|
} 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
|
2015-01-04 04:50:28 +00:00
|
|
|
// (it's not acquired in the other code paths)
|
2015-01-04 19:11:18 +00:00
|
|
|
// 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.
|
2015-01-04 04:50:28 +00:00
|
|
|
}
|
|
|
|
});
|
2015-01-05 16:05:53 +00:00
|
|
|
}
|
|
|
|
|
2015-01-04 19:11:18 +00:00
|
|
|
|