1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | #[cfg (unix)] |
4 | use std::os::unix::io::RawFd; |
5 | use std::{cell::RefCell, mem::transmute, num::NonZeroU32, time::Duration}; |
6 | |
7 | use ffi::{self, gboolean, gpointer}; |
8 | #[cfg (all(not(unix), docsrs))] |
9 | use libc::c_int as RawFd; |
10 | |
11 | #[cfg (any(unix, docsrs))] |
12 | use crate::IOCondition; |
13 | use crate::{thread_guard::ThreadGuard, translate::*, ControlFlow, MainContext, Source}; |
14 | |
15 | // rustdoc-stripper-ignore-next |
16 | /// The id of a source that is returned by `idle_add` and `timeout_add`. |
17 | /// |
18 | /// This type does not implement `Clone` to prevent calling [`SourceId::remove`] |
19 | /// multiple times on the same source. |
20 | #[derive (Debug, Eq, PartialEq)] |
21 | pub struct SourceId(NonZeroU32); |
22 | |
23 | impl SourceId { |
24 | // rustdoc-stripper-ignore-next |
25 | /// Returns the internal source ID. |
26 | pub fn as_raw(&self) -> u32 { |
27 | self.0.get() |
28 | } |
29 | |
30 | // rustdoc-stripper-ignore-next |
31 | /// Removes the source with the given id `source_id` from the default main context. |
32 | /// |
33 | /// It is a programmer error to attempt to remove a non-existent source. |
34 | #[doc (alias = "g_source_remove" )] |
35 | pub fn remove(self) { |
36 | unsafe { |
37 | result_from_gbooleanResult<(), BoolError>!( |
38 | ffi::g_source_remove(self.as_raw()), |
39 | "Failed to remove source" |
40 | ) |
41 | .unwrap() |
42 | } |
43 | } |
44 | } |
45 | |
46 | #[doc (hidden)] |
47 | impl FromGlib<u32> for SourceId { |
48 | #[inline ] |
49 | unsafe fn from_glib(val: u32) -> Self { |
50 | debug_assert_ne!(val, 0); |
51 | Self(NonZeroU32::new_unchecked(val)) |
52 | } |
53 | } |
54 | |
55 | // rustdoc-stripper-ignore-next |
56 | /// Process identificator |
57 | #[derive (Copy, Clone, Debug, Eq, PartialEq)] |
58 | #[doc (alias = "GPid" )] |
59 | pub struct Pid(pub ffi::GPid); |
60 | |
61 | unsafe impl Send for Pid {} |
62 | unsafe impl Sync for Pid {} |
63 | |
64 | #[doc (hidden)] |
65 | impl IntoGlib for Pid { |
66 | type GlibType = ffi::GPid; |
67 | |
68 | #[inline ] |
69 | fn into_glib(self) -> ffi::GPid { |
70 | self.0 |
71 | } |
72 | } |
73 | |
74 | #[doc (hidden)] |
75 | impl FromGlib<ffi::GPid> for Pid { |
76 | #[inline ] |
77 | unsafe fn from_glib(val: ffi::GPid) -> Self { |
78 | Self(val) |
79 | } |
80 | } |
81 | |
82 | unsafe extern "C" fn trampoline<F: FnMut() -> ControlFlow + Send + 'static>( |
83 | func: gpointer, |
84 | ) -> gboolean { |
85 | let func: &RefCell<F> = &*(func as *const RefCell<F>); |
86 | (*func.borrow_mut())().into_glib() |
87 | } |
88 | |
89 | unsafe extern "C" fn trampoline_local<F: FnMut() -> ControlFlow + 'static>( |
90 | func: gpointer, |
91 | ) -> gboolean { |
92 | let func: &ThreadGuard<RefCell<F>> = &*(func as *const ThreadGuard<RefCell<F>>); |
93 | (*func.get_ref().borrow_mut())().into_glib() |
94 | } |
95 | |
96 | unsafe extern "C" fn destroy_closure<F: FnMut() -> ControlFlow + Send + 'static>(ptr: gpointer) { |
97 | let _ = Box::<RefCell<F>>::from_raw(ptr as *mut _); |
98 | } |
99 | |
100 | unsafe extern "C" fn destroy_closure_local<F: FnMut() -> ControlFlow + 'static>(ptr: gpointer) { |
101 | let _ = Box::<ThreadGuard<RefCell<F>>>::from_raw(ptr as *mut _); |
102 | } |
103 | |
104 | fn into_raw<F: FnMut() -> ControlFlow + Send + 'static>(func: F) -> gpointer { |
105 | let func: Box<RefCell<F>> = Box::new(RefCell::new(func)); |
106 | Box::into_raw(func) as gpointer |
107 | } |
108 | |
109 | fn into_raw_local<F: FnMut() -> ControlFlow + 'static>(func: F) -> gpointer { |
110 | let func: Box<ThreadGuard<RefCell<F>>> = Box::new(ThreadGuard::new(RefCell::new(func))); |
111 | Box::into_raw(func) as gpointer |
112 | } |
113 | |
114 | unsafe extern "C" fn trampoline_child_watch<F: FnMut(Pid, i32) + Send + 'static>( |
115 | pid: ffi::GPid, |
116 | status: i32, |
117 | func: gpointer, |
118 | ) { |
119 | let func: &RefCell<F> = &*(func as *const RefCell<F>); |
120 | (*func.borrow_mut())(Pid(pid), status) |
121 | } |
122 | |
123 | unsafe extern "C" fn trampoline_child_watch_local<F: FnMut(Pid, i32) + 'static>( |
124 | pid: ffi::GPid, |
125 | status: i32, |
126 | func: gpointer, |
127 | ) { |
128 | let func: &ThreadGuard<RefCell<F>> = &*(func as *const ThreadGuard<RefCell<F>>); |
129 | (*func.get_ref().borrow_mut())(Pid(pid), status) |
130 | } |
131 | |
132 | unsafe extern "C" fn destroy_closure_child_watch<F: FnMut(Pid, i32) + Send + 'static>( |
133 | ptr: gpointer, |
134 | ) { |
135 | let _ = Box::<RefCell<F>>::from_raw(ptr as *mut _); |
136 | } |
137 | |
138 | unsafe extern "C" fn destroy_closure_child_watch_local<F: FnMut(Pid, i32) + 'static>( |
139 | ptr: gpointer, |
140 | ) { |
141 | let _ = Box::<ThreadGuard<RefCell<F>>>::from_raw(ptr as *mut _); |
142 | } |
143 | |
144 | fn into_raw_child_watch<F: FnMut(Pid, i32) + Send + 'static>(func: F) -> gpointer { |
145 | let func: Box<RefCell<F>> = Box::new(RefCell::new(func)); |
146 | Box::into_raw(func) as gpointer |
147 | } |
148 | |
149 | fn into_raw_child_watch_local<F: FnMut(Pid, i32) + 'static>(func: F) -> gpointer { |
150 | let func: Box<ThreadGuard<RefCell<F>>> = Box::new(ThreadGuard::new(RefCell::new(func))); |
151 | Box::into_raw(func) as gpointer |
152 | } |
153 | |
154 | #[cfg (any(unix, docsrs))] |
155 | #[cfg_attr (docsrs, doc(cfg(unix)))] |
156 | unsafe extern "C" fn trampoline_unix_fd< |
157 | F: FnMut(RawFd, IOCondition) -> ControlFlow + Send + 'static, |
158 | >( |
159 | fd: i32, |
160 | condition: ffi::GIOCondition, |
161 | func: gpointer, |
162 | ) -> gboolean { |
163 | let func: &RefCell<F> = &*(func as *const RefCell<F>); |
164 | (*func.borrow_mut())(fd, from_glib(val:condition)).into_glib() |
165 | } |
166 | |
167 | #[cfg (any(unix, docsrs))] |
168 | #[cfg_attr (docsrs, doc(cfg(unix)))] |
169 | unsafe extern "C" fn trampoline_unix_fd_local< |
170 | F: FnMut(RawFd, IOCondition) -> ControlFlow + 'static, |
171 | >( |
172 | fd: i32, |
173 | condition: ffi::GIOCondition, |
174 | func: gpointer, |
175 | ) -> gboolean { |
176 | let func: &ThreadGuard<RefCell<F>> = &*(func as *const ThreadGuard<RefCell<F>>); |
177 | (*func.get_ref().borrow_mut())(fd, from_glib(val:condition)).into_glib() |
178 | } |
179 | |
180 | #[cfg (any(unix, docsrs))] |
181 | #[cfg_attr (docsrs, doc(cfg(unix)))] |
182 | unsafe extern "C" fn destroy_closure_unix_fd< |
183 | F: FnMut(RawFd, IOCondition) -> ControlFlow + Send + 'static, |
184 | >( |
185 | ptr: gpointer, |
186 | ) { |
187 | let _ = Box::<RefCell<F>>::from_raw(ptr as *mut _); |
188 | } |
189 | |
190 | #[cfg (any(unix, docsrs))] |
191 | #[cfg_attr (docsrs, doc(cfg(unix)))] |
192 | unsafe extern "C" fn destroy_closure_unix_fd_local< |
193 | F: FnMut(RawFd, IOCondition) -> ControlFlow + 'static, |
194 | >( |
195 | ptr: gpointer, |
196 | ) { |
197 | let _ = Box::<ThreadGuard<RefCell<F>>>::from_raw(ptr as *mut _); |
198 | } |
199 | |
200 | #[cfg (any(unix, docsrs))] |
201 | #[cfg_attr (docsrs, doc(cfg(unix)))] |
202 | fn into_raw_unix_fd<F: FnMut(RawFd, IOCondition) -> ControlFlow + Send + 'static>( |
203 | func: F, |
204 | ) -> gpointer { |
205 | let func: Box<RefCell<F>> = Box::new(RefCell::new(func)); |
206 | Box::into_raw(func) as gpointer |
207 | } |
208 | |
209 | #[cfg (any(unix, docsrs))] |
210 | #[cfg_attr (docsrs, doc(cfg(unix)))] |
211 | fn into_raw_unix_fd_local<F: FnMut(RawFd, IOCondition) -> ControlFlow + 'static>( |
212 | func: F, |
213 | ) -> gpointer { |
214 | let func: Box<ThreadGuard<RefCell<F>>> = Box::new(ThreadGuard::new(RefCell::new(func))); |
215 | Box::into_raw(func) as gpointer |
216 | } |
217 | |
218 | // rustdoc-stripper-ignore-next |
219 | /// Transform a generic FnOnce into a closure that can be used as callback in various glib methods |
220 | /// |
221 | /// The resulting function can only be called once and will panic otherwise. It will return `ControlFlow::Break` |
222 | /// in order to prevent being called twice. |
223 | #[inline (always)] |
224 | fn fnmut_callback_wrapper( |
225 | func: impl FnOnce() + Send + 'static, |
226 | ) -> impl FnMut() -> ControlFlow + Send + 'static { |
227 | let mut func: Option = Some(func); |
228 | move || { |
229 | let func: impl FnOnce() + Send = func |
230 | .take() |
231 | .expect(msg:"GSource closure called after returning ControlFlow::Break" ); |
232 | func(); |
233 | ControlFlow::Break |
234 | } |
235 | } |
236 | |
237 | // rustdoc-stripper-ignore-next |
238 | /// Transform a generic FnOnce into a closure that can be used as callback in various glib methods |
239 | /// |
240 | /// The resulting function can only be called once and will panic otherwise. It will return `ControlFlow::Break` |
241 | /// in order to prevent being called twice. |
242 | /// |
243 | /// Different to `fnmut_callback_wrapper()`, this does not require `func` to be |
244 | /// `Send` but can only be called from the thread that owns the main context. |
245 | #[inline (always)] |
246 | fn fnmut_callback_wrapper_local( |
247 | func: impl FnOnce() + 'static, |
248 | ) -> impl FnMut() -> ControlFlow + 'static { |
249 | let mut func: Option = Some(func); |
250 | move || { |
251 | let func: impl FnOnce() = func |
252 | .take() |
253 | .expect(msg:"GSource closure called after returning glib::ControlFlow::Break" ); |
254 | func(); |
255 | ControlFlow::Break |
256 | } |
257 | } |
258 | |
259 | // rustdoc-stripper-ignore-next |
260 | /// Adds a closure to be called by the default main loop when it's idle. |
261 | /// |
262 | /// `func` will be called repeatedly until it returns `ControlFlow::Break`. |
263 | /// |
264 | /// The default main loop almost always is the main loop of the main thread. |
265 | /// Thus, the closure is called on the main thread. |
266 | #[doc (alias = "g_idle_add_full" )] |
267 | pub fn idle_add<F>(func: F) -> SourceId |
268 | where |
269 | F: FnMut() -> ControlFlow + Send + 'static, |
270 | { |
271 | unsafe { |
272 | from_glib(val:ffi::g_idle_add_full( |
273 | priority:ffi::G_PRIORITY_DEFAULT_IDLE, |
274 | function:Some(trampoline::<F>), |
275 | data:into_raw(func), |
276 | notify:Some(destroy_closure::<F>), |
277 | )) |
278 | } |
279 | } |
280 | |
281 | // rustdoc-stripper-ignore-next |
282 | /// Adds a closure to be called by the default main loop when it's idle. |
283 | /// |
284 | /// `func` will be called repeatedly with `priority` until it returns |
285 | /// `ControlFlow::Break`. |
286 | /// |
287 | /// The default main loop almost always is the main loop of the main thread. |
288 | /// Thus, the closure is called on the main thread. |
289 | #[doc (alias = "g_idle_add_full" )] |
290 | pub fn idle_add_full<F>(priority: Priority, func: F) -> SourceId |
291 | where |
292 | F: FnMut() -> ControlFlow + Send + 'static, |
293 | { |
294 | unsafe { |
295 | from_glib(val:ffi::g_idle_add_full( |
296 | priority:priority.into_glib(), |
297 | function:Some(trampoline::<F>), |
298 | data:into_raw(func), |
299 | notify:Some(destroy_closure::<F>), |
300 | )) |
301 | } |
302 | } |
303 | |
304 | // rustdoc-stripper-ignore-next |
305 | /// Adds a closure to be called by the default main loop when it's idle. |
306 | /// |
307 | /// `func` will be called repeatedly until it returns `ControlFlow::Break`. |
308 | /// |
309 | /// The default main loop almost always is the main loop of the main thread. |
310 | /// Thus, the closure is called on the main thread. |
311 | /// |
312 | /// In comparison to `idle_add()`, this only requires `func` to be |
313 | /// `FnOnce`, and will automatically return `ControlFlow::Break`. |
314 | #[doc (alias = "g_idle_add_full" )] |
315 | #[doc (alias = "g_idle_add_once" )] |
316 | pub fn idle_add_once<F>(func: F) -> SourceId |
317 | where |
318 | F: FnOnce() + Send + 'static, |
319 | { |
320 | idle_add(func:fnmut_callback_wrapper(func)) |
321 | } |
322 | |
323 | // rustdoc-stripper-ignore-next |
324 | /// Adds a closure to be called by the default main loop when it's idle. |
325 | /// |
326 | /// `func` will be called repeatedly until it returns `ControlFlow::Break`. |
327 | /// |
328 | /// The default main loop almost always is the main loop of the main thread. |
329 | /// Thus, the closure is called on the main thread. |
330 | /// |
331 | /// Different to `idle_add()`, this does not require `func` to be |
332 | /// `Send` but can only be called from the thread that owns the main context. |
333 | /// |
334 | /// This function panics if called from a different thread than the one that |
335 | /// owns the default main context. |
336 | #[doc (alias = "g_idle_add_full" )] |
337 | pub fn idle_add_local<F>(func: F) -> SourceId |
338 | where |
339 | F: FnMut() -> ControlFlow + 'static, |
340 | { |
341 | unsafe { |
342 | let context: MainContext = MainContext::default(); |
343 | let _acquire: MainContextAcquireGuard<'_> = context |
344 | .acquire() |
345 | .expect(msg:"default main context already acquired by another thread" ); |
346 | from_glib(val:ffi::g_idle_add_full( |
347 | priority:ffi::G_PRIORITY_DEFAULT_IDLE, |
348 | function:Some(trampoline_local::<F>), |
349 | data:into_raw_local(func), |
350 | notify:Some(destroy_closure_local::<F>), |
351 | )) |
352 | } |
353 | } |
354 | |
355 | // rustdoc-stripper-ignore-next |
356 | /// Adds a closure to be called by the default main loop when it's idle. |
357 | /// |
358 | /// `func` will be called repeatedly with `priority` until it returns |
359 | /// `ControlFlow::Break`. |
360 | /// |
361 | /// The default main loop almost always is the main loop of the main thread. |
362 | /// Thus, the closure is called on the main thread. |
363 | /// |
364 | /// Different to `idle_add()`, this does not require `func` to be |
365 | /// `Send` but can only be called from the thread that owns the main context. |
366 | /// |
367 | /// This function panics if called from a different thread than the one that |
368 | /// owns the default main context. |
369 | #[doc (alias = "g_idle_add_full" )] |
370 | pub fn idle_add_local_full<F>(priority: Priority, func: F) -> SourceId |
371 | where |
372 | F: FnMut() -> ControlFlow + 'static, |
373 | { |
374 | unsafe { |
375 | let context: MainContext = MainContext::default(); |
376 | let _acquire: MainContextAcquireGuard<'_> = context |
377 | .acquire() |
378 | .expect(msg:"default main context already acquired by another thread" ); |
379 | from_glib(val:ffi::g_idle_add_full( |
380 | priority:priority.into_glib(), |
381 | function:Some(trampoline_local::<F>), |
382 | data:into_raw_local(func), |
383 | notify:Some(destroy_closure_local::<F>), |
384 | )) |
385 | } |
386 | } |
387 | |
388 | // rustdoc-stripper-ignore-next |
389 | /// Adds a closure to be called by the default main loop when it's idle. |
390 | /// |
391 | /// `func` will be called repeatedly until it returns `ControlFlow::Break`. |
392 | /// |
393 | /// The default main loop almost always is the main loop of the main thread. |
394 | /// Thus, the closure is called on the main thread. |
395 | /// |
396 | /// Different to `idle_add()`, this does not require `func` to be |
397 | /// `Send` but can only be called from the thread that owns the main context. |
398 | /// |
399 | /// This function panics if called from a different thread than the one that |
400 | /// owns the main context. |
401 | /// |
402 | /// In comparison to `idle_add_local()`, this only requires `func` to be |
403 | /// `FnOnce`, and will automatically return `ControlFlow::Break`. |
404 | #[doc (alias = "g_idle_add_full" )] |
405 | pub fn idle_add_local_once<F>(func: F) -> SourceId |
406 | where |
407 | F: FnOnce() + 'static, |
408 | { |
409 | idle_add_local(func:fnmut_callback_wrapper_local(func)) |
410 | } |
411 | |
412 | // rustdoc-stripper-ignore-next |
413 | /// Adds a closure to be called by the default main loop at regular intervals |
414 | /// with millisecond granularity. |
415 | /// |
416 | /// `func` will be called repeatedly every `interval` milliseconds until it |
417 | /// returns `ControlFlow::Break`. Precise timing is not guaranteed, the timeout may |
418 | /// be delayed by other events. Prefer `timeout_add_seconds` when millisecond |
419 | /// precision is not necessary. |
420 | /// |
421 | /// The default main loop almost always is the main loop of the main thread. |
422 | /// Thus, the closure is called on the main thread. |
423 | #[doc (alias = "g_timeout_add_full" )] |
424 | pub fn timeout_add<F>(interval: Duration, func: F) -> SourceId |
425 | where |
426 | F: FnMut() -> ControlFlow + Send + 'static, |
427 | { |
428 | unsafe { |
429 | from_glib(val:ffi::g_timeout_add_full( |
430 | priority:ffi::G_PRIORITY_DEFAULT, |
431 | interval:interval.as_millis() as _, |
432 | function:Some(trampoline::<F>), |
433 | data:into_raw(func), |
434 | notify:Some(destroy_closure::<F>), |
435 | )) |
436 | } |
437 | } |
438 | |
439 | // rustdoc-stripper-ignore-next |
440 | /// Adds a closure to be called by the default main loop at regular intervals |
441 | /// with millisecond granularity. |
442 | /// |
443 | /// `func` will be called repeatedly every `interval` milliseconds with `priority` |
444 | /// until it returns `ControlFlow::Break`. Precise timing is not guaranteed, the |
445 | /// timeout may be delayed by other events. Prefer `timeout_add_seconds` when |
446 | /// millisecond precision is not necessary. |
447 | /// |
448 | /// The default main loop almost always is the main loop of the main thread. |
449 | /// Thus, the closure is called on the main thread. |
450 | #[doc (alias = "g_timeout_add_full" )] |
451 | pub fn timeout_add_full<F>(interval: Duration, priority: Priority, func: F) -> SourceId |
452 | where |
453 | F: FnMut() -> ControlFlow + Send + 'static, |
454 | { |
455 | unsafe { |
456 | from_glib(val:ffi::g_timeout_add_full( |
457 | priority:priority.into_glib(), |
458 | interval:interval.as_millis() as _, |
459 | function:Some(trampoline::<F>), |
460 | data:into_raw(func), |
461 | notify:Some(destroy_closure::<F>), |
462 | )) |
463 | } |
464 | } |
465 | |
466 | // rustdoc-stripper-ignore-next |
467 | /// Adds a closure to be called by the default main loop at regular intervals |
468 | /// with millisecond granularity. |
469 | /// |
470 | /// `func` will be called repeatedly every `interval` milliseconds until it |
471 | /// returns `ControlFlow::Break`. Precise timing is not guaranteed, the timeout may |
472 | /// be delayed by other events. Prefer `timeout_add_seconds` when millisecond |
473 | /// precision is not necessary. |
474 | /// |
475 | /// The default main loop almost always is the main loop of the main thread. |
476 | /// Thus, the closure is called on the main thread. |
477 | /// |
478 | /// In comparison to `timeout_add()`, this only requires `func` to be |
479 | /// `FnOnce`, and will automatically return `ControlFlow::Break`. |
480 | #[doc (alias = "g_timeout_add_full" )] |
481 | #[doc (alias = "g_timeout_add_once" )] |
482 | pub fn timeout_add_once<F>(interval: Duration, func: F) -> SourceId |
483 | where |
484 | F: FnOnce() + Send + 'static, |
485 | { |
486 | timeout_add(interval, func:fnmut_callback_wrapper(func)) |
487 | } |
488 | |
489 | // rustdoc-stripper-ignore-next |
490 | /// Adds a closure to be called by the default main loop at regular intervals |
491 | /// with millisecond granularity. |
492 | /// |
493 | /// `func` will be called repeatedly every `interval` milliseconds until it |
494 | /// returns `ControlFlow::Break`. Precise timing is not guaranteed, the timeout may |
495 | /// be delayed by other events. Prefer `timeout_add_seconds` when millisecond |
496 | /// precision is not necessary. |
497 | /// |
498 | /// The default main loop almost always is the main loop of the main thread. |
499 | /// Thus, the closure is called on the main thread. |
500 | /// |
501 | /// Different to `timeout_add()`, this does not require `func` to be |
502 | /// `Send` but can only be called from the thread that owns the main context. |
503 | /// |
504 | /// This function panics if called from a different thread than the one that |
505 | /// owns the main context. |
506 | #[doc (alias = "g_timeout_add_full" )] |
507 | pub fn timeout_add_local<F>(interval: Duration, func: F) -> SourceId |
508 | where |
509 | F: FnMut() -> ControlFlow + 'static, |
510 | { |
511 | unsafe { |
512 | let context: MainContext = MainContext::default(); |
513 | let _acquire: MainContextAcquireGuard<'_> = context |
514 | .acquire() |
515 | .expect(msg:"default main context already acquired by another thread" ); |
516 | from_glib(val:ffi::g_timeout_add_full( |
517 | priority:ffi::G_PRIORITY_DEFAULT, |
518 | interval:interval.as_millis() as _, |
519 | function:Some(trampoline_local::<F>), |
520 | data:into_raw_local(func), |
521 | notify:Some(destroy_closure_local::<F>), |
522 | )) |
523 | } |
524 | } |
525 | |
526 | // rustdoc-stripper-ignore-next |
527 | /// Adds a closure to be called by the default main loop at regular intervals |
528 | /// with millisecond granularity. |
529 | /// |
530 | /// `func` will be called repeatedly every `interval` milliseconds with `priority` |
531 | /// until it returns `ControlFlow::Break`. Precise timing is not guaranteed, the |
532 | /// timeout may be delayed by other events. Prefer `timeout_add_seconds` when |
533 | /// millisecond precision is not necessary. |
534 | /// |
535 | /// The default main loop almost always is the main loop of the main thread. |
536 | /// Thus, the closure is called on the main thread. |
537 | /// |
538 | /// Different to `timeout_add()`, this does not require `func` to be |
539 | /// `Send` but can only be called from the thread that owns the main context. |
540 | /// |
541 | /// This function panics if called from a different thread than the one that |
542 | /// owns the main context. |
543 | #[doc (alias = "g_timeout_add_full" )] |
544 | pub fn timeout_add_local_full<F>(interval: Duration, priority: Priority, func: F) -> SourceId |
545 | where |
546 | F: FnMut() -> ControlFlow + 'static, |
547 | { |
548 | unsafe { |
549 | let context: MainContext = MainContext::default(); |
550 | let _acquire: MainContextAcquireGuard<'_> = context |
551 | .acquire() |
552 | .expect(msg:"default main context already acquired by another thread" ); |
553 | from_glib(val:ffi::g_timeout_add_full( |
554 | priority:priority.into_glib(), |
555 | interval:interval.as_millis() as _, |
556 | function:Some(trampoline_local::<F>), |
557 | data:into_raw_local(func), |
558 | notify:Some(destroy_closure_local::<F>), |
559 | )) |
560 | } |
561 | } |
562 | |
563 | // rustdoc-stripper-ignore-next |
564 | /// Adds a closure to be called by the default main loop at regular intervals |
565 | /// with millisecond granularity. |
566 | /// |
567 | /// `func` will be called repeatedly every `interval` milliseconds until it |
568 | /// returns `ControlFlow::Break`. Precise timing is not guaranteed, the timeout may |
569 | /// be delayed by other events. Prefer `timeout_add_seconds` when millisecond |
570 | /// precision is not necessary. |
571 | /// |
572 | /// The default main loop almost always is the main loop of the main thread. |
573 | /// Thus, the closure is called on the main thread. |
574 | /// |
575 | /// Different to `timeout_add()`, this does not require `func` to be |
576 | /// `Send` but can only be called from the thread that owns the main context. |
577 | /// |
578 | /// This function panics if called from a different thread than the one that |
579 | /// owns the main context. |
580 | /// |
581 | /// In comparison to `timeout_add_local()`, this only requires `func` to be |
582 | /// `FnOnce`, and will automatically return `ControlFlow::Break`. |
583 | #[doc (alias = "g_timeout_add_full" )] |
584 | pub fn timeout_add_local_once<F>(interval: Duration, func: F) -> SourceId |
585 | where |
586 | F: FnOnce() + 'static, |
587 | { |
588 | timeout_add_local(interval, func:fnmut_callback_wrapper_local(func)) |
589 | } |
590 | |
591 | // rustdoc-stripper-ignore-next |
592 | /// Adds a closure to be called by the default main loop at regular intervals |
593 | /// with second granularity. |
594 | /// |
595 | /// `func` will be called repeatedly every `interval` seconds until it |
596 | /// returns `ControlFlow::Break`. Precise timing is not guaranteed, the timeout may |
597 | /// be delayed by other events. |
598 | /// |
599 | /// The default main loop almost always is the main loop of the main thread. |
600 | /// Thus, the closure is called on the main thread. |
601 | #[doc (alias = "g_timeout_add_seconds_full" )] |
602 | pub fn timeout_add_seconds<F>(interval: u32, func: F) -> SourceId |
603 | where |
604 | F: FnMut() -> ControlFlow + Send + 'static, |
605 | { |
606 | unsafe { |
607 | from_glib(val:ffi::g_timeout_add_seconds_full( |
608 | priority:ffi::G_PRIORITY_DEFAULT, |
609 | interval, |
610 | function:Some(trampoline::<F>), |
611 | data:into_raw(func), |
612 | notify:Some(destroy_closure::<F>), |
613 | )) |
614 | } |
615 | } |
616 | |
617 | // rustdoc-stripper-ignore-next |
618 | /// Adds a closure to be called by the default main loop at regular intervals |
619 | /// with second granularity. |
620 | /// |
621 | /// `func` will be called repeatedly every `interval` seconds until it |
622 | /// returns `ControlFlow::Break`. Precise timing is not guaranteed, the timeout may |
623 | /// be delayed by other events. |
624 | /// |
625 | /// The default main loop almost always is the main loop of the main thread. |
626 | /// Thus, the closure is called on the main thread. |
627 | /// |
628 | /// In comparison to `timeout_add_seconds()`, this only requires `func` to be |
629 | /// `FnOnce`, and will automatically return `ControlFlow::Break`. |
630 | #[doc (alias = "g_timeout_add_seconds_full" )] |
631 | pub fn timeout_add_seconds_once<F>(interval: u32, func: F) -> SourceId |
632 | where |
633 | F: FnOnce() + Send + 'static, |
634 | { |
635 | timeout_add_seconds(interval, func:fnmut_callback_wrapper(func)) |
636 | } |
637 | |
638 | // rustdoc-stripper-ignore-next |
639 | /// Adds a closure to be called by the default main loop at regular intervals |
640 | /// with second granularity. |
641 | /// |
642 | /// `func` will be called repeatedly every `interval` seconds until it |
643 | /// returns `ControlFlow::Break`. Precise timing is not guaranteed, the timeout may |
644 | /// be delayed by other events. |
645 | /// |
646 | /// The default main loop almost always is the main loop of the main thread. |
647 | /// Thus, the closure is called on the main thread. |
648 | /// |
649 | /// Different to `timeout_add_seconds()`, this does not require `func` to be |
650 | /// `Send` but can only be called from the thread that owns the main context. |
651 | /// |
652 | /// This function panics if called from a different thread than the one that |
653 | /// owns the main context. |
654 | #[doc (alias = "g_timeout_add_seconds_full" )] |
655 | pub fn timeout_add_seconds_local<F>(interval: u32, func: F) -> SourceId |
656 | where |
657 | F: FnMut() -> ControlFlow + 'static, |
658 | { |
659 | unsafe { |
660 | let context: MainContext = MainContext::default(); |
661 | let _acquire: MainContextAcquireGuard<'_> = context |
662 | .acquire() |
663 | .expect(msg:"default main context already acquired by another thread" ); |
664 | from_glib(val:ffi::g_timeout_add_seconds_full( |
665 | priority:ffi::G_PRIORITY_DEFAULT, |
666 | interval, |
667 | function:Some(trampoline_local::<F>), |
668 | data:into_raw_local(func), |
669 | notify:Some(destroy_closure_local::<F>), |
670 | )) |
671 | } |
672 | } |
673 | |
674 | // rustdoc-stripper-ignore-next |
675 | /// Adds a closure to be called by the default main loop at regular intervals |
676 | /// with second granularity. |
677 | /// |
678 | /// `func` will be called repeatedly every `interval` seconds until it |
679 | /// returns `ControlFlow::Break`. Precise timing is not guaranteed, the timeout may |
680 | /// be delayed by other events. |
681 | /// |
682 | /// The default main loop almost always is the main loop of the main thread. |
683 | /// Thus, the closure is called on the main thread. |
684 | /// |
685 | /// Different to `timeout_add_seconds()`, this does not require `func` to be |
686 | /// `Send` but can only be called from the thread that owns the main context. |
687 | /// |
688 | /// This function panics if called from a different thread than the one that |
689 | /// owns the main context. |
690 | /// |
691 | /// In comparison to `timeout_add_seconds_local()`, this only requires `func` to be |
692 | /// `FnOnce`, and will automatically return `ControlFlow::Break`. |
693 | #[doc (alias = "g_timeout_add_seconds_full" )] |
694 | pub fn timeout_add_seconds_local_once<F>(interval: u32, func: F) -> SourceId |
695 | where |
696 | F: FnOnce() + 'static, |
697 | { |
698 | timeout_add_seconds_local(interval, func:fnmut_callback_wrapper_local(func)) |
699 | } |
700 | |
701 | // rustdoc-stripper-ignore-next |
702 | /// Adds a closure to be called by the main loop the returned `Source` is attached to when a child |
703 | /// process exits. |
704 | /// |
705 | /// `func` will be called when `pid` exits |
706 | #[doc (alias = "g_child_watch_add_full" )] |
707 | pub fn child_watch_add<F>(pid: Pid, func: F) -> SourceId |
708 | where |
709 | F: FnMut(Pid, i32) + Send + 'static, |
710 | { |
711 | unsafe { |
712 | from_glib(val:ffi::g_child_watch_add_full( |
713 | priority:ffi::G_PRIORITY_DEFAULT, |
714 | pid:pid.0, |
715 | function:Some(trampoline_child_watch::<F>), |
716 | data:into_raw_child_watch(func), |
717 | notify:Some(destroy_closure_child_watch::<F>), |
718 | )) |
719 | } |
720 | } |
721 | |
722 | // rustdoc-stripper-ignore-next |
723 | /// Adds a closure to be called by the main loop the returned `Source` is attached to when a child |
724 | /// process exits. |
725 | /// |
726 | /// `func` will be called when `pid` exits |
727 | /// |
728 | /// Different to `child_watch_add()`, this does not require `func` to be |
729 | /// `Send` but can only be called from the thread that owns the main context. |
730 | /// |
731 | /// This function panics if called from a different thread than the one that |
732 | /// owns the main context. |
733 | #[doc (alias = "g_child_watch_add_full" )] |
734 | pub fn child_watch_add_local<F>(pid: Pid, func: F) -> SourceId |
735 | where |
736 | F: FnMut(Pid, i32) + 'static, |
737 | { |
738 | unsafe { |
739 | let context: MainContext = MainContext::default(); |
740 | let _acquire: MainContextAcquireGuard<'_> = context |
741 | .acquire() |
742 | .expect(msg:"default main context already acquired by another thread" ); |
743 | from_glib(val:ffi::g_child_watch_add_full( |
744 | priority:ffi::G_PRIORITY_DEFAULT, |
745 | pid:pid.0, |
746 | function:Some(trampoline_child_watch_local::<F>), |
747 | data:into_raw_child_watch_local(func), |
748 | notify:Some(destroy_closure_child_watch_local::<F>), |
749 | )) |
750 | } |
751 | } |
752 | |
753 | #[cfg (any(unix, docsrs))] |
754 | #[cfg_attr (docsrs, doc(cfg(unix)))] |
755 | // rustdoc-stripper-ignore-next |
756 | /// Adds a closure to be called by the default main loop whenever a UNIX signal is raised. |
757 | /// |
758 | /// `func` will be called repeatedly every time `signum` is raised until it |
759 | /// returns `ControlFlow::Break`. |
760 | /// |
761 | /// The default main loop almost always is the main loop of the main thread. |
762 | /// Thus, the closure is called on the main thread. |
763 | #[doc (alias = "g_unix_signal_add_full" )] |
764 | pub fn unix_signal_add<F>(signum: i32, func: F) -> SourceId |
765 | where |
766 | F: FnMut() -> ControlFlow + Send + 'static, |
767 | { |
768 | unsafe { |
769 | from_glib(val:ffi::g_unix_signal_add_full( |
770 | priority:ffi::G_PRIORITY_DEFAULT, |
771 | signum, |
772 | handler:Some(trampoline::<F>), |
773 | user_data:into_raw(func), |
774 | notify:Some(destroy_closure::<F>), |
775 | )) |
776 | } |
777 | } |
778 | |
779 | #[cfg (any(unix, docsrs))] |
780 | #[cfg_attr (docsrs, doc(cfg(unix)))] |
781 | // rustdoc-stripper-ignore-next |
782 | /// Adds a closure to be called by the default main loop whenever a UNIX signal is raised. |
783 | /// |
784 | /// `func` will be called repeatedly every time `signum` is raised until it |
785 | /// returns `ControlFlow::Break`. |
786 | /// |
787 | /// The default main loop almost always is the main loop of the main thread. |
788 | /// Thus, the closure is called on the main thread. |
789 | /// |
790 | /// In comparison to `unix_signal_add()`, this only requires `func` to be |
791 | /// `FnOnce`, and will automatically return `ControlFlow::Break`. |
792 | #[doc (alias = "g_unix_signal_add_full" )] |
793 | pub fn unix_signal_add_once<F>(signum: i32, func: F) -> SourceId |
794 | where |
795 | F: FnOnce() + Send + 'static, |
796 | { |
797 | unix_signal_add(signum, func:fnmut_callback_wrapper(func)) |
798 | } |
799 | |
800 | #[cfg (any(unix, docsrs))] |
801 | #[cfg_attr (docsrs, doc(cfg(unix)))] |
802 | // rustdoc-stripper-ignore-next |
803 | /// Adds a closure to be called by the default main loop whenever a UNIX signal is raised. |
804 | /// |
805 | /// `func` will be called repeatedly every time `signum` is raised until it |
806 | /// returns `ControlFlow::Break`. |
807 | /// |
808 | /// The default main loop almost always is the main loop of the main thread. |
809 | /// Thus, the closure is called on the main thread. |
810 | /// |
811 | /// Different to `unix_signal_add()`, this does not require `func` to be |
812 | /// `Send` but can only be called from the thread that owns the main context. |
813 | /// |
814 | /// This function panics if called from a different thread than the one that |
815 | /// owns the main context. |
816 | #[doc (alias = "g_unix_signal_add_full" )] |
817 | pub fn unix_signal_add_local<F>(signum: i32, func: F) -> SourceId |
818 | where |
819 | F: FnMut() -> ControlFlow + 'static, |
820 | { |
821 | unsafe { |
822 | let context: MainContext = MainContext::default(); |
823 | let _acquire: MainContextAcquireGuard<'_> = context |
824 | .acquire() |
825 | .expect(msg:"default main context already acquired by another thread" ); |
826 | from_glib(val:ffi::g_unix_signal_add_full( |
827 | priority:ffi::G_PRIORITY_DEFAULT, |
828 | signum, |
829 | handler:Some(trampoline_local::<F>), |
830 | user_data:into_raw_local(func), |
831 | notify:Some(destroy_closure_local::<F>), |
832 | )) |
833 | } |
834 | } |
835 | |
836 | #[cfg (any(unix, docsrs))] |
837 | #[cfg_attr (docsrs, doc(cfg(unix)))] |
838 | // rustdoc-stripper-ignore-next |
839 | /// Adds a closure to be called by the default main loop whenever a UNIX signal is raised. |
840 | /// |
841 | /// `func` will be called repeatedly every time `signum` is raised until it |
842 | /// returns `ControlFlow::Break`. |
843 | /// |
844 | /// The default main loop almost always is the main loop of the main thread. |
845 | /// Thus, the closure is called on the main thread. |
846 | /// |
847 | /// Different to `unix_signal_add()`, this does not require `func` to be |
848 | /// `Send` but can only be called from the thread that owns the main context. |
849 | /// |
850 | /// This function panics if called from a different thread than the one that |
851 | /// owns the main context. |
852 | /// |
853 | /// In comparison to `unix_signal_add_local()`, this only requires `func` to be |
854 | /// `FnOnce`, and will automatically return `ControlFlow::Break`. |
855 | #[doc (alias = "g_unix_signal_add_full" )] |
856 | pub fn unix_signal_add_local_once<F>(signum: i32, func: F) -> SourceId |
857 | where |
858 | F: FnOnce() + 'static, |
859 | { |
860 | unix_signal_add_local(signum, func:fnmut_callback_wrapper_local(func)) |
861 | } |
862 | |
863 | #[cfg (any(unix, docsrs))] |
864 | #[cfg_attr (docsrs, doc(cfg(unix)))] |
865 | // rustdoc-stripper-ignore-next |
866 | /// Adds a closure to be called by the main loop the returned `Source` is attached to whenever a |
867 | /// UNIX file descriptor reaches the given IO condition. |
868 | /// |
869 | /// `func` will be called repeatedly while the file descriptor matches the given IO condition |
870 | /// until it returns `ControlFlow::Break`. |
871 | /// |
872 | /// The default main loop almost always is the main loop of the main thread. |
873 | /// Thus, the closure is called on the main thread. |
874 | #[doc (alias = "g_unix_fd_add_full" )] |
875 | pub fn unix_fd_add<F>(fd: RawFd, condition: IOCondition, func: F) -> SourceId |
876 | where |
877 | F: FnMut(RawFd, IOCondition) -> ControlFlow + Send + 'static, |
878 | { |
879 | unsafe { |
880 | from_glib(val:ffi::g_unix_fd_add_full( |
881 | priority:ffi::G_PRIORITY_DEFAULT, |
882 | fd, |
883 | condition:condition.into_glib(), |
884 | function:Some(trampoline_unix_fd::<F>), |
885 | user_data:into_raw_unix_fd(func), |
886 | notify:Some(destroy_closure_unix_fd::<F>), |
887 | )) |
888 | } |
889 | } |
890 | |
891 | #[cfg (any(unix, docsrs))] |
892 | #[cfg_attr (docsrs, doc(cfg(unix)))] |
893 | // rustdoc-stripper-ignore-next |
894 | /// Adds a closure to be called by the main loop the returned `Source` is attached to whenever a |
895 | /// UNIX file descriptor reaches the given IO condition. |
896 | /// |
897 | /// `func` will be called repeatedly while the file descriptor matches the given IO condition |
898 | /// until it returns `ControlFlow::Break`. |
899 | /// |
900 | /// The default main loop almost always is the main loop of the main thread. |
901 | /// Thus, the closure is called on the main thread. |
902 | /// |
903 | /// Different to `unix_fd_add()`, this does not require `func` to be |
904 | /// `Send` but can only be called from the thread that owns the main context. |
905 | /// |
906 | /// This function panics if called from a different thread than the one that |
907 | /// owns the main context. |
908 | #[doc (alias = "g_unix_fd_add_full" )] |
909 | pub fn unix_fd_add_local<F>(fd: RawFd, condition: IOCondition, func: F) -> SourceId |
910 | where |
911 | F: FnMut(RawFd, IOCondition) -> ControlFlow + 'static, |
912 | { |
913 | unsafe { |
914 | let context: MainContext = MainContext::default(); |
915 | let _acquire: MainContextAcquireGuard<'_> = context |
916 | .acquire() |
917 | .expect(msg:"default main context already acquired by another thread" ); |
918 | from_glib(val:ffi::g_unix_fd_add_full( |
919 | priority:ffi::G_PRIORITY_DEFAULT, |
920 | fd, |
921 | condition:condition.into_glib(), |
922 | function:Some(trampoline_unix_fd_local::<F>), |
923 | user_data:into_raw_unix_fd_local(func), |
924 | notify:Some(destroy_closure_unix_fd_local::<F>), |
925 | )) |
926 | } |
927 | } |
928 | |
929 | // rustdoc-stripper-ignore-next |
930 | /// The priority of sources |
931 | #[derive (Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)] |
932 | pub struct Priority(i32); |
933 | |
934 | impl Priority { |
935 | #[doc (alias = "G_PRIORITY_HIGH" )] |
936 | pub const HIGH: Self = Self(ffi::G_PRIORITY_HIGH); |
937 | #[doc (alias = "G_PRIORITY_DEFAULT" )] |
938 | pub const DEFAULT: Self = Self(ffi::G_PRIORITY_DEFAULT); |
939 | #[doc (alias = "G_PRIORITY_HIGH_IDLE" )] |
940 | pub const HIGH_IDLE: Self = Self(ffi::G_PRIORITY_HIGH_IDLE); |
941 | #[doc (alias = "G_PRIORITY_DEFAULT_IDLE" )] |
942 | pub const DEFAULT_IDLE: Self = Self(ffi::G_PRIORITY_DEFAULT_IDLE); |
943 | #[doc (alias = "G_PRIORITY_LOW" )] |
944 | pub const LOW: Self = Self(ffi::G_PRIORITY_LOW); |
945 | } |
946 | |
947 | impl Default for Priority { |
948 | fn default() -> Self { |
949 | Self::DEFAULT |
950 | } |
951 | } |
952 | |
953 | #[doc (hidden)] |
954 | impl IntoGlib for Priority { |
955 | type GlibType = i32; |
956 | |
957 | #[inline ] |
958 | fn into_glib(self) -> i32 { |
959 | self.0 |
960 | } |
961 | } |
962 | |
963 | #[doc (hidden)] |
964 | impl FromGlib<i32> for Priority { |
965 | #[inline ] |
966 | unsafe fn from_glib(val: i32) -> Self { |
967 | Self::from(val) |
968 | } |
969 | } |
970 | |
971 | impl From<i32> for Priority { |
972 | fn from(value: i32) -> Self { |
973 | Self(value) |
974 | } |
975 | } |
976 | |
977 | // rustdoc-stripper-ignore-next |
978 | /// Adds a closure to be called by the main loop the return `Source` is attached to when it's idle. |
979 | /// |
980 | /// `func` will be called repeatedly until it returns `ControlFlow::Break`. |
981 | #[doc (alias = "g_idle_source_new" )] |
982 | pub fn idle_source_new<F>(name: Option<&str>, priority: Priority, func: F) -> Source |
983 | where |
984 | F: FnMut() -> ControlFlow + Send + 'static, |
985 | { |
986 | unsafe { |
987 | let source: *mut GSource = ffi::g_idle_source_new(); |
988 | ffi::g_source_set_callback( |
989 | source, |
990 | func:Some(trampoline::<F>), |
991 | data:into_raw(func), |
992 | notify:Some(destroy_closure::<F>), |
993 | ); |
994 | ffi::g_source_set_priority(source, priority:priority.into_glib()); |
995 | |
996 | if let Some(name: &str) = name { |
997 | ffi::g_source_set_name(source, name:name.to_glib_none().0); |
998 | } |
999 | |
1000 | from_glib_full(ptr:source) |
1001 | } |
1002 | } |
1003 | |
1004 | // rustdoc-stripper-ignore-next |
1005 | /// Adds a closure to be called by the main loop the returned `Source` is attached to at regular |
1006 | /// intervals with millisecond granularity. |
1007 | /// |
1008 | /// `func` will be called repeatedly every `interval` milliseconds until it |
1009 | /// returns `ControlFlow::Break`. Precise timing is not guaranteed, the timeout may |
1010 | /// be delayed by other events. Prefer `timeout_add_seconds` when millisecond |
1011 | /// precision is not necessary. |
1012 | #[doc (alias = "g_timeout_source_new" )] |
1013 | pub fn timeout_source_new<F>( |
1014 | interval: Duration, |
1015 | name: Option<&str>, |
1016 | priority: Priority, |
1017 | func: F, |
1018 | ) -> Source |
1019 | where |
1020 | F: FnMut() -> ControlFlow + Send + 'static, |
1021 | { |
1022 | unsafe { |
1023 | let source: *mut GSource = ffi::g_timeout_source_new(interval:interval.as_millis() as _); |
1024 | ffi::g_source_set_callback( |
1025 | source, |
1026 | func:Some(trampoline::<F>), |
1027 | data:into_raw(func), |
1028 | notify:Some(destroy_closure::<F>), |
1029 | ); |
1030 | ffi::g_source_set_priority(source, priority:priority.into_glib()); |
1031 | |
1032 | if let Some(name: &str) = name { |
1033 | ffi::g_source_set_name(source, name:name.to_glib_none().0); |
1034 | } |
1035 | |
1036 | from_glib_full(ptr:source) |
1037 | } |
1038 | } |
1039 | |
1040 | // rustdoc-stripper-ignore-next |
1041 | /// Adds a closure to be called by the main loop the returned `Source` is attached to at regular |
1042 | /// intervals with second granularity. |
1043 | /// |
1044 | /// `func` will be called repeatedly every `interval` seconds until it |
1045 | /// returns `ControlFlow::Break`. Precise timing is not guaranteed, the timeout may |
1046 | /// be delayed by other events. |
1047 | #[doc (alias = "g_timeout_source_new_seconds" )] |
1048 | pub fn timeout_source_new_seconds<F>( |
1049 | interval: u32, |
1050 | name: Option<&str>, |
1051 | priority: Priority, |
1052 | func: F, |
1053 | ) -> Source |
1054 | where |
1055 | F: FnMut() -> ControlFlow + Send + 'static, |
1056 | { |
1057 | unsafe { |
1058 | let source: *mut GSource = ffi::g_timeout_source_new_seconds(interval); |
1059 | ffi::g_source_set_callback( |
1060 | source, |
1061 | func:Some(trampoline::<F>), |
1062 | data:into_raw(func), |
1063 | notify:Some(destroy_closure::<F>), |
1064 | ); |
1065 | ffi::g_source_set_priority(source, priority:priority.into_glib()); |
1066 | |
1067 | if let Some(name: &str) = name { |
1068 | ffi::g_source_set_name(source, name:name.to_glib_none().0); |
1069 | } |
1070 | |
1071 | from_glib_full(ptr:source) |
1072 | } |
1073 | } |
1074 | |
1075 | // rustdoc-stripper-ignore-next |
1076 | /// Adds a closure to be called by the main loop the returned `Source` is attached to when a child |
1077 | /// process exits. |
1078 | /// |
1079 | /// `func` will be called when `pid` exits |
1080 | #[doc (alias = "g_child_watch_source_new" )] |
1081 | pub fn child_watch_source_new<F>( |
1082 | pid: Pid, |
1083 | name: Option<&str>, |
1084 | priority: Priority, |
1085 | func: F, |
1086 | ) -> Source |
1087 | where |
1088 | F: FnMut(Pid, i32) + Send + 'static, |
1089 | { |
1090 | unsafe { |
1091 | let source: *mut GSource = ffi::g_child_watch_source_new(pid:pid.0); |
1092 | ffi::g_source_set_callback( |
1093 | source, |
1094 | func:Some(transmute::< |
1095 | _, |
1096 | unsafe extern "C" fn(ffi::gpointer) -> ffi::gboolean, |
1097 | >(trampoline_child_watch::<F> as *const ())), |
1098 | data:into_raw_child_watch(func), |
1099 | notify:Some(destroy_closure_child_watch::<F>), |
1100 | ); |
1101 | ffi::g_source_set_priority(source, priority:priority.into_glib()); |
1102 | |
1103 | if let Some(name: &str) = name { |
1104 | ffi::g_source_set_name(source, name:name.to_glib_none().0); |
1105 | } |
1106 | |
1107 | from_glib_full(ptr:source) |
1108 | } |
1109 | } |
1110 | |
1111 | #[cfg (any(unix, docsrs))] |
1112 | #[cfg_attr (docsrs, doc(cfg(unix)))] |
1113 | // rustdoc-stripper-ignore-next |
1114 | /// Adds a closure to be called by the main loop the returned `Source` is attached to whenever a |
1115 | /// UNIX signal is raised. |
1116 | /// |
1117 | /// `func` will be called repeatedly every time `signum` is raised until it |
1118 | /// returns `ControlFlow::Break`. |
1119 | #[doc (alias = "g_unix_signal_source_new" )] |
1120 | pub fn unix_signal_source_new<F>( |
1121 | signum: i32, |
1122 | name: Option<&str>, |
1123 | priority: Priority, |
1124 | func: F, |
1125 | ) -> Source |
1126 | where |
1127 | F: FnMut() -> ControlFlow + Send + 'static, |
1128 | { |
1129 | unsafe { |
1130 | let source: *mut GSource = ffi::g_unix_signal_source_new(signum); |
1131 | ffi::g_source_set_callback( |
1132 | source, |
1133 | func:Some(trampoline::<F>), |
1134 | data:into_raw(func), |
1135 | notify:Some(destroy_closure::<F>), |
1136 | ); |
1137 | ffi::g_source_set_priority(source, priority:priority.into_glib()); |
1138 | |
1139 | if let Some(name: &str) = name { |
1140 | ffi::g_source_set_name(source, name:name.to_glib_none().0); |
1141 | } |
1142 | |
1143 | from_glib_full(ptr:source) |
1144 | } |
1145 | } |
1146 | |
1147 | #[cfg (any(unix, docsrs))] |
1148 | #[cfg_attr (docsrs, doc(cfg(unix)))] |
1149 | // rustdoc-stripper-ignore-next |
1150 | /// Adds a closure to be called by the main loop the returned `Source` is attached to whenever a |
1151 | /// UNIX file descriptor reaches the given IO condition. |
1152 | /// |
1153 | /// `func` will be called repeatedly while the file descriptor matches the given IO condition |
1154 | /// until it returns `ControlFlow::Break`. |
1155 | #[doc (alias = "g_unix_fd_source_new" )] |
1156 | pub fn unix_fd_source_new<F>( |
1157 | fd: RawFd, |
1158 | condition: IOCondition, |
1159 | name: Option<&str>, |
1160 | priority: Priority, |
1161 | func: F, |
1162 | ) -> Source |
1163 | where |
1164 | F: FnMut(RawFd, IOCondition) -> ControlFlow + Send + 'static, |
1165 | { |
1166 | unsafe { |
1167 | let source: *mut GSource = ffi::g_unix_fd_source_new(fd, condition:condition.into_glib()); |
1168 | ffi::g_source_set_callback( |
1169 | source, |
1170 | func:Some(transmute::< |
1171 | _, |
1172 | unsafe extern "C" fn(ffi::gpointer) -> ffi::gboolean, |
1173 | >(trampoline_unix_fd::<F> as *const ())), |
1174 | data:into_raw_unix_fd(func), |
1175 | notify:Some(destroy_closure_unix_fd::<F>), |
1176 | ); |
1177 | ffi::g_source_set_priority(source, priority:priority.into_glib()); |
1178 | |
1179 | if let Some(name: &str) = name { |
1180 | ffi::g_source_set_name(source, name:name.to_glib_none().0); |
1181 | } |
1182 | |
1183 | from_glib_full(ptr:source) |
1184 | } |
1185 | } |
1186 | |
1187 | impl Source { |
1188 | #[doc (alias = "g_source_attach" )] |
1189 | pub fn attach(&self, context: Option<&MainContext>) -> SourceId { |
1190 | unsafe { |
1191 | from_glib(val:ffi::g_source_attach( |
1192 | self.to_glib_none().0, |
1193 | context:context.to_glib_none().0, |
1194 | )) |
1195 | } |
1196 | } |
1197 | } |
1198 | |