-
Notifications
You must be signed in to change notification settings - Fork 784
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This module contains `ModuleState`, a struct used to represent state that lies on the per-module memory region of a Python module, as well as various exported functions that are used to integrate `ModuleState` with the Python interpreter. This commit does not implement any further functionality (such as actually representing any kind of state) and is instead more of a blank slate for further additions. Signed-off-by: Max Carrara <[email protected]>
- Loading branch information
Showing
2 changed files
with
93 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
use std::ffi::{c_int, c_void}; | ||
use std::ptr::NonNull; | ||
|
||
use crate::ffi; | ||
|
||
/// Represents a Python module's state. | ||
/// | ||
/// More precisely, this `struct` resides on the per-module memory area | ||
/// allocated during the module's creation. | ||
#[repr(C)] | ||
#[derive(Debug)] | ||
pub struct ModuleState { | ||
inner: Option<NonNull<ModuleStateImpl>>, | ||
} | ||
|
||
impl ModuleState { | ||
pub fn new() -> Self { | ||
let boxed = Box::new(ModuleStateImpl::new()); | ||
|
||
Self { | ||
inner: NonNull::new(Box::into_raw(boxed)), | ||
} | ||
} | ||
} | ||
|
||
/// Inner layout of [`ModuleState`]. | ||
/// | ||
/// In order to guarantee that all resources acquired during the initialization | ||
/// of per-module state are correctly released, this `struct` exists as the sole | ||
/// field of [`ModuleState`] in the form of a pointer. This allows | ||
/// [`module_state_free`] to safely [`drop`] this `struct` when [`ModuleState`] | ||
/// is being deallocated by the Python interpreter. | ||
#[repr(C)] | ||
#[derive(Debug)] | ||
struct ModuleStateImpl {} | ||
|
||
impl ModuleStateImpl { | ||
fn new() -> Self { | ||
Self {} | ||
} | ||
} | ||
|
||
/// Called during multi-phase initialization in order to create an instance of | ||
/// [`ModuleState`] on the memory area specific to modules. | ||
/// | ||
/// Slot: [Py_mod_exec] | ||
/// | ||
/// [Py_mod_exec]: https://docs.python.org/3/c-api/module.html#c.Py_mod_exec | ||
pub unsafe extern "C" fn module_state_init(module: *mut ffi::PyObject) -> c_int { | ||
let state: *mut ModuleState = ffi::PyModule_GetState(module.cast()).cast(); | ||
*state = ModuleState::new(); | ||
|
||
0 | ||
} | ||
|
||
/// Called during GC traversal of the module object. | ||
/// | ||
/// Used for the [`m_traverse`] field of [`PyModuleDef`]. | ||
/// | ||
/// [`m_traverse`]: https://docs.python.org/3/c-api/module.html#c.PyModuleDef.m_traverse | ||
/// [`PyModuleDef`]: https://docs.python.org/3/c-api/module.html#c.PyModuleDef | ||
pub unsafe extern "C" fn module_state_traverse( | ||
_module: *mut ffi::PyObject, | ||
_visit: ffi::visitproc, | ||
_arg: *mut c_void, | ||
) -> c_int { | ||
0 | ||
} | ||
|
||
/// Called during GC clearing of the module object. | ||
/// | ||
/// Used for the [`m_clear`] field of [`PyModuleDef`]. | ||
/// | ||
/// [`m_clear`]: https://docs.python.org/3/c-api/module.html#c.PyModuleDef.m_clear | ||
/// [`PyModuleDef`]: https://docs.python.org/3/c-api/module.html#c.PyModuleDef | ||
pub unsafe extern "C" fn module_state_clear(_module: *mut ffi::PyObject) -> c_int { | ||
// Should any PyObjects be made part of ModuleState or ModuleStateInner, | ||
// these have to be Py_CLEARed here. | ||
// See: examples/sequential/src/module.rs | ||
0 | ||
} | ||
|
||
/// Called during deallocation of the module object. | ||
/// | ||
/// Used for the [`m_free`] field of [`PyModuleDef`]. | ||
/// | ||
/// [`m_free`]: https://docs.python.org/3/c-api/module.html#c.PyModuleDef.m_free | ||
/// [`PyModuleDef`]: https://docs.python.org/3/c-api/module.html#c.PyModuleDef | ||
pub unsafe extern "C" fn module_state_free(module: *mut c_void) { | ||
let state: *mut ModuleState = ffi::PyModule_GetState(module.cast()).cast(); | ||
(*state).inner.map(drop); | ||
} |