gstreamer/iterator: Store filter types in a hash table

Static variables in generic functions only exist once and not once per
type parameter, so before we were only able to register exactly one
filter type.
This commit is contained in:
Sebastian Dröge 2020-06-04 12:35:11 +03:00
parent 9b4117ea71
commit 22113dc9cb

View file

@ -358,38 +358,51 @@ unsafe extern "C" fn filter_boxed_unref<T: 'static>(boxed: gpointer) {
} }
unsafe extern "C" fn filter_boxed_get_type<T: StaticType + 'static>() -> glib_sys::GType { unsafe extern "C" fn filter_boxed_get_type<T: StaticType + 'static>() -> glib_sys::GType {
use std::sync::Once; use once_cell::sync::Lazy;
use std::collections::HashMap;
use std::sync::Mutex;
static mut TYPE: glib_sys::GType = gobject_sys::G_TYPE_INVALID; static mut TYPES: Lazy<Mutex<HashMap<String, glib_sys::GType>>> =
static ONCE: Once = Once::new(); Lazy::new(|| Mutex::new(HashMap::new()));
ONCE.call_once(|| { let mut types = TYPES.lock().unwrap();
let type_name = { let type_name = T::static_type().name();
if let Some(type_) = types.get(&type_name) {
return *type_;
}
let type_ = {
let iter_type_name = {
let mut idx = 0; let mut idx = 0;
loop { loop {
let type_name = CString::new(format!( let iter_type_name =
"GstRsIteratorFilterBoxed-{}-{}", CString::new(format!("GstRsIteratorFilterBoxed-{}-{}", type_name, idx))
T::static_type().name(), .unwrap();
idx if gobject_sys::g_type_from_name(iter_type_name.as_ptr())
)) == gobject_sys::G_TYPE_INVALID
.unwrap();
if gobject_sys::g_type_from_name(type_name.as_ptr()) == gobject_sys::G_TYPE_INVALID
{ {
break type_name; break iter_type_name;
} }
idx += 1; idx += 1;
} }
}; };
TYPE = gobject_sys::g_boxed_type_register_static( let type_ = gobject_sys::g_boxed_type_register_static(
type_name.as_ptr(), iter_type_name.as_ptr(),
Some(filter_boxed_ref::<T>), Some(filter_boxed_ref::<T>),
Some(filter_boxed_unref::<T>), Some(filter_boxed_unref::<T>),
); );
});
TYPE assert_ne!(type_, gobject_sys::G_TYPE_INVALID);
type_
};
types.insert(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>(