1use gio_sys;
6use glib::object::Cast;
7use glib::object::IsA;
8use glib::signal::connect_raw;
9use glib::signal::SignalHandlerId;
10use glib::translate::*;
11use glib_sys;
12use libc;
13use std::boxed::Box as Box_;
14use std::fmt;
15use std::mem::transmute;
16use std::ptr;
17use Error;
18
19glib_wrapper! {
20 pub struct Cancellable(Object<gio_sys::GCancellable, gio_sys::GCancellableClass, CancellableClass>);
21
22 match fn {
23 get_type => || gio_sys::g_cancellable_get_type(),
24 }
25}
26
27impl Cancellable {
28 pub fn new() -> Cancellable {
29 unsafe { from_glib_full(gio_sys::g_cancellable_new()) }
30 }
31
32 pub fn get_current() -> Option<Cancellable> {
33 unsafe { from_glib_none(gio_sys::g_cancellable_get_current()) }
34 }
35}
36
37impl Default for Cancellable {
38 fn default() -> Self {
39 Self::new()
40 }
41}
42
43unsafe impl Send for Cancellable {}
44unsafe impl Sync for Cancellable {}
45
46pub const NONE_CANCELLABLE: Option<&Cancellable> = None;
47
48pub trait CancellableExt: 'static {
49 fn cancel(&self);
50
51 fn disconnect(&self, handler_id: libc::c_ulong);
54
55 fn get_fd(&self) -> i32;
56
57 fn is_cancelled(&self) -> bool;
58
59 fn pop_current(&self);
62
63 fn push_current(&self);
64
65 fn release_fd(&self);
66
67 fn set_error_if_cancelled(&self) -> Result<(), Error>;
68
69 fn connect_cancelled<F: Fn(&Self) + Send + Sync + 'static>(&self, f: F) -> SignalHandlerId;
70}
71
72impl<O: IsA<Cancellable>> CancellableExt for O {
73 fn cancel(&self) {
74 unsafe {
75 gio_sys::g_cancellable_cancel(self.as_ref().to_glib_none().0);
76 }
77 }
78
79 fn disconnect(&self, handler_id: libc::c_ulong) {
84 unsafe {
85 gio_sys::g_cancellable_disconnect(self.as_ref().to_glib_none().0, handler_id);
86 }
87 }
88
89 fn get_fd(&self) -> i32 {
90 unsafe { gio_sys::g_cancellable_get_fd(self.as_ref().to_glib_none().0) }
91 }
92
93 fn is_cancelled(&self) -> bool {
94 unsafe {
95 from_glib(gio_sys::g_cancellable_is_cancelled(
96 self.as_ref().to_glib_none().0,
97 ))
98 }
99 }
100
101 fn pop_current(&self) {
106 unsafe {
107 gio_sys::g_cancellable_pop_current(self.as_ref().to_glib_none().0);
108 }
109 }
110
111 fn push_current(&self) {
112 unsafe {
113 gio_sys::g_cancellable_push_current(self.as_ref().to_glib_none().0);
114 }
115 }
116
117 fn release_fd(&self) {
118 unsafe {
119 gio_sys::g_cancellable_release_fd(self.as_ref().to_glib_none().0);
120 }
121 }
122
123 fn set_error_if_cancelled(&self) -> Result<(), Error> {
124 unsafe {
125 let mut error = ptr::null_mut();
126 let _ = gio_sys::g_cancellable_set_error_if_cancelled(
127 self.as_ref().to_glib_none().0,
128 &mut error,
129 );
130 if error.is_null() {
131 Ok(())
132 } else {
133 Err(from_glib_full(error))
134 }
135 }
136 }
137
138 fn connect_cancelled<F: Fn(&Self) + Send + Sync + 'static>(&self, f: F) -> SignalHandlerId {
139 unsafe extern "C" fn cancelled_trampoline<P, F: Fn(&P) + Send + Sync + 'static>(
140 this: *mut gio_sys::GCancellable,
141 f: glib_sys::gpointer,
142 ) where
143 P: IsA<Cancellable>,
144 {
145 let f: &F = &*(f as *const F);
146 f(&Cancellable::from_glib_borrow(this).unsafe_cast())
147 }
148 unsafe {
149 let f: Box_<F> = Box_::new(f);
150 connect_raw(
151 self.as_ptr() as *mut _,
152 b"cancelled\0".as_ptr() as *const _,
153 Some(transmute(cancelled_trampoline::<Self, F> as usize)),
154 Box_::into_raw(f),
155 )
156 }
157 }
158}
159
160impl fmt::Display for Cancellable {
161 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
162 write!(f, "Cancellable")
163 }
164}