mirror of
https://github.com/libretro/RetroArch
synced 2025-02-01 09:32:58 +00:00
Merge pull request #2957 from sronsse/fixes_for_team
Task retrieval mechanism
This commit is contained in:
commit
6708be93e4
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user