Merge pull request #2957 from sronsse/fixes_for_team

Task retrieval mechanism
This commit is contained in:
Twinaphex 2016-05-06 16:22:52 +02:00
commit 6708be93e4
4 changed files with 129 additions and 58 deletions

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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,