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

Commit d1fc919

Browse files
Merge pull request #47 from vojtechkral/idle
Add g_idle_add()
2 parents d2d86ef + e1731d6 commit d1fc919

File tree

4 files changed

+143
-65
lines changed

4 files changed

+143
-65
lines changed

glib-sys/src/lib.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub type gpointer = *mut c_void;
2323
pub type GSourceFunc = extern "C" fn(user_data: gpointer) -> gboolean;
2424
pub type GCallback = extern "C" fn();
2525
pub type GClosureNotify = extern "C" fn(data: gpointer, closure: gpointer);
26+
pub type GDestroyNotify = extern "C" fn(data: gpointer);
2627

2728
#[repr(C)]
2829
pub struct GAppInfo;
@@ -75,9 +76,9 @@ pub struct GPid;
7576
pub struct GPollFD;
7677

7778
/// Represents a day between January 1, Year 1 and a few thousand years in the future. None of its members should be accessed directly.
78-
///
79+
///
7980
/// If the GDate is obtained from g_date_new(), it will be safe to mutate but invalid and thus not safe for calendrical computations.
80-
///
81+
///
8182
/// 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
8283
/// 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
8384
/// you set a day, month, and year.
@@ -348,14 +349,12 @@ extern "C" {
348349
pub fn g_timeout_source_new () -> *mut GSource;
349350
pub fn g_timeout_source_new_seconds (interval: c_uint) -> *mut GSource;
350351
//pub fn g_timeout_add (interval: c_uint, function: GSourceFunc, data: gpointer) -> c_uint;
351-
pub fn g_timeout_add (interval: c_uint, function: gpointer, data: gpointer) -> c_uint;
352-
//pub fn g_timeout_add_full ();
352+
pub fn g_timeout_add_full (priority: c_int, interval: c_uint, function: GSourceFunc, data: gpointer, notify: GDestroyNotify) -> c_uint;
353353
//pub fn g_timeout_add_seconds (interval: c_uint, function: GSourceFunc, data: gpointer) -> c_uint;
354-
pub fn g_timeout_add_seconds (interval: c_uint, function: gpointer, data: gpointer) -> c_uint;
355-
//pub fn g_timeout_add_seconds_full ();
354+
pub fn g_timeout_add_seconds_full (priority: c_int, interval: c_uint, function: GSourceFunc, data: gpointer, notify: GDestroyNotify) -> c_uint;
356355
pub fn g_idle_source_new () -> *mut GSource;
357-
//pub fn g_idle_add ();
358-
//pub fn g_idle_add_full ();
356+
// pub fn g_idle_add (function: GSourceFunc, data: gpointer) -> c_uint;
357+
pub fn g_idle_add_full (priority: c_int, function: GSourceFunc, data: gpointer, notify: GDestroyNotify) -> c_uint;
359358
pub fn g_idle_remove_by_data (data: gpointer) -> gboolean;
360359
pub fn g_child_watch_source_new (pid: GPid) -> *mut GSource;
361360
//pub fn g_child_watch_add ();

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub use self::slist::{SList, SElem};
1919
pub use self::glib_container::GlibContainer;
2020
pub use self::error::{Error};
2121
pub use self::permission::Permission;
22-
pub use self::timeout_func::timeout;
22+
pub use self::source::{Continue, idle_add, timeout_add, timeout_add_seconds};
2323
pub use self::traits::FFIGObject;
2424
pub use self::value::{Value, ValuePublic};
2525
pub use types::Type;
@@ -32,7 +32,7 @@ pub mod glib_container;
3232
mod error;
3333
mod permission;
3434
pub mod signal;
35-
pub mod timeout_func;
35+
pub mod source;
3636
pub mod traits;
3737
pub mod translate;
3838
mod value;

src/source.rs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// Copyright 2013-2015, The Rust-GNOME Project Developers.
2+
// See the COPYRIGHT file at the top-level directory of this distribution.
3+
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>
4+
5+
//! Manages available sources of events for the main loop
6+
7+
use std::cell::RefCell;
8+
use std::ops::DerefMut;
9+
use std::mem::transmute;
10+
use ffi::{gboolean, gpointer, g_idle_add_full, g_timeout_add_full, g_timeout_add_seconds_full};
11+
use translate::ToGlib;
12+
13+
/// Return type of idle and timeout functions.
14+
///
15+
/// In the callback, return `Continue(true)` to continue scheduling the callback
16+
/// in the main loop or `Continue(false)` to remove it from the main loop.
17+
pub struct Continue(pub bool);
18+
19+
impl ToGlib for Continue {
20+
type GlibType = gboolean;
21+
22+
#[inline]
23+
fn to_glib(&self) -> gboolean {
24+
self.0.to_glib()
25+
}
26+
}
27+
28+
29+
// Box::into_raw stability workaround
30+
unsafe fn into_raw<T>(b: Box<T>) -> *mut T { transmute(b) }
31+
32+
extern "C" fn trampoline(func: &RefCell<Box<FnMut() -> Continue + 'static>>) -> gboolean {
33+
func.borrow_mut().deref_mut()().to_glib()
34+
}
35+
36+
extern "C" fn destroy_closure(ptr: gpointer) {
37+
unsafe {
38+
// Box::from_raw API stability workaround
39+
let ptr = ptr as *mut RefCell<Box<FnMut() -> Continue + 'static>>;
40+
let _: Box<RefCell<Box<FnMut() -> Continue + 'static>>> = transmute(ptr);
41+
}
42+
}
43+
44+
const PRIORITY_DEFAULT: i32 = 0;
45+
const PRIORITY_DEFAULT_IDLE: i32 = 200;
46+
47+
48+
/// Adds a function to be called whenever there are no higher priority events pending to the default main loop.
49+
///
50+
/// The function is given the default idle priority, `PRIORITY_DEFAULT_IDLE`.
51+
/// If the function returns `Continue(false)` it is automatically removed from
52+
/// the list of event sources and will not be called again.
53+
///
54+
/// # Examples
55+
///
56+
/// ```ignore
57+
/// let mut i = 0;
58+
/// idle_add(move || {
59+
/// println!("Idle: {}", i);
60+
/// i += 1;
61+
/// Continue(if i <= 10 { true } else { false })
62+
/// });
63+
/// ```
64+
pub fn idle_add<F>(func: F) -> u32
65+
where F: FnMut() -> Continue + 'static {
66+
let f: Box<RefCell<Box<FnMut() -> Continue + 'static>>> = Box::new(RefCell::new(Box::new(func)));
67+
unsafe {
68+
g_idle_add_full(PRIORITY_DEFAULT_IDLE, transmute(trampoline),
69+
into_raw(f) as gpointer, destroy_closure)
70+
}
71+
}
72+
73+
/// Sets a function to be called at regular intervals, with the default priority, `PRIORITY_DEFAULT`.
74+
///
75+
/// The function is called repeatedly until it returns `Continue(false)`, at which point the timeout is
76+
/// automatically destroyed and the function will not be called again. The first call to the
77+
/// function will be at the end of the first interval .
78+
///
79+
/// Note that timeout functions may be delayed, due to the processing of other event sources. Thus
80+
/// they should not be relied on for precise timing. After each call to the timeout function, the
81+
/// time of the next timeout is recalculated based on the current time and the given interval (it
82+
/// does not try to 'catch up' time lost in delays).
83+
///
84+
/// If you want to have a timer in the "seconds" range and do not care about the exact time of the
85+
/// first call of the timer, use the `timeout_add_seconds()` function; this function allows for more
86+
/// optimizations and more efficient system power usage.
87+
///
88+
/// The interval given is in terms of monotonic time, not wall clock time.
89+
/// See `g_get_monotonic_time()` in glib documentation.
90+
///
91+
/// # Examples
92+
///
93+
/// ```ignore
94+
/// timeout_add(3000, || {
95+
/// println!("This prints once every 3 seconds");
96+
/// Continue(true)
97+
/// });
98+
/// ```
99+
pub fn timeout_add<F>(interval: u32, func: F) -> u32
100+
where F: FnMut() -> Continue + 'static {
101+
let f: Box<RefCell<Box<FnMut() -> Continue + 'static>>> = Box::new(RefCell::new(Box::new(func)));
102+
unsafe {
103+
g_timeout_add_full(PRIORITY_DEFAULT, interval, transmute(trampoline),
104+
into_raw(f) as gpointer, destroy_closure)
105+
}
106+
}
107+
108+
/// Sets a function to be called at regular intervals with the default priority, `PRIORITY_DEFAULT`.
109+
///
110+
/// The function is called repeatedly until it returns `Continue(false)`, at which point the timeout
111+
/// is automatically destroyed and the function will not be called again.
112+
///
113+
/// Note that the first call of the timer may not be precise for timeouts of one second. If you need
114+
/// finer precision and have such a timeout, you may want to use `timeout_add()` instead.
115+
///
116+
/// The interval given is in terms of monotonic time, not wall clock time.
117+
/// See `g_get_monotonic_time()` in glib documentation.
118+
///
119+
/// # Examples
120+
///
121+
/// ```ignore
122+
/// timeout_add_seconds(10, || {
123+
/// println!("This prints once every 10 seconds");
124+
/// Continue(true)
125+
/// });
126+
/// ```
127+
pub fn timeout_add_seconds<F>(interval: u32, func: F) -> u32
128+
where F: FnMut() -> Continue + 'static {
129+
let f: Box<RefCell<Box<FnMut() -> Continue + 'static>>> = Box::new(RefCell::new(Box::new(func)));
130+
unsafe {
131+
g_timeout_add_seconds_full(PRIORITY_DEFAULT, interval, transmute(trampoline),
132+
into_raw(f) as gpointer, destroy_closure)
133+
}
134+
}

src/timeout_func.rs

Lines changed: 0 additions & 55 deletions
This file was deleted.

0 commit comments

Comments
 (0)