mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-11-29 04:51:09 +00:00
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:
parent
f07727ee6d
commit
608cae3703
1 changed files with 27 additions and 39 deletions
|
@ -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>(
|
||||||
|
|
Loading…
Reference in a new issue