Add IdleManager class for sane main loop idle scheduling.
This commit is contained in:
parent
18fd246f53
commit
31fbfd4047
6 changed files with 147 additions and 1 deletions
|
|
@ -368,6 +368,7 @@ src/engine/util/util-converter.vala
|
|||
src/engine/util/util-files.vala
|
||||
src/engine/util/util-generic-capabilities.vala
|
||||
src/engine/util/util-html.vala
|
||||
src/engine/util/util-idle-manager.vala
|
||||
src/engine/util/util-imap-utf7.vala
|
||||
src/engine/util/util-inet.vala
|
||||
src/engine/util/util-iterable.vala
|
||||
|
|
|
|||
|
|
@ -295,6 +295,7 @@ engine/util/util-converter.vala
|
|||
engine/util/util-files.vala
|
||||
engine/util/util-generic-capabilities.vala
|
||||
engine/util/util-html.vala
|
||||
engine/util/util-idle-manager.vala
|
||||
engine/util/util-imap-utf7.vala
|
||||
engine/util/util-inet.vala
|
||||
engine/util/util-iterable.vala
|
||||
|
|
|
|||
102
src/engine/util/util-idle-manager.vala
Normal file
102
src/engine/util/util-idle-manager.vala
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright 2017 Michael Gratton <mike@vee.net>
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Manages execution of a function on the main loop.
|
||||
*
|
||||
* This class is a convenience API for the GLib main loop and source
|
||||
* infrastructure, automatically performing cleanup when destroyed.
|
||||
*
|
||||
* Note this class is not thread safe and should only be invoked from
|
||||
* the main loop.
|
||||
*/
|
||||
public class Geary.IdleManager : BaseObject {
|
||||
|
||||
|
||||
/** Specifies the priority the idle function should be given. */
|
||||
public enum Priority {
|
||||
HIGH = GLib.Priority.HIGH,
|
||||
DEFAULT = GLib.Priority.DEFAULT,
|
||||
HIGH_IDLE = GLib.Priority.HIGH_IDLE,
|
||||
DEFAULT_IDLE = GLib.Priority.DEFAULT_IDLE,
|
||||
LOW = GLib.Priority.LOW;
|
||||
}
|
||||
|
||||
/** Specifies if the idle function should run once or be continuously. */
|
||||
public enum Repeat { ONCE, FOREVER; }
|
||||
|
||||
/** The idle callback function prototype. */
|
||||
public delegate void IdleFunc(IdleManager manager);
|
||||
|
||||
/** Determines if the function will be re-scheduled after being run. */
|
||||
public Repeat repetition = Repeat.ONCE;
|
||||
|
||||
/** Determines the priority the function will receive on the main loop. */
|
||||
public Priority priority = Priority.DEFAULT;
|
||||
|
||||
/** Determines if the function is waiting to fire or not. */
|
||||
public bool is_running {
|
||||
get { return this.source_id >= 0; }
|
||||
}
|
||||
|
||||
private IdleFunc callback;
|
||||
private int source_id = -1;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new idle manager with an interval in seconds.
|
||||
*
|
||||
* The idle function will be by default not running, and hence
|
||||
* needs to be started by a call to {@link start}.
|
||||
*/
|
||||
public IdleManager(IdleFunc callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
~IdleManager() {
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the idle function to run on the main loop.
|
||||
*
|
||||
* If the function is already waiting to run, it will first be reset.
|
||||
*/
|
||||
public void schedule() {
|
||||
reset();
|
||||
this.source_id = (int) GLib.Idle.add_full(this.priority, on_trigger);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents the idle function from being run.
|
||||
*
|
||||
* @return `true` if function was already scheduled, else `false`
|
||||
*/
|
||||
public bool reset() {
|
||||
bool is_running = this.is_running;
|
||||
if (is_running) {
|
||||
Source.remove(this.source_id);
|
||||
this.source_id = -1;
|
||||
}
|
||||
return is_running;
|
||||
}
|
||||
|
||||
private bool on_trigger() {
|
||||
bool ret = Source.CONTINUE;
|
||||
// If running only once, reset the source id now in case the
|
||||
// callback resets the timer while it is executing, so we
|
||||
// avoid removing the source just before it would be removed
|
||||
// after this call anyway
|
||||
if (this.repetition == Repeat.ONCE) {
|
||||
this.source_id = -1;
|
||||
ret = Source.REMOVE;
|
||||
}
|
||||
callback(this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ set(TEST_SRC
|
|||
engine/rfc822-message-data-test.vala
|
||||
engine/rfc822-utils-test.vala
|
||||
engine/util-html-test.vala
|
||||
engine/util-idle-manager-test.vala
|
||||
engine/util-inet-test.vala
|
||||
engine/util-js-test.vala
|
||||
engine/util-timeout-manager-test.vala
|
||||
|
|
|
|||
40
test/engine/util-idle-manager-test.vala
Normal file
40
test/engine/util-idle-manager-test.vala
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright 2017 Michael Gratton <mike@vee.net>
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
class Geary.IdleManagerTest : Gee.TestCase {
|
||||
|
||||
public IdleManagerTest() {
|
||||
base("Geary.IdleManagerTest");
|
||||
add_test("start_reset", start_reset);
|
||||
add_test("test_run", test_run);
|
||||
}
|
||||
|
||||
public void start_reset() {
|
||||
IdleManager test = new IdleManager(() => { /* noop */ });
|
||||
assert(!test.is_running);
|
||||
test.schedule();
|
||||
assert(test.is_running);
|
||||
test.reset();
|
||||
assert(!test.is_running);
|
||||
}
|
||||
|
||||
public void test_run() {
|
||||
bool did_run = false;
|
||||
|
||||
IdleManager test = new IdleManager(() => { did_run = true; });
|
||||
test.schedule();
|
||||
|
||||
// There should be at least one event pending
|
||||
assert(Gtk.events_pending());
|
||||
|
||||
// Execute the idle function
|
||||
Gtk.main_iteration();
|
||||
|
||||
assert(did_run);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -38,8 +38,9 @@ int main(string[] args) {
|
|||
TestSuite engine = new TestSuite("engine");
|
||||
|
||||
engine.add_suite(new Geary.HTML.UtilTest().get_suite());
|
||||
engine.add_suite(new Geary.JS.Test().get_suite());
|
||||
engine.add_suite(new Geary.IdleManagerTest().get_suite());
|
||||
engine.add_suite(new Geary.Inet.Test().get_suite());
|
||||
engine.add_suite(new Geary.JS.Test().get_suite());
|
||||
engine.add_suite(new Geary.RFC822.MailboxAddressTest().get_suite());
|
||||
engine.add_suite(new Geary.RFC822.MessageTest().get_suite());
|
||||
engine.add_suite(new Geary.RFC822.MessageDataTest().get_suite());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue