diff --git a/libretro-common/include/queues/task_queue.h b/libretro-common/include/queues/task_queue.h index e2d773b346..20f0aceef3 100644 --- a/libretro-common/include/queues/task_queue.h +++ b/libretro-common/include/queues/task_queue.h @@ -32,6 +32,16 @@ RETRO_BEGIN_DECLS +enum task_type +{ + TASK_TYPE_NONE, + /* Only one blocking task can exist in the queue at a time. + * Attempts to add a new one while another is running is + * ignored. + */ + TASK_TYPE_BLOCKING +}; + enum task_queue_ctl_state { TASK_QUEUE_CTL_NONE = 0, @@ -158,6 +168,8 @@ struct retro_task * free()d automatically if non-NULL. */ char *title; + enum task_type type; + /* don't touch this. */ retro_task_t *next; }; diff --git a/libretro-common/queues/task_queue.c b/libretro-common/queues/task_queue.c index 1b04187d94..6390ae1c59 100644 --- a/libretro-common/queues/task_queue.c +++ b/libretro-common/queues/task_queue.c @@ -571,9 +571,30 @@ bool task_queue_ctl(enum task_queue_ctl_state state, void *data) break; case TASK_QUEUE_CTL_PUSH: { + retro_task_t *task = (retro_task_t*)data; + + /* Ignore this task if a related one is already running */ + if (task->type == TASK_TYPE_BLOCKING) + { + retro_task_t *running = tasks_running.front; + bool found = false; + + for (; running; running = running->next) + { + if (running->type == TASK_TYPE_BLOCKING) + { + found = true; + break; + } + } + + /* skip this task, user must try again later */ + if (found) + break; + } + /* The lack of NULL checks in the following functions * is proposital to ensure correct control flow by the users. */ - retro_task_t *task = (retro_task_t*)data; impl_current->push_running(task); break; } diff --git a/tasks/task_save.c b/tasks/task_save.c index 13fcb2a8cc..08fdeb989c 100644 --- a/tasks/task_save.c +++ b/tasks/task_save.c @@ -614,6 +614,7 @@ static void task_push_undo_save_state(const char *path, void *data, size_t size) state->size = size; state->undo_save = true; + task->type = TASK_TYPE_BLOCKING; task->state = state; task->handler = task_save_handler; task->callback = undo_save_state_cb; @@ -945,6 +946,7 @@ static void task_push_save_state(const char *path, void *data, size_t size) state->data = data; state->size = size; + task->type = TASK_TYPE_BLOCKING; task->state = state; task->handler = task_save_handler; task->title = strdup(msg_hash_to_str(MSG_SAVING_STATE)); @@ -1001,7 +1003,7 @@ static void task_push_load_and_save_state(const char *path, void *data, size_t s state->undo_data = data; task->state = state; - + task->type = TASK_TYPE_BLOCKING; task->handler = task_load_handler; task->callback = content_load_and_save_state_cb; task->title = strdup(msg_hash_to_str(MSG_LOADING_STATE)); @@ -1122,6 +1124,7 @@ bool content_load_state(const char *path, bool load_to_backup_buffer, bool autol state->load_to_backup_buffer = load_to_backup_buffer; state->autoload = autoload; + task->type = TASK_TYPE_BLOCKING; task->state = state; task->handler = task_load_handler; task->callback = content_load_state_cb;