mirror of
https://github.com/libretro/RetroArch
synced 2025-02-19 12:41:00 +00:00
task queue: Implement running tasks retrieval mechanism
This commit is contained in:
parent
10fe532d29
commit
8f6bb23f38
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user