Skip to content

Commit

Permalink
update rust API for PyMutex bindings following code review
Browse files Browse the repository at this point in the history
  • Loading branch information
ngoldbaum committed Sep 17, 2024
1 parent b1afb8b commit b3d193b
Showing 1 changed file with 22 additions and 15 deletions.
37 changes: 22 additions & 15 deletions src/types/mutex.rs
Original file line number Diff line number Diff line change
@@ -1,49 +1,56 @@
use std::ops::Deref;
use std::cell::UnsafeCell;
use std::ops::{Deref, DerefMut};

/// Wrapper for [`PyMutex`](https://docs.python.org/3/c-api/init.html#c.PyMutex) exposing an RAII interface.
/// Wrapper for [`PyMutex`](https://docs.python.org/3/c-api/init.html#c.PyMutex), exposing an RAII guard interface similar to `std::sync::Mutex`.
#[derive(Debug)]
pub struct PyMutex<T> {
_mutex: crate::ffi::PyMutex,
data: T,
_mutex: UnsafeCell<crate::ffi::PyMutex>,
data: UnsafeCell<T>,
}

/// RAII guard to handle releasing a PyMutex lock.
#[derive(Debug)]
pub struct PyMutexGuard<'a, T> {
_mutex: &'a mut crate::ffi::PyMutex,
data: &'a T,
mutex: &'a mut PyMutex<T>,
}

impl<T> PyMutex<T> {
/// Acquire the mutex, blocking the current thread until it is able to do so.
pub fn lock(&mut self) -> PyMutexGuard<'_, T> {
unsafe { crate::ffi::PyMutex_Lock(&mut self._mutex) };
PyMutexGuard {
_mutex: &mut self._mutex,
data: &self.data,
}
unsafe { crate::ffi::PyMutex_Lock(self._mutex.get_mut()) };
PyMutexGuard { mutex: &mut *self }
}

/// Create a new mutex in an unlocked state ready for use.
pub fn new(value: T) -> Self {
Self {
_mutex: crate::ffi::PyMutex::new(),
data: value,
_mutex: UnsafeCell::new(crate::ffi::PyMutex::new()),
data: UnsafeCell::new(value),
}
}
}

impl<'a, T> Drop for PyMutexGuard<'a, T> {
fn drop(&mut self) {
unsafe { crate::ffi::PyMutex_Unlock(self._mutex) };
unsafe { crate::ffi::PyMutex_Unlock(self.mutex._mutex.get_mut()) };
}
}

impl<'a, T> Deref for PyMutexGuard<'a, T> {
type Target = T;

fn deref(&self) -> &T {
self.data
// safety: cannot be null pointer because PyMutexGuard::new always
// creates a valid PyMutex pointer
unsafe { &*self.mutex.data.get() }
}
}

impl<'a, T> DerefMut for PyMutexGuard<'a, T> {
fn deref_mut(&mut self) -> &mut T {
// safety: cannot be null pointer because PyMutexGuard::new always
// creates a valid PyMutex pointer
self.mutex.data.get_mut()
}
}

Expand Down

0 comments on commit b3d193b

Please sign in to comment.