Skip to content

Commit 0b67019

Browse files
authored
Merge pull request #1762 from carlosmn/cmn/task-propagate-explicit
gio: add methods for returning and propagating boolean and int in/from a `Task`
2 parents 635d5cd + 48f9f4d commit 0b67019

File tree

2 files changed

+147
-8
lines changed

2 files changed

+147
-8
lines changed

examples/gio_task/file_size/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ impl FileSize {
2626
callback: Q,
2727
) {
2828
let closure = move |task: gio::LocalTask<i64>, source_object: Option<&glib::Object>| {
29-
let value = task.propagate().unwrap();
29+
// SAFETY: this is safe because we call propagate just once and the
30+
// task sets the result as a value
31+
let value = unsafe { task.propagate() }.unwrap();
3032
let source_object = source_object.unwrap().downcast_ref::<FileSize>().unwrap();
3133
callback(value, source_object);
3234
};
@@ -68,7 +70,8 @@ impl FileSize {
6870
callback: Q,
6971
) {
7072
let closure = move |task: gio::Task<i64>, source_object: Option<&FileSize>| {
71-
// SAFETY: this is safe because we call propagate just once
73+
// SAFETY: this is safe because we call propagate just once and the
74+
// task sets the result as a value
7275
let value = unsafe { task.propagate().unwrap() };
7376
let source_object = source_object.unwrap().downcast_ref::<FileSize>().unwrap();
7477
callback(value, source_object);

gio/src/task.rs

Lines changed: 142 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,14 @@ macro_rules! task_impl {
237237
unsafe { from_glib(ffi::g_task_return_error_if_cancelled(self.to_glib_none().0)) }
238238
}
239239

240+
// rustdoc-stripper-ignore-next
241+
/// Set the result of the task
242+
///
243+
/// # Safety
244+
///
245+
/// The value must be read with [`Task::propagate`],
246+
/// `g_task_propagate_value` or `g_task_propagate_pointer`.
240247
#[doc(alias = "g_task_return_value")]
241-
#[doc(alias = "g_task_return_boolean")]
242-
#[doc(alias = "g_task_return_int")]
243248
#[doc(alias = "g_task_return_pointer")]
244249
#[doc(alias = "g_task_return_error")]
245250
#[allow(unused_unsafe)]
@@ -272,12 +277,51 @@ macro_rules! task_impl {
272277
}
273278
}
274279

280+
// rustdoc-stripper-ignore-next
281+
/// Set the result of the task as a boolean
282+
///
283+
/// # Safety
284+
///
285+
/// The value must be read with [`Task::propagate_boolean`],
286+
/// or `g_task_propagate_boolean`.
287+
#[doc(alias = "g_task_return_boolean")]
288+
#[allow(unused_unsafe)]
289+
pub $($safety)? fn return_boolean_result(self, result: Result<bool, glib::Error>) {
290+
match result {
291+
Ok(v) => unsafe { ffi::g_task_return_boolean(self.to_glib_none().0, v as i32) },
292+
Err(e) => unsafe { ffi::g_task_return_error(self.to_glib_none().0, e.into_glib_ptr()) },
293+
}
294+
}
295+
296+
// rustdoc-stripper-ignore-next
297+
/// Set the result of the task as an int
298+
///
299+
/// # Safety
300+
///
301+
/// The value must be read with [`Task::propagate_int`],
302+
/// or `g_task_propagate_int`.
303+
#[doc(alias = "g_task_return_int")]
304+
#[allow(unused_unsafe)]
305+
pub $($safety)? fn return_int_result(self, result: Result<isize, glib::Error>) {
306+
match result {
307+
Ok(v) => unsafe { ffi::g_task_return_int(self.to_glib_none().0, v) },
308+
Err(e) => unsafe { ffi::g_task_return_error(self.to_glib_none().0, e.into_glib_ptr()) },
309+
}
310+
}
311+
312+
313+
// rustdoc-stripper-ignore-next
314+
/// Gets the result of the task and transfers ownership of it
315+
///
316+
/// # Safety
317+
///
318+
/// This must only be called once, and only if the result was set
319+
/// via [`Task::return_result`], `g_task_return_value` or
320+
/// `g_task_return_pointer`.
275321
#[doc(alias = "g_task_propagate_value")]
276-
#[doc(alias = "g_task_propagate_boolean")]
277-
#[doc(alias = "g_task_propagate_int")]
278322
#[doc(alias = "g_task_propagate_pointer")]
279323
#[allow(unused_unsafe)]
280-
pub $($safety)? fn propagate(self) -> Result<V, glib::Error> {
324+
pub unsafe fn propagate(self) -> Result<V, glib::Error> {
281325
let mut error = ptr::null_mut();
282326

283327
unsafe {
@@ -313,6 +357,52 @@ macro_rules! task_impl {
313357
}
314358
}
315359
}
360+
361+
// rustdoc-stripper-ignore-next
362+
/// Gets the result of the task as a boolean, or the error
363+
///
364+
/// # Safety
365+
///
366+
/// This must only be called once, and only if the result was set
367+
/// via [`Task::return_boolean_result`], or `g_task_return_boolean`.
368+
#[doc(alias = "g_task_propagate_boolean")]
369+
#[allow(unused_unsafe)]
370+
pub unsafe fn propagate_boolean(self) -> Result<bool, glib::Error> {
371+
let mut error = ptr::null_mut();
372+
373+
unsafe {
374+
let res = ffi::g_task_propagate_boolean(self.to_glib_none().0, &mut error);
375+
376+
if error.is_null() {
377+
Ok(res != 0)
378+
} else {
379+
Err(from_glib_full(error))
380+
}
381+
}
382+
}
383+
384+
// rustdoc-stripper-ignore-next
385+
/// Gets the result of the task as an int, or the error
386+
///
387+
/// # Safety
388+
///
389+
/// This must only be called once, and only if the result was set
390+
/// via [`Task::return_int_result`], or `g_task_return_int`.
391+
#[doc(alias = "g_task_propagate_int")]
392+
#[allow(unused_unsafe)]
393+
pub unsafe fn propagate_int(self) -> Result<isize, glib::Error> {
394+
let mut error = ptr::null_mut();
395+
396+
unsafe {
397+
let res = ffi::g_task_propagate_int(self.to_glib_none().0, &mut error);
398+
399+
if error.is_null() {
400+
Ok(res)
401+
} else {
402+
Err(from_glib_full(error))
403+
}
404+
}
405+
}
316406
}
317407
}
318408
}
@@ -447,7 +537,7 @@ mod test {
447537
use crate::{prelude::*, test_util::run_async_local};
448538

449539
#[test]
450-
fn test_int_async_result() {
540+
fn test_int_value_async_result() {
451541
let fut = run_async_local(|tx, l| {
452542
let cancellable = crate::Cancellable::new();
453543
let task = unsafe {
@@ -469,6 +559,52 @@ mod test {
469559
}
470560
}
471561

562+
#[test]
563+
fn test_boolean_async_result() {
564+
let fut = run_async_local(|tx, l| {
565+
let cancellable = crate::Cancellable::new();
566+
let task = unsafe {
567+
crate::LocalTask::new(
568+
None,
569+
Some(&cancellable),
570+
move |t: LocalTask<bool>, _b: Option<&glib::Object>| {
571+
tx.send(t.propagate_boolean()).unwrap();
572+
l.quit();
573+
},
574+
)
575+
};
576+
task.return_boolean_result(Ok(true));
577+
});
578+
579+
match fut {
580+
Err(_) => panic!(),
581+
Ok(i) => assert!(i),
582+
}
583+
}
584+
585+
#[test]
586+
fn test_int_async_result() {
587+
let fut = run_async_local(|tx, l| {
588+
let cancellable = crate::Cancellable::new();
589+
let task = unsafe {
590+
crate::LocalTask::new(
591+
None,
592+
Some(&cancellable),
593+
move |t: LocalTask<i32>, _b: Option<&glib::Object>| {
594+
tx.send(t.propagate_int()).unwrap();
595+
l.quit();
596+
},
597+
)
598+
};
599+
task.return_int_result(Ok(100_isize));
600+
});
601+
602+
match fut {
603+
Err(_) => panic!(),
604+
Ok(i) => assert_eq!(i, 100),
605+
}
606+
}
607+
472608
#[test]
473609
fn test_object_async_result() {
474610
use glib::subclass::prelude::*;

0 commit comments

Comments
 (0)