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

Add g_idle_add() #47

Merged
merged 8 commits into from
Jun 19, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions glib-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub type gpointer = *mut c_void;
pub type GSourceFunc = extern "C" fn(user_data: gpointer) -> gboolean;
pub type GCallback = extern "C" fn();
pub type GClosureNotify = extern "C" fn(data: gpointer, closure: gpointer);
pub type GDestroyNotify = extern "C" fn(data: gpointer);

#[repr(C)]
pub struct GAppInfo;
Expand Down Expand Up @@ -75,9 +76,9 @@ pub struct GPid;
pub struct GPollFD;

/// Represents a day between January 1, Year 1 and a few thousand years in the future. None of its members should be accessed directly.
///
///
/// If the GDate is obtained from g_date_new(), it will be safe to mutate but invalid and thus not safe for calendrical computations.
///
///
/// If it's declared on the stack, it will contain garbage so must be initialized with g_date_clear(). g_date_clear() makes the date
/// invalid but sane. An invalid date doesn't represent a day, it's "empty." A date becomes valid after you set it to a Julian day or
/// you set a day, month, and year.
Expand Down Expand Up @@ -348,14 +349,12 @@ extern "C" {
pub fn g_timeout_source_new () -> *mut GSource;
pub fn g_timeout_source_new_seconds (interval: c_uint) -> *mut GSource;
//pub fn g_timeout_add (interval: c_uint, function: GSourceFunc, data: gpointer) -> c_uint;
pub fn g_timeout_add (interval: c_uint, function: gpointer, data: gpointer) -> c_uint;
//pub fn g_timeout_add_full ();
pub fn g_timeout_add_full (priority: c_int, interval: c_uint, function: GSourceFunc, data: gpointer, notify: GDestroyNotify) -> c_uint;
//pub fn g_timeout_add_seconds (interval: c_uint, function: GSourceFunc, data: gpointer) -> c_uint;
pub fn g_timeout_add_seconds (interval: c_uint, function: gpointer, data: gpointer) -> c_uint;
//pub fn g_timeout_add_seconds_full ();
pub fn g_timeout_add_seconds_full (priority: c_int, interval: c_uint, function: GSourceFunc, data: gpointer, notify: GDestroyNotify) -> c_uint;
pub fn g_idle_source_new () -> *mut GSource;
//pub fn g_idle_add ();
//pub fn g_idle_add_full ();
// pub fn g_idle_add (function: GSourceFunc, data: gpointer) -> c_uint;
pub fn g_idle_add_full (priority: c_int, function: GSourceFunc, data: gpointer, notify: GDestroyNotify) -> c_uint;
pub fn g_idle_remove_by_data (data: gpointer) -> gboolean;
pub fn g_child_watch_source_new (pid: GPid) -> *mut GSource;
//pub fn g_child_watch_add ();
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub use self::slist::{SList, SElem};
pub use self::glib_container::GlibContainer;
pub use self::error::{Error};
pub use self::permission::Permission;
pub use self::timeout_func::timeout;
pub use self::source::{Continue, idle_add, timeout_add, timeout_add_seconds};
pub use self::traits::FFIGObject;
pub use self::value::{Value, ValuePublic};
pub use types::Type;
Expand All @@ -32,7 +32,7 @@ pub mod glib_container;
mod error;
mod permission;
pub mod signal;
pub mod timeout_func;
pub mod source;
pub mod traits;
pub mod translate;
mod value;
Expand Down
134 changes: 134 additions & 0 deletions src/source.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// Copyright 2013-2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! Manages available sources of events for the main loop

use std::cell::RefCell;
use std::ops::DerefMut;
use std::mem::transmute;
use ffi::{gboolean, gpointer, g_idle_add_full, g_timeout_add_full, g_timeout_add_seconds_full};
use translate::ToGlib;

/// Return type of idle and timeout functions.
///
/// In the callback, return `Continue(true)` to continue scheduling the callback
/// in the main loop or `Continue(false)` to remove it from the main loop.
pub struct Continue(pub bool);

impl ToGlib for Continue {
type GlibType = gboolean;

#[inline]
fn to_glib(&self) -> gboolean {
self.0.to_glib()
}
}


// Box::into_raw stability workaround
unsafe fn into_raw<T>(b: Box<T>) -> *mut T { transmute(b) }

extern "C" fn trampoline(func: &RefCell<Box<FnMut() -> Continue + 'static>>) -> gboolean {
func.borrow_mut().deref_mut()().to_glib()
}

extern "C" fn destroy_closure(ptr: gpointer) {
unsafe {
// Box::from_raw API stability workaround
let ptr = ptr as *mut RefCell<Box<FnMut() -> Continue + 'static>>;
let _: Box<RefCell<Box<FnMut() -> Continue + 'static>>> = transmute(ptr);
}
}

const PRIORITY_DEFAULT: i32 = 0;
const PRIORITY_DEFAULT_IDLE: i32 = 200;


/// Adds a function to be called whenever there are no higher priority events pending to the default main loop.
///
/// The function is given the default idle priority, `PRIORITY_DEFAULT_IDLE`.
/// If the function returns `Continue(false)` it is automatically removed from
/// the list of event sources and will not be called again.
///
/// # Examples
///
/// ```ignore
/// let mut i = 0;
/// idle_add(move || {
/// println!("Idle: {}", i);
/// i += 1;
/// Continue(if i <= 10 { true } else { false })
/// });
/// ```
pub fn idle_add<F>(func: F) -> u32
where F: FnMut() -> Continue + 'static {
let f: Box<RefCell<Box<FnMut() -> Continue + 'static>>> = Box::new(RefCell::new(Box::new(func)));
unsafe {
g_idle_add_full(PRIORITY_DEFAULT_IDLE, transmute(trampoline),
into_raw(f) as gpointer, destroy_closure)
}
}

/// Sets a function to be called at regular intervals, with the default priority, `PRIORITY_DEFAULT`.
///
/// The function is called repeatedly until it returns `Continue(false)`, at which point the timeout is
/// automatically destroyed and the function will not be called again. The first call to the
/// function will be at the end of the first interval .
///
/// Note that timeout functions may be delayed, due to the processing of other event sources. Thus
/// they should not be relied on for precise timing. After each call to the timeout function, the
/// time of the next timeout is recalculated based on the current time and the given interval (it
/// does not try to 'catch up' time lost in delays).
///
/// If you want to have a timer in the "seconds" range and do not care about the exact time of the
/// first call of the timer, use the `timeout_add_seconds()` function; this function allows for more
/// optimizations and more efficient system power usage.
///
/// The interval given is in terms of monotonic time, not wall clock time.
/// See `g_get_monotonic_time()` in glib documentation.
///
/// # Examples
///
/// ```ignore
/// timeout_add(3000, || {
/// println!("This prints once every 3 seconds");
/// Continue(true)
/// });
/// ```
pub fn timeout_add<F>(interval: u32, func: F) -> u32
where F: FnMut() -> Continue + 'static {
let f: Box<RefCell<Box<FnMut() -> Continue + 'static>>> = Box::new(RefCell::new(Box::new(func)));
unsafe {
g_timeout_add_full(PRIORITY_DEFAULT, interval, transmute(trampoline),
into_raw(f) as gpointer, destroy_closure)
}
}

/// Sets a function to be called at regular intervals with the default priority, `PRIORITY_DEFAULT`.
///
/// The function is called repeatedly until it returns `Continue(false)`, at which point the timeout
/// is automatically destroyed and the function will not be called again.
///
/// Note that the first call of the timer may not be precise for timeouts of one second. If you need
/// finer precision and have such a timeout, you may want to use `timeout_add()` instead.
///
/// The interval given is in terms of monotonic time, not wall clock time.
/// See `g_get_monotonic_time()` in glib documentation.
///
/// # Examples
///
/// ```ignore
/// timeout_add_seconds(10, || {
/// println!("This prints once every 10 seconds");
/// Continue(true)
/// });
/// ```
pub fn timeout_add_seconds<F>(interval: u32, func: F) -> u32
where F: FnMut() -> Continue + 'static {
let f: Box<RefCell<Box<FnMut() -> Continue + 'static>>> = Box::new(RefCell::new(Box::new(func)));
unsafe {
g_timeout_add_seconds_full(PRIORITY_DEFAULT, interval, transmute(trampoline),
into_raw(f) as gpointer, destroy_closure)
}
}
55 changes: 0 additions & 55 deletions src/timeout_func.rs

This file was deleted.