mirror of
https://github.com/libretro/RetroArch
synced 2025-03-29 22:20:21 +00:00
apple: use gcd for task queue (#17248)
This commit is contained in:
parent
0e26bea0b2
commit
62c725579a
@ -28,10 +28,18 @@
|
||||
|
||||
#include <features/features_cpu.h>
|
||||
|
||||
#if defined(HAVE_GCD) && !defined(HAVE_THREADS)
|
||||
#error "gcd uses threads, what are you doing"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#include <rthreads/rthreads.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GCD
|
||||
#include <dispatch/dispatch.h>
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
retro_task_t *front;
|
||||
@ -72,6 +80,10 @@ static bool worker_continue = true;
|
||||
/* use running_lock when touching it */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GCD
|
||||
static unsigned gcd_queue_count = 0;
|
||||
#endif
|
||||
|
||||
static void task_queue_msg_push(retro_task_t *task,
|
||||
unsigned prio, unsigned duration,
|
||||
bool flush, const char *fmt, ...)
|
||||
@ -481,11 +493,14 @@ static void threaded_worker(void *userdata)
|
||||
retro_task_t *task = NULL;
|
||||
bool finished = false;
|
||||
|
||||
if (!worker_continue)
|
||||
break; /* should we keep running until all tasks finished? */
|
||||
|
||||
slock_lock(running_lock);
|
||||
|
||||
if (!worker_continue)
|
||||
{
|
||||
slock_unlock(running_lock);
|
||||
break; /* should we keep running until all tasks finished? */
|
||||
}
|
||||
|
||||
/* Get first task to run */
|
||||
if (!(task = tasks_running.front))
|
||||
{
|
||||
@ -602,6 +617,152 @@ static struct retro_task_impl impl_threaded = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GCD
|
||||
|
||||
static void gcd_worker(retro_task_t *task)
|
||||
{
|
||||
bool finished = false;
|
||||
slock_lock(running_lock);
|
||||
|
||||
if (!worker_continue)
|
||||
{
|
||||
gcd_queue_count--;
|
||||
if (!gcd_queue_count)
|
||||
scond_signal(worker_cond);
|
||||
slock_unlock(running_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
if (task->when)
|
||||
{
|
||||
retro_time_t now = cpu_features_get_time_usec();
|
||||
retro_time_t delay = task->when - now - 500;
|
||||
if (delay > 0)
|
||||
{
|
||||
dispatch_time_t after = dispatch_time(DISPATCH_TIME_NOW, delay);
|
||||
dispatch_after(after, dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0),
|
||||
^{ gcd_worker(task); });
|
||||
slock_unlock(running_lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
slock_unlock(running_lock);
|
||||
|
||||
task->handler(task);
|
||||
|
||||
slock_lock(property_lock);
|
||||
finished = ((task->flags & RETRO_TASK_FLG_FINISHED) > 0) ? true : false;
|
||||
slock_unlock(property_lock);
|
||||
|
||||
if (!finished)
|
||||
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0),
|
||||
^{ gcd_worker(task); });
|
||||
else
|
||||
{
|
||||
/* Remove task from running queue */
|
||||
slock_lock(running_lock);
|
||||
slock_lock(queue_lock);
|
||||
gcd_queue_count--;
|
||||
if (!gcd_queue_count)
|
||||
scond_signal(worker_cond);
|
||||
task_queue_remove(&tasks_running, task);
|
||||
slock_unlock(queue_lock);
|
||||
slock_unlock(running_lock);
|
||||
|
||||
/* Add task to finished queue */
|
||||
slock_lock(finished_lock);
|
||||
task_queue_put(&tasks_finished, task);
|
||||
slock_unlock(finished_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void retro_task_gcd_push_running(retro_task_t *task)
|
||||
{
|
||||
slock_lock(running_lock);
|
||||
slock_lock(queue_lock);
|
||||
task_queue_put(&tasks_running, task);
|
||||
gcd_queue_count++;
|
||||
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0),
|
||||
^{ gcd_worker(task); });
|
||||
slock_unlock(queue_lock);
|
||||
slock_unlock(running_lock);
|
||||
}
|
||||
|
||||
static void retro_task_gcd_wait(retro_task_condition_fn_t cond, void* data)
|
||||
{
|
||||
bool wait = false;
|
||||
|
||||
do
|
||||
{
|
||||
retro_task_t *task = NULL;
|
||||
retro_task_threaded_gather();
|
||||
|
||||
slock_lock(running_lock);
|
||||
wait = false;
|
||||
/* can't just look at the first task like threaded, they're not sorted by when */
|
||||
for (task = tasks_running.front; !wait && task; task = task->next)
|
||||
wait |= !task->when;
|
||||
slock_unlock(running_lock);
|
||||
|
||||
if (!wait)
|
||||
{
|
||||
slock_lock(finished_lock);
|
||||
for (task = tasks_finished.front; !wait && task; task = task->next)
|
||||
wait |= !task->when;
|
||||
slock_unlock(finished_lock);
|
||||
}
|
||||
} while (wait && (!cond || cond(data)));
|
||||
}
|
||||
|
||||
static void retro_task_gcd_init(void)
|
||||
{
|
||||
running_lock = slock_new();
|
||||
finished_lock = slock_new();
|
||||
property_lock = slock_new();
|
||||
queue_lock = slock_new();
|
||||
worker_cond = scond_new();
|
||||
|
||||
slock_lock(running_lock);
|
||||
worker_continue = true;
|
||||
slock_unlock(running_lock);
|
||||
}
|
||||
|
||||
static void retro_task_gcd_deinit(void)
|
||||
{
|
||||
slock_lock(running_lock);
|
||||
worker_continue = false;
|
||||
if (gcd_queue_count)
|
||||
scond_wait(worker_cond, running_lock);
|
||||
slock_unlock(running_lock);
|
||||
|
||||
scond_free(worker_cond);
|
||||
slock_free(running_lock);
|
||||
slock_free(finished_lock);
|
||||
slock_free(property_lock);
|
||||
slock_free(queue_lock);
|
||||
|
||||
worker_cond = NULL;
|
||||
running_lock = NULL;
|
||||
finished_lock = NULL;
|
||||
property_lock = NULL;
|
||||
queue_lock = NULL;
|
||||
}
|
||||
|
||||
static struct retro_task_impl impl_gcd = {
|
||||
NULL,
|
||||
retro_task_gcd_push_running,
|
||||
retro_task_threaded_cancel,
|
||||
retro_task_threaded_reset,
|
||||
retro_task_gcd_wait,
|
||||
retro_task_threaded_gather,
|
||||
retro_task_threaded_find,
|
||||
retro_task_threaded_retrieve,
|
||||
retro_task_gcd_init,
|
||||
retro_task_gcd_deinit
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Deinitializes the task system.
|
||||
* This deinitializes the task system.
|
||||
* The tasks that are running at
|
||||
@ -621,7 +782,11 @@ void task_queue_init(bool threaded, retro_task_queue_msg_t msg_push)
|
||||
if (threaded)
|
||||
{
|
||||
task_threaded_enable = true;
|
||||
#ifdef HAVE_GCD
|
||||
impl_current = &impl_gcd;
|
||||
#else
|
||||
impl_current = &impl_threaded;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -659,7 +824,7 @@ void task_queue_retrieve(task_retriever_data_t *data)
|
||||
void task_queue_check(void)
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
bool current_threaded = (impl_current == &impl_threaded);
|
||||
bool current_threaded = (impl_current != &impl_regular);
|
||||
bool want_threaded = task_threaded_enable;
|
||||
|
||||
if (want_threaded != current_threaded)
|
||||
|
@ -28,6 +28,7 @@ OTHER_CFLAGS = $(inherited) -DHAVE_DYNAMIC
|
||||
OTHER_CFLAGS = $(inherited) -DHAVE_EASTEREGG
|
||||
OTHER_CFLAGS = $(inherited) -DHAVE_FILTERS_BUILTIN
|
||||
OTHER_CFLAGS = $(inherited) -DHAVE_FLAC
|
||||
OTHER_CFLAGS = $(inherited) -DHAVE_GCD
|
||||
OTHER_CFLAGS = $(inherited) -DHAVE_GFX_WIDGETS
|
||||
OTHER_CFLAGS = $(inherited) -DHAVE_GIT_VERSION
|
||||
OTHER_CFLAGS = $(inherited) -DHAVE_GLSL
|
||||
|
Loading…
x
Reference in New Issue
Block a user