mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-11-22 01:21:05 +00:00
validate: Give a mutable reference to the action in the execute function
We need to be able to keep a reference to the action when we implement async action types so now we can do `action.clone()` and get a hard reference to it. We also need to be able to mutate the structure, it is possible to `get_mut()` on it, get a mutable reference to the structure. There was a bug in the test where we were using a ref to the wrong action object in the async signal which is why we didn't detect the problem. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1586>
This commit is contained in:
parent
5fccc0bc82
commit
d8a3784b74
3 changed files with 50 additions and 21 deletions
|
@ -47,6 +47,22 @@ impl ActionRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Action {
|
impl Action {
|
||||||
|
pub(crate) unsafe fn from_glib_ptr_borrow_mut(
|
||||||
|
ptr: &mut *mut ffi::GstValidateAction,
|
||||||
|
) -> &mut Self {
|
||||||
|
assert_initialized_main_thread!();
|
||||||
|
|
||||||
|
debug_assert_eq!((*(*ptr)).mini_object.refcount, 1);
|
||||||
|
|
||||||
|
debug_assert_eq!(
|
||||||
|
std::mem::size_of::<Action>(),
|
||||||
|
std::mem::size_of::<gst::glib::ffi::gpointer>()
|
||||||
|
);
|
||||||
|
debug_assert!(!ptr.is_null());
|
||||||
|
|
||||||
|
&mut *(ptr as *mut *mut ffi::GstValidateAction as *mut Action)
|
||||||
|
}
|
||||||
|
|
||||||
#[doc(alias = "gst_validate_action_new")]
|
#[doc(alias = "gst_validate_action_new")]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
scenario: Option<&impl IsA<Scenario>>,
|
scenario: Option<&impl IsA<Scenario>>,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{ffi::c_int, ptr};
|
use std::{ffi::c_int, ptr};
|
||||||
|
|
||||||
use crate::ffi;
|
use crate::{ffi, Action};
|
||||||
use glib::{object::Cast, translate::*};
|
use glib::translate::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
@ -176,7 +176,7 @@ impl<'a> ActionParameterBuilder<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActionFunction = dyn Fn(&crate::Scenario, &mut crate::ActionRef) -> Result<crate::ActionSuccess, crate::ActionError>
|
type ActionFunction = dyn Fn(&crate::Scenario, &mut crate::Action) -> Result<crate::ActionSuccess, crate::ActionError>
|
||||||
+ Sync
|
+ Sync
|
||||||
+ Send
|
+ Send
|
||||||
+ 'static;
|
+ 'static;
|
||||||
|
@ -198,7 +198,7 @@ impl<'a> ActionTypeBuilder<'a> {
|
||||||
pub fn new<
|
pub fn new<
|
||||||
F: Fn(
|
F: Fn(
|
||||||
&crate::Scenario,
|
&crate::Scenario,
|
||||||
&mut crate::ActionRef,
|
&mut crate::Action,
|
||||||
) -> Result<crate::ActionSuccess, crate::ActionError>
|
) -> Result<crate::ActionSuccess, crate::ActionError>
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync
|
+ Sync
|
||||||
|
@ -318,9 +318,9 @@ impl<'a> ActionTypeBuilder<'a> {
|
||||||
|
|
||||||
unsafe extern "C" fn execute_func_trampoline(
|
unsafe extern "C" fn execute_func_trampoline(
|
||||||
scenario: *mut ffi::GstValidateScenario,
|
scenario: *mut ffi::GstValidateScenario,
|
||||||
action: *mut ffi::GstValidateAction,
|
mut action_ptr: *mut ffi::GstValidateAction,
|
||||||
) -> c_int {
|
) -> c_int {
|
||||||
let action_type = ffi::gst_validate_get_action_type((*action).type_);
|
let action_type = ffi::gst_validate_get_action_type((*action_ptr).type_);
|
||||||
let scenario = from_glib_borrow(scenario);
|
let scenario = from_glib_borrow(scenario);
|
||||||
|
|
||||||
let func: &ActionFunction = &*(gst::ffi::gst_mini_object_get_qdata(
|
let func: &ActionFunction = &*(gst::ffi::gst_mini_object_get_qdata(
|
||||||
|
@ -328,21 +328,21 @@ impl<'a> ActionTypeBuilder<'a> {
|
||||||
QUARK_ACTION_TYPE_FUNC.get().unwrap().into_glib(),
|
QUARK_ACTION_TYPE_FUNC.get().unwrap().into_glib(),
|
||||||
) as *const Box<ActionFunction>);
|
) as *const Box<ActionFunction>);
|
||||||
|
|
||||||
let res = (*func)(&scenario, crate::ActionRef::from_mut_ptr(action));
|
// SAFETY: `execute_func_trampoline` is called with the unic reference of `action_ptr`
|
||||||
|
// so we can safely borrow it mutably
|
||||||
|
let original_ptr = action_ptr;
|
||||||
|
let action = Action::from_glib_ptr_borrow_mut(&mut action_ptr);
|
||||||
|
let res = (*func)(&scenario, action);
|
||||||
|
|
||||||
if let Err(crate::ActionError::Error(ref err)) = res {
|
debug_assert_eq!(action.as_ptr(), original_ptr);
|
||||||
scenario
|
match res {
|
||||||
.dynamic_cast_ref::<crate::Reporter>()
|
Err(crate::ActionError::Error(ref err)) => {
|
||||||
.unwrap()
|
action.report_error(err);
|
||||||
.report_action(
|
ffi::GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED
|
||||||
&from_glib_borrow(action),
|
}
|
||||||
glib::Quark::from_str("scenario::execution-error"),
|
Err(_) => panic!("New action error types should be handled here."),
|
||||||
err,
|
Ok(v) => v.into_glib(),
|
||||||
);
|
|
||||||
return ffi::GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res.into_glib()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -89,7 +89,6 @@ fn test_action_types() {
|
||||||
assert!(!*fails_called.lock().unwrap());
|
assert!(!*fails_called.lock().unwrap());
|
||||||
action.execute().expect_err("Action should have failed");
|
action.execute().expect_err("Action should have failed");
|
||||||
assert!(*fails_called.lock().unwrap());
|
assert!(*fails_called.lock().unwrap());
|
||||||
action.set_done();
|
|
||||||
|
|
||||||
gst_validate::ActionParameterBuilder::new("async", "Verify unused param are properly cleaned")
|
gst_validate::ActionParameterBuilder::new("async", "Verify unused param are properly cleaned")
|
||||||
.default_value("true")
|
.default_value("true")
|
||||||
|
@ -102,12 +101,26 @@ fn test_action_types() {
|
||||||
glib::clone!(
|
glib::clone!(
|
||||||
#[strong]
|
#[strong]
|
||||||
async_called,
|
async_called,
|
||||||
move |_, _action| {
|
move |_, action| {
|
||||||
|
let action_mut = action.get_mut().unwrap();
|
||||||
|
action_mut
|
||||||
|
.structure_mut()
|
||||||
|
.expect("We should have a structure set in that action")
|
||||||
|
.set("running-async", true);
|
||||||
|
|
||||||
std::thread::spawn(glib::clone!(
|
std::thread::spawn(glib::clone!(
|
||||||
#[strong]
|
#[strong]
|
||||||
async_called,
|
async_called,
|
||||||
|
#[strong]
|
||||||
|
action,
|
||||||
move || {
|
move || {
|
||||||
*async_called.0.lock().unwrap() = true;
|
*async_called.0.lock().unwrap() = true;
|
||||||
|
|
||||||
|
assert!(action
|
||||||
|
.structure()
|
||||||
|
.unwrap()
|
||||||
|
.get::<bool>("running-async")
|
||||||
|
.unwrap());
|
||||||
action.set_done();
|
action.set_done();
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
Loading…
Reference in a new issue