From 8f6bb23f38402d80c475e0f9ee53b71809e542d8 Mon Sep 17 00:00:00 2001 From: Sebastien Ronsse Date: Fri, 6 May 2016 14:29:58 +1000 Subject: [PATCH 1/2] 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; + } +} + From 9f45722020617ccac79d510e3d053a0e43eca17c Mon Sep 17 00:00:00 2001 From: Sebastien Ronsse Date: Fri, 6 May 2016 14:31:25 +1000 Subject: [PATCH 2/2] task http: Update http_task_get_transfer_list using new task retrieval mechanism --- tasks/task_http.c | 68 +++++++++--------------------------------- tasks/tasks_internal.h | 5 +--- 2 files changed, 15 insertions(+), 58 deletions(-) diff --git a/tasks/task_http.c b/tasks/task_http.c index e22f739e7c..a69e7ae6c1 100644 --- a/tasks/task_http.c +++ b/tasks/task_http.c @@ -211,47 +211,20 @@ static bool rarch_task_http_finder(retro_task_t *task, void *user_data) return string_is_equal(http->connection.url, (const char*)user_data); } -static bool rarch_task_http_retriever(retro_task_t *task, void *user_data) +static bool rarch_task_http_retriever(retro_task_t *task, void *data) { http_handle_t *http; - http_transfer_info_t **list = user_data; - http_transfer_info_t *info; - http_transfer_info_t *link; + http_transfer_info_t *info = data; - /* Check if task is valid and corresponding to an HTTP transfer */ - if (!task || (task->handler != rarch_task_http_transfer_handler)) - return false; - - /* Check if user data argument is valid */ - if (!list) - return false; - - /* Extract HTTP handle and check if it is valid */ - http = (http_handle_t*)task->state; + /* Extract HTTP handle and return already if invalid */ + http = (http_handle_t *)task->state; if (!http) return false; - /* Create new HTTP info link */ - info = malloc(sizeof(http_transfer_info_t)); + /* Fill HTTP info link */ strlcpy(info->url, http->connection.url, sizeof(info->url)); info->progress = task->progress; - info->next = NULL; - - /* Add link to list */ - if (*list == NULL) - { - /* Initialize list with info if required */ - *list = info; - } - else - { - /* Cycle through list until end is reached and add info */ - for (link = *list; link->next != NULL; link = link->next); - link->next = info; - } - - /* Request task finder to continue searching in all cases */ - return false; + return true; } void *rarch_task_push_http_transfer(const char *url, const char *type, @@ -326,30 +299,17 @@ error: return NULL; } -http_transfer_info_t *http_task_get_transfer_list(void) +task_retriever_info_t *http_task_get_transfer_list(void) { - http_transfer_info_t *list = NULL; - task_finder_data_t find_data; + task_retriever_data_t retrieve_data; - /* Fill find data */ - find_data.func = rarch_task_http_retriever; - find_data.userdata = &list; + /* Fill retrieve data */ + retrieve_data.handler = rarch_task_http_transfer_handler; + retrieve_data.element_size = sizeof(http_transfer_info_t); + retrieve_data.func = rarch_task_http_retriever; /* Build list of current HTTP transfers and return it */ - task_queue_ctl(TASK_QUEUE_CTL_FIND, &find_data); - return list; -} - -void http_task_free_transfer_list(http_transfer_info_t *list) -{ - http_transfer_info_t *link; - - /* Free list of transfers */ - while (list) - { - link = list->next; - free(list); - list = link; - } + task_queue_ctl(TASK_QUEUE_CTL_RETRIEVE, &retrieve_data); + return retrieve_data.list; } diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h index cc4ad6e3a6..44562f2bad 100644 --- a/tasks/tasks_internal.h +++ b/tasks/tasks_internal.h @@ -38,15 +38,12 @@ typedef struct http_transfer_info { char url[PATH_MAX_LENGTH]; int progress; - struct http_transfer_info *next; } http_transfer_info_t; void *rarch_task_push_http_transfer(const char *url, const char *type, retro_task_callback_t cb, void *userdata); -http_transfer_info_t *http_task_get_transfer_list(void); - -void http_task_free_transfer_list(http_transfer_info_t *list); +task_retriever_info_t *http_task_get_transfer_list(void); #endif bool rarch_task_push_image_load(const char *fullpath, const char *type,