From 8f6bb23f38402d80c475e0f9ee53b71809e542d8 Mon Sep 17 00:00:00 2001 From: Sebastien Ronsse Date: Fri, 6 May 2016 14:29:58 +1000 Subject: [PATCH] task queue: Implement running tasks retrieval mechanism --- libretro-common/include/queues/task_queue.h | 28 +++++++ libretro-common/queues/task_queue.c | 86 +++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/libretro-common/include/queues/task_queue.h b/libretro-common/include/queues/task_queue.h index b72ce91192..a7482158b3 100644 --- a/libretro-common/include/queues/task_queue.h +++ b/libretro-common/include/queues/task_queue.h @@ -56,6 +56,14 @@ enum task_queue_ctl_state */ TASK_QUEUE_CTL_FIND, + /** + * Calls func for every running task when handler + * parameter matches task handler, allowing the + * list parameter to be filled with user-defined + * data. + */ + TASK_QUEUE_CTL_RETRIEVE, + /* Blocks until all tasks have finished. * This must only be called from the main thread. */ TASK_QUEUE_CTL_WAIT, @@ -99,6 +107,8 @@ typedef void (*retro_task_handler_t)(retro_task_t *task); typedef bool (*retro_task_finder_t)(retro_task_t *task, void *userdata); +typedef bool (*retro_task_retriever_t)(retro_task_t *task, void *data); + typedef struct { char *source_file; @@ -149,10 +159,28 @@ typedef struct task_finder_data void *userdata; } task_finder_data_t; +typedef struct task_retriever_info +{ + struct task_retriever_info *next; + void *data; +} task_retriever_info_t; + +typedef struct task_retriever_data +{ + retro_task_handler_t handler; + size_t element_size; + retro_task_retriever_t func; + task_retriever_info_t *list; +} task_retriever_data_t; + void task_queue_push_progress(retro_task_t *task); bool task_queue_ctl(enum task_queue_ctl_state state, void *data); +void *task_queue_retriever_info_next(task_retriever_info_t **link); + +void task_queue_retriever_info_free(task_retriever_info_t *list); + void task_queue_cancel_task(void *task); RETRO_END_DECLS diff --git a/libretro-common/queues/task_queue.c b/libretro-common/queues/task_queue.c index be254981b4..388b0ba99b 100644 --- a/libretro-common/queues/task_queue.c +++ b/libretro-common/queues/task_queue.c @@ -44,6 +44,7 @@ struct retro_task_impl void (*wait)(void); void (*gather)(void); bool (*find)(retro_task_finder_t, void*); + void (*retrieve)(task_retriever_data_t *data); void (*init)(void); void (*deinit)(void); }; @@ -237,6 +238,43 @@ static bool retro_task_regular_find(retro_task_finder_t func, void *user_data) return false; } +static void retro_task_regular_retrieve(task_retriever_data_t *data) +{ + retro_task_t *task; + task_retriever_info_t *info; + task_retriever_info_t *tail = NULL; + + /* Parse all running tasks and handle matching handlers */ + for (task = tasks_running.front; task != NULL; task = task->next) + if (task->handler == data->handler) + { + /* Create new link */ + info = malloc(sizeof(task_retriever_info_t)); + info->data = malloc(data->element_size); + info->next = NULL; + + /* Call retriever function and fill info-specific data */ + if (!data->func(task, info->data)) + { + free(info->data); + free(info); + continue; + } + + /* Add link to list */ + if (data->list == NULL) + { + data->list = info; + tail = data->list; + } + else + { + tail->next = info; + tail = tail->next; + } + } +} + static struct retro_task_impl impl_regular = { retro_task_regular_push_running, retro_task_regular_cancel, @@ -244,6 +282,7 @@ static struct retro_task_impl impl_regular = { retro_task_regular_wait, retro_task_regular_gather, retro_task_regular_find, + retro_task_regular_retrieve, retro_task_regular_init, retro_task_regular_deinit }; @@ -341,6 +380,20 @@ static bool retro_task_threaded_find( return result; } +static void retro_task_threaded_retrieve(task_retriever_data_t *data) +{ + retro_task_t *task; + + /* Protect access to running tasks */ + slock_lock(running_lock); + + /* Call regular retrieve function */ + retro_task_regular_retrieve(data); + + /* Release access to running tasks */ + slock_unlock(running_lock); +} + static void threaded_worker(void *userdata) { (void)userdata; @@ -430,6 +483,7 @@ static struct retro_task_impl impl_threaded = { retro_task_threaded_wait, retro_task_threaded_gather, retro_task_threaded_find, + retro_task_threaded_retrieve, retro_task_threaded_init, retro_task_threaded_deinit }; @@ -480,6 +534,9 @@ bool task_queue_ctl(enum task_queue_ctl_state state, void *data) return false; } break; + case TASK_QUEUE_CTL_RETRIEVE: + impl_current->retrieve(data); + break; case TASK_QUEUE_CTL_CHECK: { #ifdef HAVE_THREADS @@ -526,3 +583,32 @@ void task_queue_cancel_task(void *task) { task_queue_ctl(TASK_QUEUE_CTL_CANCEL, task); } + +void *task_queue_retriever_info_next(task_retriever_info_t **link) +{ + void *data = NULL; + + /* Grab data and move to next link */ + if (*link) + { + data = (*link)->data; + *link = (*link)->next; + } + + return data; +} + +void task_queue_retriever_info_free(task_retriever_info_t *list) +{ + task_retriever_info_t *info; + + /* Free links including retriever-specific data */ + while (list) + { + info = list->next; + free(list->data); + free(list); + list = info; + } +} +