gstreamer: Register only a single type instead of per return value for the gst::Iterator::filter() GValue

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1187>
This commit is contained in:
Sebastian Dröge 2023-01-07 16:46:38 +02:00 committed by GStreamer Marge Bot
parent f07727ee6d
commit 608cae3703

View file

@ -1,6 +1,6 @@
// Take a look at the license at the top of the repository in the LICENSE file. // Take a look at the license at the top of the repository in the LICENSE file.
use std::{ffi::CString, fmt, iter, marker::PhantomData, mem, ptr, sync::Arc}; use std::{any::Any, fmt, iter, marker::PhantomData, mem, ptr, sync::Arc};
use glib::{ use glib::{
ffi::{gconstpointer, gpointer}, ffi::{gconstpointer, gpointer},
@ -63,9 +63,8 @@ where
T: StaticType, T: StaticType,
{ {
unsafe { unsafe {
let func_box: Box<dyn Fn(T) -> bool + Send + Sync + 'static> = Box::new(func); let func_box: Box<dyn Any + Send + Sync + 'static> = Box::new(func);
let mut closure_value = let mut closure_value = glib::Value::from_type_unchecked(filter_boxed_get_type());
glib::Value::from_type_unchecked(from_glib(filter_boxed_get_type::<T>()));
glib::gobject_ffi::g_value_take_boxed( glib::gobject_ffi::g_value_take_boxed(
closure_value.to_glib_none_mut().0, closure_value.to_glib_none_mut().0,
Arc::into_raw(Arc::new(func_box)) as gpointer, Arc::into_raw(Arc::new(func_box)) as gpointer,
@ -73,7 +72,7 @@ where
from_glib_full(ffi::gst_iterator_filter( from_glib_full(ffi::gst_iterator_filter(
self.into_glib_ptr(), self.into_glib_ptr(),
Some(filter_trampoline::<T>), Some(filter_trampoline::<T, F>),
closure_value.to_glib_none().0, closure_value.to_glib_none().0,
)) ))
} }
@ -317,7 +316,10 @@ where
unsafe impl<T> Send for Iterator<T> {} unsafe impl<T> Send for Iterator<T> {}
unsafe impl<T> Sync for Iterator<T> {} unsafe impl<T> Sync for Iterator<T> {}
unsafe extern "C" fn filter_trampoline<T>(value: gconstpointer, func: gconstpointer) -> i32 unsafe extern "C" fn filter_trampoline<T: StaticType, F: Fn(T) -> bool + Send + Sync + 'static>(
value: gconstpointer,
func: gconstpointer,
) -> i32
where where
for<'a> T: FromValue<'a> + 'static, for<'a> T: FromValue<'a> + 'static,
{ {
@ -325,7 +327,8 @@ where
let func = func as *const glib::gobject_ffi::GValue; let func = func as *const glib::gobject_ffi::GValue;
let func = glib::gobject_ffi::g_value_get_boxed(func); let func = glib::gobject_ffi::g_value_get_boxed(func);
let func = &*(func as *const &(dyn Fn(T) -> bool + Send + Sync + 'static)); let func = &*(func as *const &(dyn Any + Send + Sync + 'static));
let func = func.downcast_ref::<F>().unwrap();
let value = &*(value as *const glib::Value); let value = &*(value as *const glib::Value);
let value = value.get::<T>().expect("Iterator filter_trampoline"); let value = value.get::<T>().expect("Iterator filter_trampoline");
@ -337,8 +340,8 @@ where
} }
} }
unsafe extern "C" fn filter_boxed_ref<T: 'static>(boxed: gpointer) -> gpointer { unsafe extern "C" fn filter_boxed_ref(boxed: gpointer) -> gpointer {
let boxed = Arc::from_raw(boxed as *const Box<dyn Fn(T) -> bool + Send + Sync + 'static>); let boxed = Arc::from_raw(boxed as *const Box<dyn Any + Send + Sync + 'static>);
let copy = Arc::clone(&boxed); let copy = Arc::clone(&boxed);
// Forget it and keep it alive, we will still need it later // Forget it and keep it alive, we will still need it later
@ -347,33 +350,22 @@ unsafe extern "C" fn filter_boxed_ref<T: 'static>(boxed: gpointer) -> gpointer {
Arc::into_raw(copy) as gpointer Arc::into_raw(copy) as gpointer
} }
unsafe extern "C" fn filter_boxed_unref<T: 'static>(boxed: gpointer) { unsafe extern "C" fn filter_boxed_unref(boxed: gpointer) {
let _ = Arc::from_raw(boxed as *const Box<dyn Fn(T) -> bool + Send + Sync + 'static>); let _ = Arc::from_raw(boxed as *const Box<dyn Any + Send + Sync + 'static>);
} }
unsafe extern "C" fn filter_boxed_get_type<T: StaticType + 'static>() -> glib::ffi::GType { unsafe extern "C" fn filter_boxed_get_type() -> glib::Type {
use std::{collections::HashMap, sync::Mutex}; use std::sync::Once;
use once_cell::sync::Lazy; static mut TYPE: glib::Type = glib::Type::INVALID;
static ONCE: Once = Once::new();
static mut TYPES: Lazy<Mutex<HashMap<String, glib::ffi::GType>>> = ONCE.call_once(|| {
Lazy::new(|| Mutex::new(HashMap::new()));
let mut types = TYPES.lock().unwrap();
let type_name = T::static_type().name();
if let Some(type_) = types.get(type_name) {
return *type_;
}
let type_ = {
let iter_type_name = { let iter_type_name = {
let mut idx = 0; let mut idx = 0;
loop { loop {
let iter_type_name = let iter_type_name = glib::gformat!("GstRsIteratorFilterBoxed-{}", idx);
CString::new(format!("GstRsIteratorFilterBoxed-{}-{}", type_name, idx))
.unwrap();
if glib::gobject_ffi::g_type_from_name(iter_type_name.as_ptr()) if glib::gobject_ffi::g_type_from_name(iter_type_name.as_ptr())
== glib::gobject_ffi::G_TYPE_INVALID == glib::gobject_ffi::G_TYPE_INVALID
{ {
@ -383,20 +375,16 @@ unsafe extern "C" fn filter_boxed_get_type<T: StaticType + 'static>() -> glib::f
} }
}; };
let type_ = glib::gobject_ffi::g_boxed_type_register_static( TYPE = from_glib(glib::gobject_ffi::g_boxed_type_register_static(
iter_type_name.as_ptr(), iter_type_name.as_ptr(),
Some(filter_boxed_ref::<T>), Some(filter_boxed_ref),
Some(filter_boxed_unref::<T>), Some(filter_boxed_unref),
); ));
assert_ne!(type_, glib::gobject_ffi::G_TYPE_INVALID); assert!(TYPE.is_valid());
});
type_ TYPE
};
types.insert(String::from(type_name), type_);
type_
} }
unsafe extern "C" fn find_trampoline<T, F: FnMut(T) -> bool>( unsafe extern "C" fn find_trampoline<T, F: FnMut(T) -> bool>(