From a021aaa3ce60ecbf8cf48a808bc2db18c6a55ed6 Mon Sep 17 00:00:00 2001 From: Anders Hellerup Madsen Date: Sun, 5 Feb 2023 17:55:32 +0100 Subject: [PATCH] gstreamer: Add object_lock method to gst::Object See https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/issues/439 Part-of: --- gstreamer/src/lib.rs | 1 + gstreamer/src/object.rs | 7 +++++ gstreamer/src/utils.rs | 70 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index d94885d6f..992f78d72 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -252,6 +252,7 @@ pub mod functions; pub use crate::functions::*; mod utils; +pub use crate::utils::ObjectLockGuard; #[cfg(any(feature = "v1_18", feature = "dox"))] mod gtype; diff --git a/gstreamer/src/object.rs b/gstreamer/src/object.rs index e308a3028..27edc9afa 100644 --- a/gstreamer/src/object.rs +++ b/gstreamer/src/object.rs @@ -28,6 +28,8 @@ pub trait GstObjectExtManual: 'static { interval: ClockTime, values: &mut [glib::Value], ) -> Result<(), glib::error::BoolError>; + + fn object_lock(&self) -> crate::utils::ObjectLockGuard; } impl> GstObjectExtManual for O { @@ -118,6 +120,11 @@ impl> GstObjectExtManual for O { ) } } + + #[inline] + fn object_lock(&self) -> crate::utils::ObjectLockGuard { + crate::utils::ObjectLockGuard::acquire(self) + } } #[cfg(test)] diff --git a/gstreamer/src/utils.rs b/gstreamer/src/utils.rs index 6bccef1b0..6231f37aa 100644 --- a/gstreamer/src/utils.rs +++ b/gstreamer/src/utils.rs @@ -35,3 +35,73 @@ pub trait Displayable { fn display(self) -> Self::DisplayImpl; } + +#[must_use = "if unused the object lock will immediately be released"] +pub struct ObjectLockGuard<'a, T: ?Sized> { + obj: &'a T, + mutex: &'a mut glib::ffi::GMutex, +} + +impl<'a, T> ObjectLockGuard<'a, T> +where + T: glib::IsA + ?Sized, +{ + #[inline] + pub fn acquire(obj: &'a T) -> ObjectLockGuard<'a, T> { + skip_assert_initialized!(); + unsafe { + use glib::ObjectType; + let mutex = &mut (*obj.as_ref().as_ptr()).lock; + glib::ffi::g_mutex_lock(mutex); + Self { obj, mutex } + } + } +} + +impl AsRef for ObjectLockGuard<'_, T> { + #[inline] + fn as_ref(&self) -> &T { + self.obj + } +} + +impl std::ops::Deref for ObjectLockGuard<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + self.obj + } +} + +impl std::fmt::Debug for ObjectLockGuard<'_, T> +where + T: std::fmt::Debug, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.obj.fmt(f) + } +} + +impl std::cmp::PartialEq for ObjectLockGuard<'_, T> +where + T: std::cmp::PartialEq, +{ + fn eq(&self, other: &Self) -> bool { + self.obj.eq(other) + } +} + +impl std::cmp::Eq for ObjectLockGuard<'_, T> where T: std::cmp::Eq {} + +impl Drop for ObjectLockGuard<'_, T> +where + T: ?Sized, +{ + #[inline] + fn drop(&mut self) { + unsafe { + glib::ffi::g_mutex_unlock(self.mutex); + } + } +}