Merge pull request #2462 from heuripedes/master

Minor task changes
This commit is contained in:
Twinaphex 2015-11-25 02:26:46 +01:00
commit dba90266db
8 changed files with 189 additions and 61 deletions

View File

@ -180,7 +180,7 @@ void input_overlay_set_scale_factor(float scale)
input_overlay_set_vertex_geom(); input_overlay_set_vertex_geom();
} }
static void input_overlay_free_overlay(struct overlay *overlay) void input_overlay_free_overlay(struct overlay *overlay)
{ {
size_t i; size_t i;
@ -551,6 +551,9 @@ static void input_overlay_loaded(void *task_data, void *user_data, const char *e
input_overlay_t *ol; input_overlay_t *ol;
driver_t *driver = driver_get_ptr(); driver_t *driver = driver_get_ptr();
if (err)
return;
/* We can't display when the menu is up */ /* We can't display when the menu is up */
if (settings->input.overlay_hide_in_menu && menu_driver_alive()) if (settings->input.overlay_hide_in_menu && menu_driver_alive())
{ {

View File

@ -198,6 +198,7 @@ typedef struct
**/ **/
void input_overlay_free(void); void input_overlay_free(void);
void input_overlay_free_overlay(struct overlay *overlay);
/** /**
* input_overlay_init * input_overlay_init

View File

@ -493,7 +493,7 @@ static void rarch_dbscan_task_handler(rarch_task_t *task)
database_state_handle_t *dbstate = &db->state; database_state_handle_t *dbstate = &db->state;
const char *name = dbinfo ? dbinfo->list->elems[dbinfo->list_ptr].data : NULL; const char *name = dbinfo ? dbinfo->list->elems[dbinfo->list_ptr].data : NULL;
if (!dbinfo) if (!dbinfo || task->cancelled)
goto task_finished; goto task_finished;
switch (dbinfo->status) switch (dbinfo->status)

View File

@ -442,7 +442,7 @@ static void rarch_task_file_load_handler(rarch_task_t *task)
break; break;
} }
if (nbio->is_finished && nbio->image.is_finished) if (nbio->is_finished && nbio->image.is_finished && !task->cancelled)
{ {
task->task_data = malloc(sizeof(nbio->image.ti)); task->task_data = malloc(sizeof(nbio->image.ti));
memcpy(task->task_data, &nbio->image.ti, sizeof(nbio->image.ti)); memcpy(task->task_data, &nbio->image.ti, sizeof(nbio->image.ti));
@ -453,6 +453,13 @@ static void rarch_task_file_load_handler(rarch_task_t *task)
if (nbio->is_finished) if (nbio->is_finished)
goto task_finished; goto task_finished;
if (task->cancelled)
{
task->error = strdup("Task canceled.");
goto task_finished;
}
return; return;
task_finished: task_finished:

View File

@ -162,6 +162,9 @@ static void rarch_task_http_transfer_handler(rarch_task_t *task)
break; break;
} }
if (task->cancelled)
goto task_finished;
return; return;
task_finished: task_finished:
task->finished = true; task->finished = true;
@ -174,14 +177,17 @@ task_finished:
if (tmp && http->cb) if (tmp && http->cb)
http->cb(tmp, len); http->cb(tmp, len);
if (net_http_error(http->handle)) if (net_http_error(http->handle) || task->cancelled)
{ {
tmp = (char*)net_http_data(http->handle, &len, true); tmp = (char*)net_http_data(http->handle, &len, true);
if (tmp) if (tmp)
free(tmp); free(tmp);
task->error = strdup("Download failed."); if (task->cancelled)
task->error = strdup("Task cancelled.");
else
task->error = strdup("Download failed.");
} }
else else
{ {

View File

@ -629,17 +629,38 @@ static void rarch_task_overlay_handler(rarch_task_t *task)
goto task_finished; goto task_finished;
} }
if (task->cancelled)
goto task_finished;
return; return;
task_finished: task_finished:
task->finished = true; task->finished = true;
data = (overlay_task_data_t*)calloc(1, sizeof(*data)); if (task->cancelled)
{
struct overlay *o;
unsigned i;
data->overlays = loader->overlays; if (task->error)
data->size = loader->size; free(task->error);
data->active = loader->active;
task->task_data = data; task->error = strdup("Task cancelled.");
for (i = 0; i < loader->size; i++)
input_overlay_free_overlay(&loader->overlays[i]);
free(loader->overlays);
}
else
{
data = (overlay_task_data_t*)calloc(1, sizeof(*data));
data->overlays = loader->overlays;
data->size = loader->size;
data->active = loader->active;
task->task_data = data;
}
if (loader->overlay_path) if (loader->overlay_path)
free(loader->overlay_path); free(loader->overlay_path);

View File

@ -9,56 +9,54 @@
#include "rthreads/rthreads.h" #include "rthreads/rthreads.h"
#endif #endif
static rarch_task_t *running_queue = NULL; typedef struct {
static rarch_task_t *finished_queue = NULL; rarch_task_t *front;
rarch_task_t *back;
} task_queue_t;
struct rarch_task_impl { struct rarch_task_impl {
void (*push_running)(rarch_task_t *); void (*push_running)(rarch_task_t *);
void (*push_finished)(rarch_task_t *); void (*cancel)(void);
void (*wait)(void);
void (*gather)(void); void (*gather)(void);
void (*init)(void); void (*init)(void);
void (*deinit)(void); void (*deinit)(void);
}; };
static task_queue_t tasks_running = {NULL, NULL};
static task_queue_t tasks_finished = {NULL, NULL};
static struct rarch_task_impl *impl_current = NULL; static struct rarch_task_impl *impl_current = NULL;
static void _push_task(rarch_task_t **q, rarch_task_t *task) static void task_queue_put(task_queue_t *queue, rarch_task_t *task)
{ {
if (*q == NULL)
*q = task;
else
{
rarch_task_t *last = *q;
while (last->next)
last = last->next;
last->next = task;
}
task->next = NULL; task->next = NULL;
if (queue->front == NULL)
queue->front = task;
else
queue->back->next = task;
queue->back = task;
} }
static rarch_task_t *_pop_task(rarch_task_t **q) static rarch_task_t *task_queue_get(task_queue_t *queue)
{ {
rarch_task_t *task = *q; rarch_task_t *task = queue->front;
if (*q == NULL) if (task)
return NULL; {
queue->front = task->next;
*q = task->next; task->next = NULL;
task->next = NULL; }
return task; return task;
} }
static void rarch_task_internal_gather(void) static void rarch_task_internal_gather(void)
{ {
rarch_task_t *next = NULL; rarch_task_t *task;
while ((next = _pop_task(&finished_queue)) != NULL) while ((task = task_queue_get(&tasks_finished)) != NULL)
{ {
rarch_task_t *task = next;
next = next->next;
if (task->callback) if (task->callback)
task->callback(task->task_data, task->user_data, task->error); task->callback(task->task_data, task->user_data, task->error);
@ -69,14 +67,9 @@ static void rarch_task_internal_gather(void)
} }
} }
static void regular_push_finished(rarch_task_t *task)
{
_push_task(&finished_queue, task);
}
static void regular_push_running(rarch_task_t *task) static void regular_push_running(rarch_task_t *task)
{ {
_push_task(&running_queue, task); task_queue_put(&tasks_running, task);
} }
static void regular_gather(void) static void regular_gather(void)
@ -87,7 +80,7 @@ static void regular_gather(void)
/* mimics threaded_gather() for compatibility, a faster implementation /* mimics threaded_gather() for compatibility, a faster implementation
* can be written for systems without HAVE_THREADS if necessary. */ * can be written for systems without HAVE_THREADS if necessary. */
while ((task = _pop_task(&running_queue)) != NULL) while ((task = task_queue_get(&tasks_running)) != NULL)
{ {
task->next = queue; task->next = queue;
queue = task; queue = task;
@ -99,7 +92,7 @@ static void regular_gather(void)
task->handler(task); task->handler(task);
if (task->finished) if (task->finished)
regular_push_finished(task); task_queue_put(&tasks_finished, task);
else else
regular_push_running(task); regular_push_running(task);
} }
@ -107,6 +100,20 @@ static void regular_gather(void)
rarch_task_internal_gather(); rarch_task_internal_gather();
} }
static void regular_wait(void)
{
while (tasks_running.front)
regular_gather();
}
static void regular_cancel()
{
rarch_task_t *task;
for (task = tasks_running.front; task; task = task->next)
task->cancelled = true;
}
static void regular_init(void) static void regular_init(void)
{ {
} }
@ -117,7 +124,8 @@ static void regular_deinit(void)
static struct rarch_task_impl impl_regular = { static struct rarch_task_impl impl_regular = {
regular_push_running, regular_push_running,
regular_push_finished, regular_cancel,
regular_wait,
regular_gather, regular_gather,
regular_init, regular_init,
regular_deinit regular_deinit
@ -130,17 +138,10 @@ static scond_t *worker_cond = NULL;
static sthread_t *worker_thread = NULL; static sthread_t *worker_thread = NULL;
static bool worker_continue = true; /* use running_lock when touching it */ static bool worker_continue = true; /* use running_lock when touching it */
static void threaded_push_finished(rarch_task_t *task)
{
slock_lock(finished_lock);
_push_task(&finished_queue, task);
slock_unlock(finished_lock);
}
static void threaded_push_running(rarch_task_t *task) static void threaded_push_running(rarch_task_t *task)
{ {
slock_lock(running_lock); slock_lock(running_lock);
_push_task(&running_queue, task); task_queue_put(&tasks_running, task);
scond_signal(worker_cond); scond_signal(worker_cond);
slock_unlock(running_lock); slock_unlock(running_lock);
} }
@ -152,6 +153,29 @@ static void threaded_gather(void)
slock_unlock(finished_lock); slock_unlock(finished_lock);
} }
static void threaded_wait(void)
{
bool wait;
do
{
threaded_gather();
slock_lock(running_lock);
wait = (tasks_running.front != NULL);
slock_unlock(running_lock);
} while (wait);
}
static void threaded_cancel(void)
{
rarch_task_t *task;
slock_lock(running_lock);
for (task = tasks_running.front; task; task = task->next)
task->cancelled = true;
slock_unlock(running_lock);
}
static void threaded_worker(void *userdata) static void threaded_worker(void *userdata)
{ {
(void)userdata; (void)userdata;
@ -171,7 +195,7 @@ static void threaded_worker(void *userdata)
if (!worker_continue) if (!worker_continue)
break; /* should we keep running until all tasks finished? */ break; /* should we keep running until all tasks finished? */
while ((task = _pop_task(&running_queue)) != NULL) while ((task = task_queue_get(&tasks_running)) != NULL)
{ {
task->next = queue; task->next = queue;
queue = task; queue = task;
@ -192,7 +216,11 @@ static void threaded_worker(void *userdata)
task->handler(task); task->handler(task);
if (task->finished) if (task->finished)
threaded_push_finished(task); {
slock_lock(finished_lock);
task_queue_put(&tasks_finished, task);
slock_unlock(finished_lock);
}
else else
threaded_push_running(task); threaded_push_running(task);
} }
@ -235,7 +263,8 @@ static void threaded_deinit(void)
static struct rarch_task_impl impl_threaded = { static struct rarch_task_impl impl_threaded = {
threaded_push_running, threaded_push_running,
threaded_push_finished, threaded_cancel,
threaded_wait,
threaded_gather, threaded_gather,
threaded_init, threaded_init,
threaded_deinit threaded_deinit
@ -245,7 +274,8 @@ static struct rarch_task_impl impl_threaded = {
void rarch_task_init(void) void rarch_task_init(void)
{ {
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
if (config_get_ptr()->threaded_data_runloop_enable) settings_t *settings = config_get_ptr();
if (settings->threaded_data_runloop_enable)
impl_current = &impl_threaded; impl_current = &impl_threaded;
else else
#endif #endif
@ -281,7 +311,19 @@ void rarch_task_check(void)
impl_current->gather(); impl_current->gather();
} }
/* The lack of NULL checks in the following functions is proposital
* to ensure correct control flow by the users. */
void rarch_task_push(rarch_task_t *task) void rarch_task_push(rarch_task_t *task)
{ {
impl_current->push_running(task); impl_current->push_running(task);
} }
void rarch_task_wait(void)
{
impl_current->wait();
}
void rarch_task_reset(void)
{
impl_current->cancel();
}

View File

@ -37,9 +37,12 @@ struct rarch_task {
rarch_task_handler_t handler; rarch_task_handler_t handler;
rarch_task_callback_t callback; /* always called from the main loop */ rarch_task_callback_t callback; /* always called from the main loop */
/* set by the handler */ /* set to true by the handler to signal the task has finished executing. */
bool finished; bool finished;
/* set to true by the task system to signal the task *must* end. */
bool cancelled;
/* created by the handler, destroyed by the user */ /* created by the handler, destroyed by the user */
void *task_data; void *task_data;
@ -56,12 +59,57 @@ struct rarch_task {
rarch_task_t *next; rarch_task_t *next;
}; };
/* MAIN THREAD ONLY */ /**
* @brief Initializes the task system
*
* This function initializes the task system and chooses an appropriate
* implementation according to the settings.
*
* This function must only be called from the main thread.
*/
void rarch_task_init(void); void rarch_task_init(void);
/**
* @brief Deinitializes the task system
*
* This function deinitializes the task system. The tasks that are running at
* the moment will stay on hold until rarch_task_init() is called again.
*/
void rarch_task_deinit(void); void rarch_task_deinit(void);
/**
* @brief Checks for finished tasks
*
* Takes the finished tasks, if any, and runs their callbacks.
*
* This function must only be called from the main thread.
*/
void rarch_task_check(void); void rarch_task_check(void);
/* MAIN AND TASK THREADS */ /**
* @brief Sends a signal to terminate all the tasks.
*
* This function won't terminate the tasks immediately. They will finish as
* soon as possible.
*
* This function must only be called from the main thread.
*/
void rarch_task_reset(void);
/**
* @brief Blocks until all tasks have finished.
*
* This function must only be called from the main thread.
*/
void rarch_task_wait(void);
/**
* @brief Pushes a task
*
* The task will start as soon as possible.
*
* @param task
*/
void rarch_task_push(rarch_task_t *task); void rarch_task_push(rarch_task_t *task);
#ifdef HAVE_NETWORKING #ifdef HAVE_NETWORKING