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

Commit

Permalink
Add _local() variants for all of the GSources that add themselves to …
Browse files Browse the repository at this point in the history
…the default main context
  • Loading branch information
sdroege committed Feb 10, 2019
1 parent 7f1351a commit 5bbdaad
Showing 1 changed file with 145 additions and 6 deletions.
151 changes: 145 additions & 6 deletions src/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use translate::{from_glib, from_glib_full, FromGlib, ToGlib, ToGlibPtr};
use libc;

use Source;
use MainContext;

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

fn into_raw<F: FnMut() -> Continue + Send + 'static>(func: F) -> gpointer {
let func: Box<RefCell<Box<FnMut() -> Continue + Send + 'static>>> =
fn into_raw<F: FnMut() -> Continue + 'static>(func: F) -> gpointer {
let func: Box<RefCell<Box<FnMut() -> Continue + 'static>>> =
Box::new(RefCell::new(Box::new(func)));
Box::into_raw(func) as gpointer
}
Expand All @@ -125,8 +126,8 @@ unsafe extern "C" fn destroy_closure_child_watch(ptr: gpointer) {
}

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

#[cfg(any(unix, feature = "dox"))]
fn into_raw_unix_fd<F: FnMut(RawFd, IOCondition) -> Continue + Send + 'static>(func: F) -> gpointer {
let func: Box<RefCell<Box<FnMut(RawFd, IOCondition) -> Continue + Send + 'static>>> =
fn into_raw_unix_fd<F: FnMut(RawFd, IOCondition) -> Continue + 'static>(func: F) -> gpointer {
let func: Box<RefCell<Box<FnMut(RawFd, IOCondition) -> Continue + 'static>>> =
Box::new(RefCell::new(Box::new(func)));
Box::into_raw(func) as gpointer
}
Expand All @@ -164,6 +165,27 @@ where F: FnMut() -> Continue + Send + 'static {
}
}

/// Adds a closure to be called by the default main loop when it's idle.
///
/// `func` will be called repeatedly until it returns `Continue(false)`.
///
/// The default main loop almost always is the main loop of the main thread.
/// Thus the closure is called on the main thread.
///
/// Different to `idle_add()`, this does not require `func` to be
/// `Send` but can only be called from the thread that owns the main context.
///
/// This function panics if called from a different thread than the one that
/// owns the main context.
pub fn idle_add_local<F>(func: F) -> SourceId
where F: FnMut() -> Continue + 'static {
unsafe {
assert!(MainContext::default().is_owner());
from_glib(glib_ffi::g_idle_add_full(glib_ffi::G_PRIORITY_DEFAULT_IDLE, Some(trampoline),
into_raw(func), Some(destroy_closure)))
}
}

/// Adds a closure to be called by the default main loop at regular intervals
/// with millisecond granularity.
///
Expand All @@ -182,6 +204,31 @@ where F: FnMut() -> Continue + Send + 'static {
}
}

/// Adds a closure to be called by the default main loop at regular intervals
/// with millisecond granularity.
///
/// `func` will be called repeatedly every `interval` milliseconds until it
/// returns `Continue(false)`. Precise timing is not guaranteed, the timeout may
/// be delayed by other events. Prefer `timeout_add_seconds` when millisecond
/// precision is not necessary.
///
/// The default main loop almost always is the main loop of the main thread.
/// Thus the closure is called on the main thread.
///
/// Different to `timeout_add()`, this does not require `func` to be
/// `Send` but can only be called from the thread that owns the main context.
///
/// This function panics if called from a different thread than the one that
/// owns the main context.
pub fn timeout_add_local<F>(interval: u32, func: F) -> SourceId
where F: FnMut() -> Continue + 'static {
unsafe {
assert!(MainContext::default().is_owner());
from_glib(glib_ffi::g_timeout_add_full(glib_ffi::G_PRIORITY_DEFAULT, interval,
Some(trampoline), into_raw(func), Some(destroy_closure)))
}
}

/// Adds a closure to be called by the default main loop at regular intervals
/// with second granularity.
///
Expand All @@ -199,6 +246,30 @@ where F: FnMut() -> Continue + Send + 'static {
}
}

/// Adds a closure to be called by the default main loop at regular intervals
/// with second granularity.
///
/// `func` will be called repeatedly every `interval` seconds until it
/// returns `Continue(false)`. Precise timing is not guaranteed, the timeout may
/// be delayed by other events.
///
/// The default main loop almost always is the main loop of the main thread.
/// Thus the closure is called on the main thread.
///
/// Different to `timeout_add_seconds()`, this does not require `func` to be
/// `Send` but can only be called from the thread that owns the main context.
///
/// This function panics if called from a different thread than the one that
/// owns the main context.
pub fn timeout_add_seconds_local<F>(interval: u32, func: F) -> SourceId
where F: FnMut() -> Continue + 'static {
unsafe {
assert!(MainContext::default().is_owner());
from_glib(glib_ffi::g_timeout_add_seconds_full(glib_ffi::G_PRIORITY_DEFAULT, interval,
Some(trampoline), into_raw(func), Some(destroy_closure)))
}
}

/// Adds a closure to be called by the main loop the returned `Source` is attached to when a child
/// process exits.
///
Expand All @@ -212,6 +283,26 @@ where F: FnMut(Pid, i32) + Send + 'static {
}
}

/// Adds a closure to be called by the main loop the returned `Source` is attached to when a child
/// process exits.
///
/// `func` will be called when `pid` exits
///
/// Different to `child_watch_add()`, this does not require `func` to be
/// `Send` but can only be called from the thread that owns the main context.
///
/// This function panics if called from a different thread than the one that
/// owns the main context.
pub fn child_watch_add_local<'a, N: Into<Option<&'a str>>, F>(pid: Pid, func: F) -> SourceId
where F: FnMut(Pid, i32) + 'static {
unsafe {
assert!(MainContext::default().is_owner());
let trampoline = trampoline_child_watch as *mut libc::c_void;
from_glib(glib_ffi::g_child_watch_add_full(glib_ffi::G_PRIORITY_DEFAULT, pid.0,
Some(transmute(trampoline)), into_raw_child_watch(func), Some(destroy_closure_child_watch)))
}
}

#[cfg(any(unix, feature = "dox"))]
/// Adds a closure to be called by the default main loop whenever a UNIX signal is raised.
///
Expand All @@ -228,6 +319,29 @@ where F: FnMut() -> Continue + Send + 'static {
}
}

#[cfg(any(unix, feature = "dox"))]
/// Adds a closure to be called by the default main loop whenever a UNIX signal is raised.
///
/// `func` will be called repeatedly every time `signum` is raised until it
/// returns `Continue(false)`.
///
/// The default main loop almost always is the main loop of the main thread.
/// Thus the closure is called on the main thread.
///
/// Different to `unix_signal_add()`, this does not require `func` to be
/// `Send` but can only be called from the thread that owns the main context.
///
/// This function panics if called from a different thread than the one that
/// owns the main context.
pub fn unix_signal_add_local<F>(signum: i32, func: F) -> SourceId
where F: FnMut() -> Continue + 'static {
unsafe {
assert!(MainContext::default().is_owner());
from_glib(glib_ffi::g_unix_signal_add_full(glib_ffi::G_PRIORITY_DEFAULT, signum,
Some(trampoline), into_raw(func), Some(destroy_closure)))
}
}

#[cfg(any(unix, feature = "dox"))]
/// Adds a closure to be called by the main loop the returned `Source` is attached to whenever a
/// UNIX file descriptor reaches the given IO condition.
Expand All @@ -246,6 +360,31 @@ where F: FnMut(RawFd, IOCondition) -> Continue + Send + 'static {
}
}

#[cfg(any(unix, feature = "dox"))]
/// Adds a closure to be called by the main loop the returned `Source` is attached to whenever a
/// UNIX file descriptor reaches the given IO condition.
///
/// `func` will be called repeatedly while the file descriptor matches the given IO condition
/// until it returns `Continue(false)`.
///
/// The default main loop almost always is the main loop of the main thread.
/// Thus the closure is called on the main thread.
///
/// Different to `unix_fd_add()`, this does not require `func` to be
/// `Send` but can only be called from the thread that owns the main context.
///
/// This function panics if called from a different thread than the one that
/// owns the main context.
pub fn unix_fd_add_local<F>(fd: RawFd, condition: IOCondition, func: F) -> SourceId
where F: FnMut(RawFd, IOCondition) -> Continue + 'static {
unsafe {
assert!(MainContext::default().is_owner());
let trampoline = trampoline_unix_fd as *mut libc::c_void;
from_glib(glib_ffi::g_unix_fd_add_full(glib_ffi::G_PRIORITY_DEFAULT, fd, condition.to_glib(),
Some(transmute(trampoline)), into_raw_unix_fd(func), Some(destroy_closure_unix_fd)))
}
}

/// Removes the source with the given id `source_id` from the default main context.
///
/// It is a programmer error to attempt to remove a non-existent source.
Expand Down

0 comments on commit 5bbdaad

Please sign in to comment.