Skip to content
This repository was archived by the owner on Jun 8, 2021. It is now read-only.

Commit 5bbdaad

Browse files
committed
Add _local() variants for all of the GSources that add themselves to the default main context
1 parent 7f1351a commit 5bbdaad

File tree

1 file changed

+145
-6
lines changed

1 file changed

+145
-6
lines changed

src/source.rs

Lines changed: 145 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use translate::{from_glib, from_glib_full, FromGlib, ToGlib, ToGlibPtr};
1818
use libc;
1919

2020
use Source;
21+
use MainContext;
2122

2223
/// The id of a source that is returned by `idle_add` and `timeout_add`.
2324
#[derive(Debug, Eq, PartialEq)]
@@ -108,8 +109,8 @@ unsafe extern "C" fn destroy_closure(ptr: gpointer) {
108109
Box::<RefCell<Box<FnMut() -> Continue + 'static>>>::from_raw(ptr as *mut _);
109110
}
110111

111-
fn into_raw<F: FnMut() -> Continue + Send + 'static>(func: F) -> gpointer {
112-
let func: Box<RefCell<Box<FnMut() -> Continue + Send + 'static>>> =
112+
fn into_raw<F: FnMut() -> Continue + 'static>(func: F) -> gpointer {
113+
let func: Box<RefCell<Box<FnMut() -> Continue + 'static>>> =
113114
Box::new(RefCell::new(Box::new(func)));
114115
Box::into_raw(func) as gpointer
115116
}
@@ -125,8 +126,8 @@ unsafe extern "C" fn destroy_closure_child_watch(ptr: gpointer) {
125126
}
126127

127128
#[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
128-
fn into_raw_child_watch<F: FnMut(Pid, i32) + Send + 'static>(func: F) -> gpointer {
129-
let func: Box<RefCell<Box<FnMut(Pid, i32) + Send + 'static>>> =
129+
fn into_raw_child_watch<F: FnMut(Pid, i32) + 'static>(func: F) -> gpointer {
130+
let func: Box<RefCell<Box<FnMut(Pid, i32) + 'static>>> =
130131
Box::new(RefCell::new(Box::new(func)));
131132
Box::into_raw(func) as gpointer
132133
}
@@ -144,8 +145,8 @@ unsafe extern "C" fn destroy_closure_unix_fd(ptr: gpointer) {
144145
}
145146

146147
#[cfg(any(unix, feature = "dox"))]
147-
fn into_raw_unix_fd<F: FnMut(RawFd, IOCondition) -> Continue + Send + 'static>(func: F) -> gpointer {
148-
let func: Box<RefCell<Box<FnMut(RawFd, IOCondition) -> Continue + Send + 'static>>> =
148+
fn into_raw_unix_fd<F: FnMut(RawFd, IOCondition) -> Continue + 'static>(func: F) -> gpointer {
149+
let func: Box<RefCell<Box<FnMut(RawFd, IOCondition) -> Continue + 'static>>> =
149150
Box::new(RefCell::new(Box::new(func)));
150151
Box::into_raw(func) as gpointer
151152
}
@@ -164,6 +165,27 @@ where F: FnMut() -> Continue + Send + 'static {
164165
}
165166
}
166167

168+
/// Adds a closure to be called by the default main loop when it's idle.
169+
///
170+
/// `func` will be called repeatedly until it returns `Continue(false)`.
171+
///
172+
/// The default main loop almost always is the main loop of the main thread.
173+
/// Thus the closure is called on the main thread.
174+
///
175+
/// Different to `idle_add()`, this does not require `func` to be
176+
/// `Send` but can only be called from the thread that owns the main context.
177+
///
178+
/// This function panics if called from a different thread than the one that
179+
/// owns the main context.
180+
pub fn idle_add_local<F>(func: F) -> SourceId
181+
where F: FnMut() -> Continue + 'static {
182+
unsafe {
183+
assert!(MainContext::default().is_owner());
184+
from_glib(glib_ffi::g_idle_add_full(glib_ffi::G_PRIORITY_DEFAULT_IDLE, Some(trampoline),
185+
into_raw(func), Some(destroy_closure)))
186+
}
187+
}
188+
167189
/// Adds a closure to be called by the default main loop at regular intervals
168190
/// with millisecond granularity.
169191
///
@@ -182,6 +204,31 @@ where F: FnMut() -> Continue + Send + 'static {
182204
}
183205
}
184206

207+
/// Adds a closure to be called by the default main loop at regular intervals
208+
/// with millisecond granularity.
209+
///
210+
/// `func` will be called repeatedly every `interval` milliseconds until it
211+
/// returns `Continue(false)`. Precise timing is not guaranteed, the timeout may
212+
/// be delayed by other events. Prefer `timeout_add_seconds` when millisecond
213+
/// precision is not necessary.
214+
///
215+
/// The default main loop almost always is the main loop of the main thread.
216+
/// Thus the closure is called on the main thread.
217+
///
218+
/// Different to `timeout_add()`, this does not require `func` to be
219+
/// `Send` but can only be called from the thread that owns the main context.
220+
///
221+
/// This function panics if called from a different thread than the one that
222+
/// owns the main context.
223+
pub fn timeout_add_local<F>(interval: u32, func: F) -> SourceId
224+
where F: FnMut() -> Continue + 'static {
225+
unsafe {
226+
assert!(MainContext::default().is_owner());
227+
from_glib(glib_ffi::g_timeout_add_full(glib_ffi::G_PRIORITY_DEFAULT, interval,
228+
Some(trampoline), into_raw(func), Some(destroy_closure)))
229+
}
230+
}
231+
185232
/// Adds a closure to be called by the default main loop at regular intervals
186233
/// with second granularity.
187234
///
@@ -199,6 +246,30 @@ where F: FnMut() -> Continue + Send + 'static {
199246
}
200247
}
201248

249+
/// Adds a closure to be called by the default main loop at regular intervals
250+
/// with second granularity.
251+
///
252+
/// `func` will be called repeatedly every `interval` seconds until it
253+
/// returns `Continue(false)`. Precise timing is not guaranteed, the timeout may
254+
/// be delayed by other events.
255+
///
256+
/// The default main loop almost always is the main loop of the main thread.
257+
/// Thus the closure is called on the main thread.
258+
///
259+
/// Different to `timeout_add_seconds()`, this does not require `func` to be
260+
/// `Send` but can only be called from the thread that owns the main context.
261+
///
262+
/// This function panics if called from a different thread than the one that
263+
/// owns the main context.
264+
pub fn timeout_add_seconds_local<F>(interval: u32, func: F) -> SourceId
265+
where F: FnMut() -> Continue + 'static {
266+
unsafe {
267+
assert!(MainContext::default().is_owner());
268+
from_glib(glib_ffi::g_timeout_add_seconds_full(glib_ffi::G_PRIORITY_DEFAULT, interval,
269+
Some(trampoline), into_raw(func), Some(destroy_closure)))
270+
}
271+
}
272+
202273
/// Adds a closure to be called by the main loop the returned `Source` is attached to when a child
203274
/// process exits.
204275
///
@@ -212,6 +283,26 @@ where F: FnMut(Pid, i32) + Send + 'static {
212283
}
213284
}
214285

286+
/// Adds a closure to be called by the main loop the returned `Source` is attached to when a child
287+
/// process exits.
288+
///
289+
/// `func` will be called when `pid` exits
290+
///
291+
/// Different to `child_watch_add()`, this does not require `func` to be
292+
/// `Send` but can only be called from the thread that owns the main context.
293+
///
294+
/// This function panics if called from a different thread than the one that
295+
/// owns the main context.
296+
pub fn child_watch_add_local<'a, N: Into<Option<&'a str>>, F>(pid: Pid, func: F) -> SourceId
297+
where F: FnMut(Pid, i32) + 'static {
298+
unsafe {
299+
assert!(MainContext::default().is_owner());
300+
let trampoline = trampoline_child_watch as *mut libc::c_void;
301+
from_glib(glib_ffi::g_child_watch_add_full(glib_ffi::G_PRIORITY_DEFAULT, pid.0,
302+
Some(transmute(trampoline)), into_raw_child_watch(func), Some(destroy_closure_child_watch)))
303+
}
304+
}
305+
215306
#[cfg(any(unix, feature = "dox"))]
216307
/// Adds a closure to be called by the default main loop whenever a UNIX signal is raised.
217308
///
@@ -228,6 +319,29 @@ where F: FnMut() -> Continue + Send + 'static {
228319
}
229320
}
230321

322+
#[cfg(any(unix, feature = "dox"))]
323+
/// Adds a closure to be called by the default main loop whenever a UNIX signal is raised.
324+
///
325+
/// `func` will be called repeatedly every time `signum` is raised until it
326+
/// returns `Continue(false)`.
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 `unix_signal_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 main context.
336+
pub fn unix_signal_add_local<F>(signum: i32, func: F) -> SourceId
337+
where F: FnMut() -> Continue + 'static {
338+
unsafe {
339+
assert!(MainContext::default().is_owner());
340+
from_glib(glib_ffi::g_unix_signal_add_full(glib_ffi::G_PRIORITY_DEFAULT, signum,
341+
Some(trampoline), into_raw(func), Some(destroy_closure)))
342+
}
343+
}
344+
231345
#[cfg(any(unix, feature = "dox"))]
232346
/// Adds a closure to be called by the main loop the returned `Source` is attached to whenever a
233347
/// UNIX file descriptor reaches the given IO condition.
@@ -246,6 +360,31 @@ where F: FnMut(RawFd, IOCondition) -> Continue + Send + 'static {
246360
}
247361
}
248362

363+
#[cfg(any(unix, feature = "dox"))]
364+
/// Adds a closure to be called by the main loop the returned `Source` is attached to whenever a
365+
/// UNIX file descriptor reaches the given IO condition.
366+
///
367+
/// `func` will be called repeatedly while the file descriptor matches the given IO condition
368+
/// until it returns `Continue(false)`.
369+
///
370+
/// The default main loop almost always is the main loop of the main thread.
371+
/// Thus the closure is called on the main thread.
372+
///
373+
/// Different to `unix_fd_add()`, this does not require `func` to be
374+
/// `Send` but can only be called from the thread that owns the main context.
375+
///
376+
/// This function panics if called from a different thread than the one that
377+
/// owns the main context.
378+
pub fn unix_fd_add_local<F>(fd: RawFd, condition: IOCondition, func: F) -> SourceId
379+
where F: FnMut(RawFd, IOCondition) -> Continue + 'static {
380+
unsafe {
381+
assert!(MainContext::default().is_owner());
382+
let trampoline = trampoline_unix_fd as *mut libc::c_void;
383+
from_glib(glib_ffi::g_unix_fd_add_full(glib_ffi::G_PRIORITY_DEFAULT, fd, condition.to_glib(),
384+
Some(transmute(trampoline)), into_raw_unix_fd(func), Some(destroy_closure_unix_fd)))
385+
}
386+
}
387+
249388
/// Removes the source with the given id `source_id` from the default main context.
250389
///
251390
/// It is a programmer error to attempt to remove a non-existent source.

0 commit comments

Comments
 (0)