RetroArch/libretro-common/include/queues/task_queue.h

271 lines
7.3 KiB
C

/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (task_queue.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_TASK_QUEUE_H__
#define __LIBRETRO_SDK_TASK_QUEUE_H__
#include <stdint.h>
#include <stddef.h>
#include <boolean.h>
#include <retro_common.h>
#include <retro_common_api.h>
#include <libretro.h>
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_style
{
TASK_STYLE_NONE,
TASK_STYLE_POSITIVE,
TASK_STYLE_NEGATIVE
};
typedef struct retro_task retro_task_t;
typedef void (*retro_task_callback_t)(retro_task_t *task,
void *task_data,
void *user_data, const char *error);
typedef void (*retro_task_handler_t)(retro_task_t *task);
typedef bool (*retro_task_finder_t)(retro_task_t *task,
void *userdata);
typedef void (*retro_task_queue_msg_t)(retro_task_t *task,
const char *msg,
unsigned prio, unsigned duration, bool flush);
typedef bool (*retro_task_retriever_t)(retro_task_t *task, void *data);
typedef bool (*retro_task_condition_fn_t)(void *data);
typedef struct
{
char *source_file;
} decompress_task_data_t;
struct retro_task
{
/* when the task should run (0 for as soon as possible) */
retro_time_t when;
retro_task_handler_t handler;
/* always called from the main loop */
retro_task_callback_t callback;
/* task cleanup handler to free allocated resources, will
* be called immediately after running the main callback */
retro_task_handler_t cleanup;
/* created by the handler, destroyed by the user */
void *task_data;
/* owned by the user */
void *user_data;
/* created and destroyed by the code related to the handler */
void *state;
/* created by task handler; destroyed by main loop
* (after calling the callback) */
char *error;
void (*progress_cb)(retro_task_t*);
/* handler can modify but will be
* free()d automatically if non-NULL. */
char *title;
/* frontend userdata
* (e.g. associate a sticky notification to a task) */
void *frontend_userdata;
/* don't touch this. */
retro_task_t *next;
/* -1 = unmetered/indeterminate, 0-100 = current progress percentage */
int8_t progress;
/* task identifier */
uint32_t ident;
enum task_type type;
enum task_style style;
/* if set to true, frontend will
use an alternative look for the
task progress display */
bool alternative_look;
/* set to true by the handler to signal
* the task has finished executing. */
bool finished;
/* set to true by the task system
* to signal the task *must* end. */
bool cancelled;
/* if true no OSD messages will be displayed. */
bool mute;
};
typedef struct task_finder_data
{
retro_task_finder_t func;
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
{
task_retriever_info_t *list;
retro_task_handler_t handler;
retro_task_retriever_t func;
size_t element_size;
} task_retriever_data_t;
void *task_queue_retriever_info_next(task_retriever_info_t **link);
void task_queue_retriever_info_free(task_retriever_info_t *list);
/**
* Signals a task to end without waiting for
* it to complete. */
void task_queue_cancel_task(void *task);
void task_set_finished(retro_task_t *task, bool finished);
void task_set_mute(retro_task_t *task, bool mute);
void task_set_error(retro_task_t *task, char *error);
void task_set_progress(retro_task_t *task, int8_t progress);
void task_set_title(retro_task_t *task, char *title);
void task_set_data(retro_task_t *task, void *data);
void task_set_cancelled(retro_task_t *task, bool cancelled);
void task_free_title(retro_task_t *task);
bool task_get_cancelled(retro_task_t *task);
bool task_get_finished(retro_task_t *task);
bool task_get_mute(retro_task_t *task);
char* task_get_error(retro_task_t *task);
int8_t task_get_progress(retro_task_t *task);
char* task_get_title(retro_task_t *task);
void* task_get_data(retro_task_t *task);
bool task_is_on_main_thread(void);
void task_queue_set_threaded(void);
void task_queue_unset_threaded(void);
bool task_queue_is_threaded(void);
/**
* Calls func for every running task
* until it returns true.
* Returns a task or NULL if not found.
*/
bool task_queue_find(task_finder_data_t *find_data);
/**
* Calls func for every running task when handler
* parameter matches task handler, allowing the
* list parameter to be filled with user-defined
* data.
*/
void task_queue_retrieve(task_retriever_data_t *data);
/* Checks for finished tasks
* Takes the finished tasks, if any,
* and runs their callbacks.
* This must only be called from the main thread. */
void task_queue_check(void);
/* Pushes a task
* The task will start as soon as possible.
* If a second blocking task is attempted, false will be returned
* and the task will be ignored. */
bool task_queue_push(retro_task_t *task);
/* Blocks until all non-scheduled tasks have finished.
* Will return early if cond is not NULL
* and cond(data) returns false.
* This must only be called from the main thread. */
void task_queue_wait(retro_task_condition_fn_t cond, void* data);
/* Sends a signal to terminate all the tasks.
*
* This won't terminate the tasks immediately.
* They will finish as soon as possible.
*
* This must only be called from the main thread. */
void task_queue_reset(void);
/* Deinitializes the task system.
* This deinitializes the task system.
* The tasks that are running at
* the moment will stay on hold */
void task_queue_deinit(void);
/* Initializes the task system.
* This initializes the task system
* and chooses an appropriate
* implementation according to the settings.
*
* This must only be called from the main thread. */
void task_queue_init(bool threaded, retro_task_queue_msg_t msg_push);
/* Allocates and inits a new retro_task_t */
retro_task_t *task_init(void);
RETRO_END_DECLS
#endif