-
-
Notifications
You must be signed in to change notification settings - Fork 103
/
main.rs
124 lines (105 loc) · 3.96 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
mod file_size;
use futures_channel::oneshot;
use glib::translate::*;
use glib::{self, clone};
use file_size::FileSize;
fn main() {
let main_context = glib::MainContext::default();
let main_loop = glib::MainLoop::new(Some(&main_context), false);
let (send_safe, recv_safe) = oneshot::channel();
let (send_unsafe, recv_unsafe) = oneshot::channel();
let (send_threaded, recv_threaded) = oneshot::channel();
main_context.invoke_local(move || {
run_unsafe(send_unsafe);
});
main_context.invoke_local(move || {
run_safe(send_safe);
});
main_context.invoke_local(move || {
run_in_thread(send_threaded);
});
main_context.spawn_local(clone!(@strong main_loop => async move {
recv_safe.await.unwrap();
recv_unsafe.await.unwrap();
recv_threaded.await.unwrap();
main_loop.quit();
}));
main_loop.run();
}
// This function mimicks what the C code using the exported async/finish API would do. It first defines a
// callback of type GAsyncResult that internally calls get_file_size_finish to retrieve the Task
// result, and simply prints it out. Then it invokes the my_file_size_get_file_size_async method, passing the
// callback to it as parameter.
fn run_unsafe(send: oneshot::Sender<()>) {
let simple_object = FileSize::new();
let cancellable = gio::Cancellable::new();
// The callback to be passed to my_file_size_get_file_size_async
unsafe extern "C" fn c_callback(
source_object: *mut glib::gobject_ffi::GObject,
result: *mut gio::ffi::GAsyncResult,
user_data: glib::ffi::gpointer,
) {
let mut error = std::ptr::null_mut();
let ret = file_size::ffi::my_file_size_get_file_size_finish(
source_object as *mut file_size::ffi::FileSize,
result,
&mut error,
);
if !error.is_null() {
eprintln!("Task returned error!");
return;
}
println!("Unsafe callback - Returned value from task: {ret}");
println!(
"Unsafe callback - FileSize::size: {}",
file_size::ffi::my_file_size_get_retrieved_size(
source_object as *mut file_size::ffi::FileSize
)
);
Box::from_raw(user_data as *mut oneshot::Sender<()>)
.send(())
.unwrap();
}
// The actual call to my_file_size_get_file_size_async
unsafe {
file_size::ffi::my_file_size_get_file_size_async(
simple_object.to_glib_none().0,
cancellable.to_glib_none().0,
Some(c_callback),
Box::into_raw(Box::new(send)) as glib::ffi::gpointer,
);
}
}
// This function is the "safe" counterpart of "run_unsafe", using only safe rust
// bindings to accomplish the same task
fn run_safe(send: oneshot::Sender<()>) {
let simple_object = FileSize::new();
let cancellable = gio::Cancellable::new();
let closure = move |value: i64, source_object: &FileSize| {
println!("Safe callback - Returned value from task: {value}");
println!(
"Safe callback - FileSize::size: {}",
source_object.retrieved_size().unwrap()
);
send.send(()).unwrap();
};
simple_object.file_size_async(Some(&cancellable), closure);
}
// A version that uses the safe bindings to accomplish the same task, but running
// in a thread of the gio thread pool
fn run_in_thread(send: oneshot::Sender<()>) {
let simple_object = FileSize::new();
let cancellable = gio::Cancellable::new();
let closure = move |value: i64, source_object: &FileSize| {
println!(
"Safe callback (threaded version) - Returned value from task: {}",
value
);
println!(
"Safe callback (threaded version) - FileSize::size: {}",
source_object.retrieved_size().unwrap()
);
send.send(()).unwrap();
};
simple_object.file_size_in_thread_async(Some(&cancellable), closure);
}