diff --git a/libretro-common/include/queues/task_queue.h b/libretro-common/include/queues/task_queue.h index 7fc9e2b039..b72ce91192 100644 --- a/libretro-common/include/queues/task_queue.h +++ b/libretro-common/include/queues/task_queue.h @@ -82,8 +82,13 @@ enum task_queue_ctl_state TASK_QUEUE_CTL_UNSET_THREADED, - TASK_QUEUE_CTL_IS_THREADED -}; + TASK_QUEUE_CTL_IS_THREADED, + + /** + * Signals a task to end without waiting for + * it to complete. */ + TASK_QUEUE_CTL_CANCEL, + }; typedef struct retro_task retro_task_t; typedef void (*retro_task_callback_t)(void *task_data, @@ -148,6 +153,8 @@ void task_queue_push_progress(retro_task_t *task); bool task_queue_ctl(enum task_queue_ctl_state state, void *data); +void task_queue_cancel_task(void *task); + RETRO_END_DECLS #endif diff --git a/libretro-common/queues/task_queue.c b/libretro-common/queues/task_queue.c index f7406f4865..be254981b4 100644 --- a/libretro-common/queues/task_queue.c +++ b/libretro-common/queues/task_queue.c @@ -39,6 +39,7 @@ typedef struct struct retro_task_impl { void (*push_running)(retro_task_t *); + void (*cancel)(void *); void (*reset)(void); void (*wait)(void); void (*gather)(void); @@ -167,6 +168,12 @@ static void retro_task_regular_push_running(retro_task_t *task) task_queue_put(&tasks_running, task); } +static void retro_task_regular_cancel(void *task) +{ + retro_task_t *t = task; + t->cancelled = true; +} + static void retro_task_regular_gather(void) { retro_task_t *task = NULL; @@ -232,6 +239,7 @@ static bool retro_task_regular_find(retro_task_finder_t func, void *user_data) static struct retro_task_impl impl_regular = { retro_task_regular_push_running, + retro_task_regular_cancel, retro_task_regular_reset, retro_task_regular_wait, retro_task_regular_gather, @@ -255,6 +263,24 @@ static void retro_task_threaded_push_running(retro_task_t *task) slock_unlock(running_lock); } +static void retro_task_threaded_cancel(void *task) +{ + retro_task_t *t; + + slock_lock(running_lock); + + for (t = tasks_running.front; t; t = t->next) + { + if (t == task) + { + t->cancelled = true; + break; + } + } + + slock_unlock(running_lock); +} + static void retro_task_threaded_gather(void) { retro_task_t *task = NULL; @@ -399,6 +425,7 @@ static void retro_task_threaded_deinit(void) static struct retro_task_impl impl_threaded = { retro_task_threaded_push_running, + retro_task_threaded_cancel, retro_task_threaded_reset, retro_task_threaded_wait, retro_task_threaded_gather, @@ -484,6 +511,9 @@ bool task_queue_ctl(enum task_queue_ctl_state state, void *data) case TASK_QUEUE_CTL_WAIT: impl_current->wait(); break; + case TASK_QUEUE_CTL_CANCEL: + impl_current->cancel(data); + break; case TASK_QUEUE_CTL_NONE: default: break; @@ -491,3 +521,8 @@ bool task_queue_ctl(enum task_queue_ctl_state state, void *data) return true; } + +void task_queue_cancel_task(void *task) +{ + task_queue_ctl(TASK_QUEUE_CTL_CANCEL, task); +} diff --git a/tasks/task_http.c b/tasks/task_http.c index b77c8512d6..36ff154c8f 100644 --- a/tasks/task_http.c +++ b/tasks/task_http.c @@ -127,6 +127,9 @@ static void rarch_task_http_transfer_handler(retro_task_t *task) http_handle_t *http = (http_handle_t*)task->state; http_transfer_data_t *data; + if (task->cancelled) + goto task_finished; + switch (http->status) { case HTTP_STATUS_CONNECTION_TRANSFER_PARSE: @@ -148,7 +151,7 @@ static void rarch_task_http_transfer_handler(retro_task_t *task) break; } - if (task->cancelled || http->error) + if (http->error) goto task_finished; return; @@ -251,7 +254,7 @@ static bool rarch_task_http_retriever(retro_task_t *task, void *user_data) return false; } -bool rarch_task_push_http_transfer(const char *url, const char *type, +void *rarch_task_push_http_transfer(const char *url, const char *type, retro_task_callback_t cb, void *user_data) { char tmp[PATH_MAX_LENGTH]; @@ -261,7 +264,7 @@ bool rarch_task_push_http_transfer(const char *url, const char *type, http_handle_t *http = NULL; if (string_is_empty(url)) - return false; + return NULL; find_data.func = rarch_task_http_finder; find_data.userdata = (void*)url; @@ -270,13 +273,13 @@ bool rarch_task_push_http_transfer(const char *url, const char *type, if (task_queue_ctl(TASK_QUEUE_CTL_FIND, &find_data)) { RARCH_LOG("[http] '%s'' is already being downloaded.\n", url); - return false; + return NULL; } conn = net_http_connection_new(url); if (!conn) - return false; + return NULL; http = (http_handle_t*)calloc(1, sizeof(*http)); @@ -310,7 +313,7 @@ bool rarch_task_push_http_transfer(const char *url, const char *type, task_queue_ctl(TASK_QUEUE_CTL_PUSH, t); - return true; + return t; error: if (conn) @@ -320,7 +323,7 @@ error: if (http) free(http); - return false; + return NULL; } http_transfer_info_t *http_task_get_transfer_list() diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h index 5bcdc230c0..7f477b4499 100644 --- a/tasks/tasks_internal.h +++ b/tasks/tasks_internal.h @@ -41,7 +41,7 @@ typedef struct http_transfer_info struct http_transfer_info *next; } http_transfer_info_t; -bool rarch_task_push_http_transfer(const char *url, const char *type, +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();