19 #include <stdatomic.h>
25 #if HAVE_PTHREADS || HAVE_W32THREADS || HAVE_OS2THREADS
27 typedef struct WorkerContext {
36 WorkerContext *workers;
38 int nb_active_threads;
49 void (*
worker_func)(
void *priv,
int jobnr,
int threadnr,
int nb_jobs,
int nb_threads);
55 unsigned nb_jobs = ctx->nb_jobs;
56 unsigned nb_active_threads = ctx->nb_active_threads;
58 unsigned current_job = first_job;
61 ctx->worker_func(ctx->priv, current_job, first_job, nb_jobs, nb_active_threads);
64 return current_job == nb_jobs + nb_active_threads - 1;
67 static void *attribute_align_arg thread_worker(
void *v)
95 void (*
worker_func)(
void *priv,
int jobnr,
int threadnr,
int nb_jobs,
int nb_threads),
106 nb_threads = nb_cpus + 1;
111 nb_workers = nb_threads;
119 if (nb_workers && !(ctx->workers =
av_calloc(nb_workers,
sizeof(*ctx->workers)))) {
127 ctx->nb_threads = nb_threads;
128 ctx->nb_active_threads = 0;
138 for (i = 0; i < nb_workers; i++) {
139 WorkerContext *w = &ctx->workers[i];
166 int nb_workers, i, is_last = 0;
169 ctx->nb_jobs = nb_jobs;
170 ctx->nb_active_threads =
FFMIN(nb_jobs, ctx->nb_threads);
173 nb_workers = ctx->nb_active_threads;
174 if (!ctx->main_func || !execute_main)
177 for (i = 0; i < nb_workers; i++) {
178 WorkerContext *w = &ctx->workers[i];
185 if (ctx->main_func && execute_main)
186 ctx->main_func(ctx->priv);
188 is_last = run_jobs(ctx);
208 nb_workers = ctx->nb_threads;
213 for (i = 0; i < nb_workers; i++) {
214 WorkerContext *w = &ctx->workers[i];
221 for (i = 0; i < nb_workers; i++) {
222 WorkerContext *w = &ctx->workers[i];
237 void (*
worker_func)(
void *priv,
int jobnr,
int threadnr,
int nb_jobs,
int nb_threads),
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
#define pthread_mutex_lock(a)
static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
Memory handling functions.
static void worker_func(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads)
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
int(* cond)(enum AVPixelFormat pix_fmt)
#define av_assert0(cond)
assert() equivalent, that is always enabled.
struct AVSliceThread AVSliceThread
static av_always_inline int pthread_cond_signal(pthread_cond_t *cond)
simple assert() macros that are a bit more flexible than ISO C assert().
void avpriv_slicethread_free(AVSliceThread **pctx)
Destroy slice threading context.
typedef void(APIENTRY *FF_PFNGLACTIVETEXTUREPROC)(GLenum texture)
static av_always_inline int pthread_join(pthread_t thread, void **value_ptr)
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
#define pthread_mutex_unlock(a)
#define atomic_fetch_add_explicit(object, operand, order)
static av_always_inline int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
int avpriv_slicethread_create(AVSliceThread **pctx, void *priv, void(*worker_func)(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads), void(*main_func)(void *priv), int nb_threads)
Create slice threading context.
void avpriv_slicethread_execute(AVSliceThread *ctx, int nb_jobs, int execute_main)
Execute slice threading.
#define atomic_store_explicit(object, desired, order)
int( main_func)(AVCodecContext *c)
static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
#define atomic_init(obj, value)