2015-11-10 14:18:11 -05:00
|
|
|
/*
|
2013-09-01 10:55:13 -04:00
|
|
|
* Copyright 2013 (c) Anna Schumaker.
|
|
|
|
*/
|
2014-06-05 10:19:22 -04:00
|
|
|
#include <core/idle.h>
|
2015-11-10 14:08:11 -05:00
|
|
|
#include <glib.h>
|
2013-09-01 10:55:13 -04:00
|
|
|
|
2015-11-10 13:52:24 -05:00
|
|
|
|
|
|
|
struct idle_task {
|
2016-05-02 18:42:38 -04:00
|
|
|
bool (*idle_func)(void *);
|
2015-11-10 13:52:24 -05:00
|
|
|
void *idle_data;
|
2016-04-30 10:11:48 -04:00
|
|
|
enum idle_sync_t idle_sync;
|
2015-11-10 13:52:24 -05:00
|
|
|
};
|
|
|
|
|
2016-04-30 10:11:48 -04:00
|
|
|
static GThreadPool *idle_pool = NULL;
|
|
|
|
static GQueue idle_queue = G_QUEUE_INIT;
|
|
|
|
static unsigned int queued = 0;
|
|
|
|
static unsigned int serviced = 0;
|
2013-09-01 10:55:13 -04:00
|
|
|
|
|
|
|
|
2016-07-28 16:15:29 -04:00
|
|
|
void __idle_free_task(struct idle_task *task)
|
|
|
|
{
|
|
|
|
g_free(task);
|
|
|
|
g_atomic_int_inc(&serviced);
|
|
|
|
}
|
|
|
|
|
2016-05-02 18:42:38 -04:00
|
|
|
bool __idle_run_task(struct idle_task *task)
|
2016-04-30 10:11:48 -04:00
|
|
|
{
|
2016-05-02 18:42:38 -04:00
|
|
|
bool finished = task->idle_func(task->idle_data);
|
2016-07-28 16:15:29 -04:00
|
|
|
if (finished)
|
|
|
|
__idle_free_task(task);
|
2016-05-02 18:42:38 -04:00
|
|
|
return finished;
|
2016-04-30 10:11:48 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void __idle_thread(gpointer task, gpointer data)
|
|
|
|
{
|
2016-05-02 18:42:38 -04:00
|
|
|
if (!__idle_run_task(task))
|
|
|
|
g_thread_pool_push(idle_pool, task, NULL);
|
2016-04-30 10:11:48 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void idle_init()
|
|
|
|
{
|
|
|
|
idle_pool = g_thread_pool_new(__idle_thread, NULL, 1, true, NULL);
|
|
|
|
}
|
|
|
|
|
2016-07-28 16:15:29 -04:00
|
|
|
#ifdef CONFIG_TESTING
|
|
|
|
void idle_init_sync()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_TESTING */
|
|
|
|
|
2016-04-30 10:11:48 -04:00
|
|
|
void idle_deinit()
|
|
|
|
{
|
|
|
|
struct idle_task *task;
|
|
|
|
|
|
|
|
while (!g_queue_is_empty(&idle_queue)) {
|
|
|
|
task = g_queue_pop_head(&idle_queue);
|
|
|
|
g_free(task);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (idle_pool)
|
|
|
|
g_thread_pool_free(idle_pool, true, false);
|
|
|
|
|
|
|
|
queued = 0;
|
|
|
|
serviced = 0;
|
|
|
|
}
|
|
|
|
|
2016-05-02 18:42:38 -04:00
|
|
|
void idle_schedule(enum idle_sync_t sync, bool (*func)(void *), void *data)
|
2013-09-01 10:55:13 -04:00
|
|
|
{
|
2015-11-10 14:18:11 -05:00
|
|
|
struct idle_task *task = g_malloc(sizeof(struct idle_task));
|
2015-11-10 13:52:24 -05:00
|
|
|
task->idle_func = func;
|
|
|
|
task->idle_data = data;
|
2016-04-30 10:11:48 -04:00
|
|
|
task->idle_sync = sync;
|
2013-09-01 10:55:13 -04:00
|
|
|
|
2015-11-10 14:08:11 -05:00
|
|
|
g_queue_push_tail(&idle_queue, task);
|
2016-04-30 10:11:48 -04:00
|
|
|
g_atomic_int_inc(&queued);
|
2013-09-01 10:55:13 -04:00
|
|
|
}
|
|
|
|
|
2015-11-10 13:56:54 -05:00
|
|
|
bool idle_run_task()
|
2013-09-01 10:55:13 -04:00
|
|
|
{
|
2015-11-10 14:08:11 -05:00
|
|
|
struct idle_task *task;
|
|
|
|
|
2015-11-10 14:18:11 -05:00
|
|
|
if (!g_queue_is_empty(&idle_queue)) {
|
|
|
|
task = g_queue_pop_head(&idle_queue);
|
2016-07-28 16:15:29 -04:00
|
|
|
if (task->idle_sync == IDLE_ASYNC) {
|
|
|
|
if (idle_pool)
|
|
|
|
g_thread_pool_push(idle_pool, task, NULL);
|
|
|
|
else
|
|
|
|
__idle_free_task(task);
|
|
|
|
} else if (!__idle_run_task(task))
|
2016-05-02 18:42:38 -04:00
|
|
|
g_queue_push_tail(&idle_queue, task);
|
2013-09-01 10:55:13 -04:00
|
|
|
}
|
|
|
|
|
2016-04-30 10:11:48 -04:00
|
|
|
if (g_atomic_int_get(&queued) != g_atomic_int_get(&serviced))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
queued = 0;
|
|
|
|
serviced = 0;
|
|
|
|
return false;
|
2013-09-01 10:55:13 -04:00
|
|
|
}
|
|
|
|
|
2015-11-10 13:27:32 -05:00
|
|
|
float idle_progress()
|
2013-09-01 10:55:13 -04:00
|
|
|
{
|
2016-04-30 10:11:48 -04:00
|
|
|
if (g_atomic_int_get(&serviced) == 0 &&
|
|
|
|
g_atomic_int_get(&queued) == 0)
|
2014-03-16 13:09:33 -04:00
|
|
|
return 1.0;
|
2016-04-30 10:11:48 -04:00
|
|
|
return (float)g_atomic_int_get(&serviced) / (float)queued;
|
2016-03-01 08:27:13 -05:00
|
|
|
}
|