From 29655f841ad090183ac8cbe7096153ba000e767a Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Sun, 14 Jun 2015 22:25:37 +0200 Subject: [PATCH 1/8] Add g_idle_add() --- glib-sys/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glib-sys/src/lib.rs b/glib-sys/src/lib.rs index 6e00faf7..aab22350 100644 --- a/glib-sys/src/lib.rs +++ b/glib-sys/src/lib.rs @@ -75,9 +75,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. @@ -354,7 +354,7 @@ extern "C" { 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_idle_source_new () -> *mut GSource; - //pub fn g_idle_add (); + pub fn g_idle_add (function: gpointer, data: gpointer) -> c_uint; //pub fn g_idle_add_full (); pub fn g_idle_remove_by_data (data: gpointer) -> gboolean; pub fn g_child_watch_source_new (pid: GPid) -> *mut GSource; From 85adfd4a6a502b609c0c69dd0b26cc44cde0d863 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 16 Jun 2015 15:57:20 +0200 Subject: [PATCH 2/8] Add g_idle_add() and glib::idle --- glib-sys/src/lib.rs | 2 +- src/idle_func.rs | 18 ++++++++++++++++++ src/lib.rs | 2 ++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/idle_func.rs diff --git a/glib-sys/src/lib.rs b/glib-sys/src/lib.rs index aab22350..e2f300ff 100644 --- a/glib-sys/src/lib.rs +++ b/glib-sys/src/lib.rs @@ -354,7 +354,7 @@ extern "C" { 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_idle_source_new () -> *mut GSource; - pub fn g_idle_add (function: gpointer, data: gpointer) -> c_uint; + pub fn g_idle_add (function: GSourceFunc, data: gpointer) -> c_uint; //pub fn g_idle_add_full (); pub fn g_idle_remove_by_data (data: gpointer) -> gboolean; pub fn g_child_watch_source_new (pid: GPid) -> *mut GSource; diff --git a/src/idle_func.rs b/src/idle_func.rs new file mode 100644 index 00000000..772ee4c8 --- /dev/null +++ b/src/idle_func.rs @@ -0,0 +1,18 @@ +// 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 + +//! callback idle functions + +pub mod idle { + use std::mem::transmute; + use ffi; + + // pub fn add(func: F, data: &mut T) -> u32 + // where F: FnMut(&mut T) -> bool { + pub fn add(func: fn(&mut T) -> bool, data: &mut T) -> u32 { + unsafe { + ffi::g_idle_add(transmute(func), transmute(data)) + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 19d99a5d..8b5fb205 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ 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::idle_func::idle; pub use self::traits::FFIGObject; pub use self::value::{Value, ValuePublic}; pub use types::Type; @@ -33,6 +34,7 @@ mod error; mod permission; pub mod signal; pub mod timeout_func; +pub mod idle_func; pub mod traits; pub mod translate; mod value; From a7fe9348af3c2cd630ffb3d297c7194f96ac4f4e Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 16 Jun 2015 17:35:00 +0200 Subject: [PATCH 3/8] Add g_idle_add() and glib::idle --- glib-sys/src/lib.rs | 5 +++-- src/idle_func.rs | 30 ++++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/glib-sys/src/lib.rs b/glib-sys/src/lib.rs index e2f300ff..6c558509 100644 --- a/glib-sys/src/lib.rs +++ b/glib-sys/src/lib.rs @@ -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; @@ -354,8 +355,8 @@ extern "C" { 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_idle_source_new () -> *mut GSource; - pub fn g_idle_add (function: GSourceFunc, data: gpointer) -> c_uint; - //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 (); diff --git a/src/idle_func.rs b/src/idle_func.rs index 772ee4c8..5f2027b4 100644 --- a/src/idle_func.rs +++ b/src/idle_func.rs @@ -5,14 +5,36 @@ //! callback idle functions pub mod idle { + use std::cell::RefCell; use std::mem::transmute; use ffi; - // pub fn add(func: F, data: &mut T) -> u32 - // where F: FnMut(&mut T) -> bool { - pub fn add(func: fn(&mut T) -> bool, data: &mut T) -> u32 { + // Box::into_raw stability workaround + unsafe fn into_raw(b: Box) -> *mut T { transmute(b) } + + // extern "C" fn trampoline(func: &RefCell bool>>) -> ffi::gboolean { + extern "C" fn trampoline(func: &RefCell bool>>) -> ffi::gboolean { + func.borrow_mut()() as ffi::gboolean + } + + extern "C" fn destroy_closure(ptr: ffi::gpointer) { + unsafe { + // Box::from_raw API stability workaround + // let ptr = ptr as *mut RefCell bool>>; + // let _: Box bool>>> = ::std::mem::transmute(ptr); + let ptr = ptr as *mut RefCell bool>>; + let _: Box bool>>> = ::std::mem::transmute(ptr); + } + } + + pub fn add(func: F) -> u32 + // where F: FnMut() -> bool { + // let f: Box bool>>> = Box::new(RefCell::new(Box::new(func))); + where F: Fn() -> bool { + let f: Box bool>>> = Box::new(RefCell::new(Box::new(func))); unsafe { - ffi::g_idle_add(transmute(func), transmute(data)) + ffi::g_idle_add_full(200 /* = G_PRIORITY_DEFAULT_IDLE */, + transmute(trampoline), into_raw(f) as ffi::gpointer, destroy_closure) } } } From be2d6c3f6b29cba6ddab7ddf048ef969311d8c50 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 16 Jun 2015 18:42:56 +0200 Subject: [PATCH 4/8] Idle: Use FnMut, add Continue return type --- src/idle_func.rs | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/idle_func.rs b/src/idle_func.rs index 5f2027b4..895f3fc1 100644 --- a/src/idle_func.rs +++ b/src/idle_func.rs @@ -6,34 +6,43 @@ pub mod idle { use std::cell::RefCell; + use std::ops::DerefMut; use std::mem::transmute; - use ffi; + use ffi::{gboolean, g_idle_add_full}; + use translate::ToGlib; + + 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(b: Box) -> *mut T { transmute(b) } - // extern "C" fn trampoline(func: &RefCell bool>>) -> ffi::gboolean { - extern "C" fn trampoline(func: &RefCell bool>>) -> ffi::gboolean { - func.borrow_mut()() as ffi::gboolean + extern "C" fn trampoline(func: &RefCell Continue + 'static>>) -> gboolean { + func.borrow_mut().deref_mut()().to_glib() } - extern "C" fn destroy_closure(ptr: ffi::gpointer) { + extern "C" fn destroy_closure(ptr: gpointer) { unsafe { // Box::from_raw API stability workaround - // let ptr = ptr as *mut RefCell bool>>; - // let _: Box bool>>> = ::std::mem::transmute(ptr); - let ptr = ptr as *mut RefCell bool>>; - let _: Box bool>>> = ::std::mem::transmute(ptr); + let ptr = ptr as *mut RefCell Continue + 'static>>; + let _: Box Continue + 'static>>> = ::std::mem::transmute(ptr); } } pub fn add(func: F) -> u32 - // where F: FnMut() -> bool { - // let f: Box bool>>> = Box::new(RefCell::new(Box::new(func))); - where F: Fn() -> bool { - let f: Box bool>>> = Box::new(RefCell::new(Box::new(func))); + where F: FnMut() -> Continue + 'static { + let f: Box Continue + 'static>>> = Box::new(RefCell::new(Box::new(func))); unsafe { - ffi::g_idle_add_full(200 /* = G_PRIORITY_DEFAULT_IDLE */, + g_idle_add_full(200 /* = G_PRIORITY_DEFAULT_IDLE */, transmute(trampoline), into_raw(f) as ffi::gpointer, destroy_closure) } } From 9bdfe6983729d89f884bb9f0d690f91d9e627913 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 16 Jun 2015 19:14:40 +0200 Subject: [PATCH 5/8] Idle: Fix: imports --- src/idle_func.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/idle_func.rs b/src/idle_func.rs index 895f3fc1..ffb9debd 100644 --- a/src/idle_func.rs +++ b/src/idle_func.rs @@ -8,7 +8,7 @@ pub mod idle { use std::cell::RefCell; use std::ops::DerefMut; use std::mem::transmute; - use ffi::{gboolean, g_idle_add_full}; + use ffi::{gboolean, gpointer, g_idle_add_full}; use translate::ToGlib; pub struct Continue(pub bool); @@ -43,7 +43,7 @@ pub mod idle { let f: Box Continue + 'static>>> = Box::new(RefCell::new(Box::new(func))); unsafe { g_idle_add_full(200 /* = G_PRIORITY_DEFAULT_IDLE */, - transmute(trampoline), into_raw(f) as ffi::gpointer, destroy_closure) + transmute(trampoline), into_raw(f) as gpointer, destroy_closure) } } } From 2149905268d1df210a776969c77fc9b42b2c191f Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Wed, 17 Jun 2015 21:38:15 +0200 Subject: [PATCH 6/8] Merge idle and timouet funcs into `source` module, cleanup --- glib-sys/src/lib.rs | 6 +-- src/idle_func.rs | 49 -------------------- src/lib.rs | 6 +-- src/source.rs | 110 ++++++++++++++++++++++++++++++++++++++++++++ src/timeout_func.rs | 55 ---------------------- 5 files changed, 114 insertions(+), 112 deletions(-) delete mode 100644 src/idle_func.rs create mode 100644 src/source.rs delete mode 100644 src/timeout_func.rs diff --git a/glib-sys/src/lib.rs b/glib-sys/src/lib.rs index 6c558509..c954a283 100644 --- a/glib-sys/src/lib.rs +++ b/glib-sys/src/lib.rs @@ -349,11 +349,9 @@ 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 (function: GSourceFunc, data: gpointer) -> c_uint; pub fn g_idle_add_full (priority: c_int, function: GSourceFunc, data: gpointer, notify: GDestroyNotify) -> c_uint; diff --git a/src/idle_func.rs b/src/idle_func.rs deleted file mode 100644 index ffb9debd..00000000 --- a/src/idle_func.rs +++ /dev/null @@ -1,49 +0,0 @@ -// 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 - -//! callback idle functions - -pub mod idle { - use std::cell::RefCell; - use std::ops::DerefMut; - use std::mem::transmute; - use ffi::{gboolean, gpointer, g_idle_add_full}; - use translate::ToGlib; - - 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(b: Box) -> *mut T { transmute(b) } - - extern "C" fn trampoline(func: &RefCell 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 Continue + 'static>>; - let _: Box Continue + 'static>>> = ::std::mem::transmute(ptr); - } - } - - pub fn add(func: F) -> u32 - where F: FnMut() -> Continue + 'static { - let f: Box Continue + 'static>>> = Box::new(RefCell::new(Box::new(func))); - unsafe { - g_idle_add_full(200 /* = G_PRIORITY_DEFAULT_IDLE */, - transmute(trampoline), into_raw(f) as gpointer, destroy_closure) - } - } -} diff --git a/src/lib.rs b/src/lib.rs index 8b5fb205..d009536d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,8 +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::idle_func::idle; +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; @@ -33,8 +32,7 @@ pub mod glib_container; mod error; mod permission; pub mod signal; -pub mod timeout_func; -pub mod idle_func; +pub mod source; pub mod traits; pub mod translate; mod value; diff --git a/src/source.rs b/src/source.rs new file mode 100644 index 00000000..30ce2d64 --- /dev/null +++ b/src/source.rs @@ -0,0 +1,110 @@ +// 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 + +//! GSourceFunc functions + +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; + +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(b: Box) -> *mut T { transmute(b) } + +extern "C" fn trampoline(func: &RefCell 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 Continue + 'static>>; + let _: Box Continue + 'static>>> = transmute(ptr); + } +} + +const G_PRIORITY_DEFAULT: i32 = 0; +const G_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, G_PRIORITY_DEFAULT_IDLE. +/// If the function returns FALSE it is automatically removed from +/// the list of event sources and will not be called again. +/// +/// This internally creates a main loop source using g_idle_source_new() +/// and attaches it to the global GMainContext using g_source_attach(), +/// so the callback will be invoked in whichever thread is running that main context. +/// You can do these steps manually if you need greater control or to use a custom main context. +pub fn idle_add(func: F) -> u32 + where F: FnMut() -> Continue + 'static { + let f: Box Continue + 'static>>> = Box::new(RefCell::new(Box::new(func))); + unsafe { + g_idle_add_full(G_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, G_PRIORITY_DEFAULT. +/// The function is called repeatedly until it returns 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 g_timeout_add_seconds() function; this function allows for more +/// optimizations and more efficient system power usage. +/// +/// This internally creates a main loop source using g_timeout_source_new() and attaches it to the +/// global GMainContext using g_source_attach(), so the callback will be invoked in whichever thread +/// is running that main context. You can do these steps manually if you need greater control or to +/// use a custom main context. +/// +/// The interval given is in terms of monotonic time, not wall clock time. See g_get_monotonic_time(). +pub fn timeout_add(interval: u32, func: F) -> u32 + where F: FnMut() -> Continue + 'static { + let f: Box Continue + 'static>>> = Box::new(RefCell::new(Box::new(func))); + unsafe { + g_timeout_add_full(G_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, G_PRIORITY_DEFAULT. +/// The function is called repeatedly until it returns FALSE, at which point the timeout is automatically +/// destroyed and the function will not be called again. +/// +/// This internally creates a main loop source using g_timeout_source_new_seconds() and attaches it to +/// the main loop context using g_source_attach(). You can do these steps manually if you need greater +/// control. Also see g_timeout_add_seconds_full(). +/// +/// 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 g_timeout_add() instead. +/// +/// The interval given is in terms of monotonic time, not wall clock time. See g_get_monotonic_time(). +pub fn timeout_add_seconds(interval: u32, func: F) -> u32 + where F: FnMut() -> Continue + 'static { + let f: Box Continue + 'static>>> = Box::new(RefCell::new(Box::new(func))); + unsafe { + g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, interval, transmute(trampoline), + into_raw(f) as gpointer, destroy_closure) + } +} diff --git a/src/timeout_func.rs b/src/timeout_func.rs deleted file mode 100644 index 328d462d..00000000 --- a/src/timeout_func.rs +++ /dev/null @@ -1,55 +0,0 @@ -// 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 - -//! callback timeout functions - -pub mod timeout { - use ffi; - - /// Sets a function to be called at regular intervals, with the default priority, G_PRIORITY_DEFAULT. - /// The function is called repeatedly until it returns 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 g_timeout_add_seconds() function; this function allows for more - /// optimizations and more efficient system power usage. - /// - /// This internally creates a main loop source using g_timeout_source_new() and attaches it to the - /// global GMainContext using g_source_attach(), so the callback will be invoked in whichever thread - /// is running that main context. You can do these steps manually if you need greater control or to - /// use a custom main context. - /// - /// The interval given is in terms of monotonic time, not wall clock time. See g_get_monotonic_time(). - pub fn add(interval: u32, func: fn(&mut T) -> i32, data: &T) -> u32 { - let tmp = data as *const T; - let tmp_f = func as ffi::gpointer; - - unsafe { ffi::g_timeout_add(interval, tmp_f, tmp as ffi::gpointer) } - } - - /// Sets a function to be called at regular intervals with the default priority, G_PRIORITY_DEFAULT. - /// The function is called repeatedly until it returns FALSE, at which point the timeout is automatically - /// destroyed and the function will not be called again. - /// - /// This internally creates a main loop source using g_timeout_source_new_seconds() and attaches it to - /// the main loop context using g_source_attach(). You can do these steps manually if you need greater - /// control. Also see g_timeout_add_seconds_full(). - /// - /// 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 g_timeout_add() instead. - /// - /// The interval given is in terms of monotonic time, not wall clock time. See g_get_monotonic_time(). - pub fn add_seconds(interval: u32, func: fn(&mut T) -> i32, data: &T) -> u32 { - let tmp = data as *const T; - let tmp_f = func as ffi::gpointer; - - unsafe { ffi::g_timeout_add_seconds(interval, tmp_f, tmp as ffi::gpointer) } - } -} From e974752121dea511363a1eb63777b00eed419ffb Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Thu, 18 Jun 2015 22:57:52 +0200 Subject: [PATCH 7/8] Source: Improve doc, fix const names --- src/source.rs | 80 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 28 deletions(-) diff --git a/src/source.rs b/src/source.rs index 30ce2d64..5dd15a04 100644 --- a/src/source.rs +++ b/src/source.rs @@ -2,7 +2,7 @@ // See the COPYRIGHT file at the top-level directory of this distribution. // Licensed under the MIT license, see the LICENSE file or -//! GSourceFunc functions +//! Manages available sources of events for the main loop use std::cell::RefCell; use std::ops::DerefMut; @@ -10,6 +10,10 @@ 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 { @@ -37,30 +41,38 @@ extern "C" fn destroy_closure(ptr: gpointer) { } } -const G_PRIORITY_DEFAULT: i32 = 0; -const G_PRIORITY_DEFAULT_IDLE: i32 = 200; +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, G_PRIORITY_DEFAULT_IDLE. -/// If the function returns FALSE it is automatically removed from +/// +/// 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. /// -/// This internally creates a main loop source using g_idle_source_new() -/// and attaches it to the global GMainContext using g_source_attach(), -/// so the callback will be invoked in whichever thread is running that main context. -/// You can do these steps manually if you need greater control or to use a custom main context. +/// # Examples +/// +/// ``` +/// let mut i = 0; +/// idle_add(move || { +/// println!("Idle: {}", i); +/// i += 1; +/// Continue(if i <= 10 { true } else { false }) +/// }); +/// ``` pub fn idle_add(func: F) -> u32 where F: FnMut() -> Continue + 'static { let f: Box Continue + 'static>>> = Box::new(RefCell::new(Box::new(func))); unsafe { - g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, transmute(trampoline), + 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, G_PRIORITY_DEFAULT. -/// The function is called repeatedly until it returns FALSE, at which point the timeout is +/// 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 . /// @@ -70,41 +82,53 @@ pub fn idle_add(func: F) -> u32 /// 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 g_timeout_add_seconds() function; this function allows for more +/// first call of the timer, use the `timeout_add_seconds()` function; this function allows for more /// optimizations and more efficient system power usage. /// -/// This internally creates a main loop source using g_timeout_source_new() and attaches it to the -/// global GMainContext using g_source_attach(), so the callback will be invoked in whichever thread -/// is running that main context. You can do these steps manually if you need greater control or to -/// use a custom main context. +/// The interval given is in terms of monotonic time, not wall clock time. +/// See `g_get_monotonic_time()` in glib documentation. /// -/// The interval given is in terms of monotonic time, not wall clock time. See g_get_monotonic_time(). +/// # Examples +/// +/// ``` +/// timeout_add(3000, || { +/// println!("This prints once every 3 seconds"); +/// Continue(true) +/// }); +/// ``` pub fn timeout_add(interval: u32, func: F) -> u32 where F: FnMut() -> Continue + 'static { let f: Box Continue + 'static>>> = Box::new(RefCell::new(Box::new(func))); unsafe { - g_timeout_add_full(G_PRIORITY_DEFAULT, interval, transmute(trampoline), + 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, G_PRIORITY_DEFAULT. -/// The function is called repeatedly until it returns FALSE, at which point the timeout is automatically -/// destroyed and the function will not be called again. +/// Sets a function to be called at regular intervals with the default priority, `PRIORITY_DEFAULT`. /// -/// This internally creates a main loop source using g_timeout_source_new_seconds() and attaches it to -/// the main loop context using g_source_attach(). You can do these steps manually if you need greater -/// control. Also see g_timeout_add_seconds_full(). +/// 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 g_timeout_add() instead. +/// 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 /// -/// The interval given is in terms of monotonic time, not wall clock time. See g_get_monotonic_time(). +/// ``` +/// timeout_add_seconds(10, || { +/// println!("This prints once every 10 seconds"); +/// Continue(true) +/// }); +/// ``` pub fn timeout_add_seconds(interval: u32, func: F) -> u32 where F: FnMut() -> Continue + 'static { let f: Box Continue + 'static>>> = Box::new(RefCell::new(Box::new(func))); unsafe { - g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, interval, transmute(trampoline), + g_timeout_add_seconds_full(PRIORITY_DEFAULT, interval, transmute(trampoline), into_raw(f) as gpointer, destroy_closure) } } From e1731d6ce8e399ea55099da65e36cf12ea3ea00c Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Fri, 19 Jun 2015 12:35:40 +0200 Subject: [PATCH 8/8] Source: Doc: ignore examples in test --- src/source.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/source.rs b/src/source.rs index 5dd15a04..69d845c8 100644 --- a/src/source.rs +++ b/src/source.rs @@ -53,7 +53,7 @@ const PRIORITY_DEFAULT_IDLE: i32 = 200; /// /// # Examples /// -/// ``` +/// ```ignore /// let mut i = 0; /// idle_add(move || { /// println!("Idle: {}", i); @@ -90,7 +90,7 @@ pub fn idle_add(func: F) -> u32 /// /// # Examples /// -/// ``` +/// ```ignore /// timeout_add(3000, || { /// println!("This prints once every 3 seconds"); /// Continue(true) @@ -118,7 +118,7 @@ pub fn timeout_add(interval: u32, func: F) -> u32 /// /// # Examples /// -/// ``` +/// ```ignore /// timeout_add_seconds(10, || { /// println!("This prints once every 10 seconds"); /// Continue(true)