commit
dba90266db
|
@ -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())
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
138
tasks/tasks.c
138
tasks/tasks.c
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue