Skip to content

Commit

Permalink
Add send feature to make Image implement Send
Browse files Browse the repository at this point in the history
This uses a global mutex when ref counts are changed, which should
prevent data races, as long as `&mut` prevent other mutation.
  • Loading branch information
ids1024 committed Dec 3, 2024
1 parent 89ab367 commit c15b587
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 0 deletions.
1 change: 1 addition & 0 deletions pixman/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ image = "0.24.7"
[features]
default = []
drm-fourcc = ["dep:drm-fourcc"]
send = []
14 changes: 14 additions & 0 deletions pixman/src/image/bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ pub struct Image<'bits, 'alpha> {
_alpha: PhantomData<&'alpha ()>,
}

// SAFETY: A reference to the image is only created by `set_alpha_map`.
// Which returns a type with a lifetime bound, so `&mut self` methods cannot
// be called while this additional reference is in use.
//
// Thus the only mutability allowed is reference counting, which is made
// thread-safe with the `REF_COUNT_LOCK` mutex, used when calling
// `pixman_image_unref`, or `pixman_image_set_alpha_map`.
#[cfg(feature = "send")]
unsafe impl<'bits, 'alpha> Send for Image<'bits, 'alpha> {}

impl<'bits, 'alpha> std::ops::Deref for Image<'bits, 'alpha> {
type Target = ImageRef;

Expand Down Expand Up @@ -140,6 +150,8 @@ impl<'bits, 'a> Image<'bits, 'a> {
x: i16,
y: i16,
) -> Image<'bits, 'alpha> {
#[cfg(feature = "send")]
let _lock = crate::REF_COUNT_LOCK.lock().unwrap();
unsafe {
ffi::pixman_image_set_alpha_map(self.as_ptr(), alpha_map.as_ptr(), x, y);
}
Expand All @@ -152,6 +164,8 @@ impl<'bits, 'a> Image<'bits, 'a> {

/// Clear a previously set alpha map
pub fn clear_alpha_map(self) -> Image<'bits, 'static> {
#[cfg(feature = "send")]
let _lock = crate::REF_COUNT_LOCK.lock().unwrap();
unsafe {
ffi::pixman_image_set_alpha_map(self.as_ptr(), std::ptr::null_mut(), 0, 0);
}
Expand Down
6 changes: 6 additions & 0 deletions pixman/src/image/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ impl ImageRef {

impl Drop for ImageRef {
fn drop(&mut self) {
#[cfg(feature = "send")]
let _lock = crate::REF_COUNT_LOCK.lock().unwrap();
unsafe {
ffi::pixman_image_unref(self.0);
}
Expand All @@ -197,6 +199,8 @@ macro_rules! image_type {
x: i16,
y: i16,
) -> $name<'alpha> {
#[cfg(feature = "send")]
let _lock = $crate::REF_COUNT_LOCK.lock().unwrap();
unsafe {
$crate::ffi::pixman_image_set_alpha_map(
self.as_ptr(),
Expand All @@ -213,6 +217,8 @@ macro_rules! image_type {

/// Clear a previously set alpha map
pub fn clear_alpha_map(self) -> $name<'static> {
#[cfg(feature = "send")]
let _lock = $crate::REF_COUNT_LOCK.lock().unwrap();
unsafe {
$crate::ffi::pixman_image_set_alpha_map(
self.as_ptr(),
Expand Down
3 changes: 3 additions & 0 deletions pixman/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ pub use vector::*;
#[error("The requested operation failed")]
pub struct OperationFailed;

#[cfg(feature = "send")]
static REF_COUNT_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());

/// Blit the src into the dst with the specified values
#[allow(clippy::too_many_arguments)]
pub fn blit(
Expand Down

0 comments on commit c15b587

Please sign in to comment.