[vlc-commits] misc: remove background_worker
Romain Vimont
git at videolan.org
Fri Oct 23 17:48:08 CEST 2020
vlc | branch: master | Romain Vimont <rom1v at videolabs.io> | Fri Sep 4 17:10:35 2020 +0200| [e2530e5aef32f57be85b86715188e0e4099c63ff] | committer: Alexandre Janniaux
misc: remove background_worker
A new "minimal" executor API has been introduced to replace it.
Signed-off-by: Alexandre Janniaux <ajanni at videolabs.io>
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=e2530e5aef32f57be85b86715188e0e4099c63ff
---
src/Makefile.am | 2 -
src/misc/background_worker.c | 363 -------------------------------------------
src/misc/background_worker.h | 203 ------------------------
3 files changed, 568 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am
index 4803093c93..5e691b1b01 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -352,8 +352,6 @@ libvlccore_la_SOURCES = \
text/iso_lang.c \
text/iso-639_def.h \
misc/actions.c \
- misc/background_worker.c \
- misc/background_worker.h \
misc/executor.c \
misc/md5.c \
misc/probe.c \
diff --git a/src/misc/background_worker.c b/src/misc/background_worker.c
deleted file mode 100644
index 05e28d813c..0000000000
--- a/src/misc/background_worker.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 2017 VLC authors and VideoLAN
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <assert.h>
-#include <vlc_common.h>
-#include <vlc_list.h>
-#include <vlc_threads.h>
-
-#include "libvlc.h"
-#include "background_worker.h"
-
-struct task {
- struct vlc_list node;
- void* id; /**< id associated with entity */
- void* entity; /**< the entity to process */
- vlc_tick_t timeout; /**< timeout duration in vlc_tick_t */
-};
-
-struct background_worker;
-
-struct background_thread {
- struct background_worker *owner;
- vlc_cond_t probe_cancel_wait; /**< wait for probe request or cancelation */
- bool probe; /**< true if a probe is requested */
- bool cancel; /**< true if a cancel is requested */
- struct task *task; /**< current task */
- struct vlc_list node;
-};
-
-struct background_worker {
- void* owner;
- struct background_worker_config conf;
-
- vlc_mutex_t lock;
-
- int uncompleted; /**< number of tasks requested but not completed */
- int nthreads; /**< number of threads in the threads list */
- struct vlc_list threads; /**< list of active background_thread instances */
-
- struct vlc_list queue; /**< queue of tasks */
- vlc_cond_t queue_wait; /**< wait for the queue to be non-empty */
-
- vlc_cond_t nothreads_wait; /**< wait for nthreads == 0 */
- bool closing; /**< true if background worker deletion is requested */
-};
-
-static struct task *task_Create(struct background_worker *worker, void *id,
- void *entity, int timeout)
-{
- struct task *task = malloc(sizeof(*task));
- if (unlikely(!task))
- return NULL;
-
- task->id = id;
- task->entity = entity;
- task->timeout = timeout < 0 ? worker->conf.default_timeout : VLC_TICK_FROM_MS(timeout);
- worker->conf.pf_hold(task->entity);
- return task;
-}
-
-static void task_Destroy(struct background_worker *worker, struct task *task)
-{
- worker->conf.pf_release(task->entity);
- free(task);
-}
-
-static struct task *QueueTake(struct background_worker *worker, int timeout_ms)
-{
- vlc_mutex_assert(&worker->lock);
-
- vlc_tick_t deadline = vlc_tick_now() + VLC_TICK_FROM_MS(timeout_ms);
- bool timeout = false;
- while (!timeout && !worker->closing && vlc_list_is_empty(&worker->queue))
- timeout = vlc_cond_timedwait(&worker->queue_wait,
- &worker->lock, deadline) != 0;
-
- if (worker->closing || timeout)
- return NULL;
-
- struct task *task = vlc_list_first_entry_or_null(&worker->queue,
- struct task, node);
- assert(task);
- vlc_list_remove(&task->node);
-
- return task;
-}
-
-static void QueuePush(struct background_worker *worker, struct task *task)
-{
- vlc_mutex_assert(&worker->lock);
- vlc_list_append(&task->node, &worker->queue);
- vlc_cond_signal(&worker->queue_wait);
-}
-
-static void QueueRemoveAll(struct background_worker *worker, void *id)
-{
- vlc_mutex_assert(&worker->lock);
- struct task *task;
- vlc_list_foreach(task, &worker->queue, node)
- {
- if (!id || task->id == id)
- {
- vlc_list_remove(&task->node);
- task_Destroy(worker, task);
- }
- }
-}
-
-static struct background_thread *
-background_thread_Create(struct background_worker *owner)
-{
- struct background_thread *thread = malloc(sizeof(*thread));
- if (!thread)
- return NULL;
-
- vlc_cond_init(&thread->probe_cancel_wait);
- thread->probe = false;
- thread->cancel = false;
- thread->task = NULL;
- thread->owner = owner;
- return thread;
-}
-
-static void background_thread_Destroy(struct background_thread *thread)
-{
- free(thread);
-}
-
-static struct background_worker *background_worker_Create(void *owner,
- struct background_worker_config *conf)
-{
- struct background_worker* worker = malloc(sizeof(*worker));
- if (unlikely(!worker))
- return NULL;
-
- worker->conf = *conf;
- worker->owner = owner;
-
- vlc_mutex_init(&worker->lock);
- worker->uncompleted = 0;
- worker->nthreads = 0;
- vlc_list_init(&worker->threads);
- vlc_list_init(&worker->queue);
- vlc_cond_init(&worker->queue_wait);
- vlc_cond_init(&worker->nothreads_wait);
- worker->closing = false;
- return worker;
-}
-
-static void background_worker_Destroy(struct background_worker *worker)
-{
- free(worker);
-}
-
-static void TerminateTask(struct background_thread *thread, struct task *task)
-{
- struct background_worker *worker = thread->owner;
-
- vlc_mutex_lock(&worker->lock);
- thread->task = NULL;
- worker->uncompleted--;
- assert(worker->uncompleted >= 0);
- vlc_mutex_unlock(&worker->lock);
-
- task_Destroy(worker, task);
-}
-
-static void RemoveThread(struct background_thread *thread)
-{
- struct background_worker *worker = thread->owner;
-
- vlc_mutex_lock(&worker->lock);
-
- vlc_list_remove(&thread->node);
- worker->nthreads--;
- assert(worker->nthreads >= 0);
- if (!worker->nthreads)
- vlc_cond_signal(&worker->nothreads_wait);
-
- vlc_mutex_unlock(&worker->lock);
-
- background_thread_Destroy(thread);
-}
-
-static void* Thread( void* data )
-{
- struct background_thread *thread = data;
- struct background_worker *worker = thread->owner;
-
- for (;;)
- {
- vlc_mutex_lock(&worker->lock);
- struct task *task = QueueTake(worker, 5000);
- if (!task)
- {
- vlc_mutex_unlock(&worker->lock);
- /* terminate this thread */
- break;
- }
-
- thread->task = task;
- thread->cancel = false;
- thread->probe = false;
- vlc_tick_t deadline;
- if (task->timeout > 0)
- deadline = vlc_tick_now() + task->timeout;
- else
- deadline = INT64_MAX; /* no deadline */
- vlc_mutex_unlock(&worker->lock);
-
- void *handle;
- if (worker->conf.pf_start(worker->owner, task->entity, &handle))
- {
- TerminateTask(thread, task);
- continue;
- }
-
- for (;;)
- {
- vlc_mutex_lock(&worker->lock);
- bool timeout = false;
- while (!timeout && !thread->probe && !thread->cancel)
- /* any non-zero return value means timeout */
- timeout = vlc_cond_timedwait(&thread->probe_cancel_wait,
- &worker->lock, deadline) != 0;
-
- bool cancel = thread->cancel;
- thread->cancel = false;
- thread->probe = false;
- vlc_mutex_unlock(&worker->lock);
-
- if (timeout || cancel
- || worker->conf.pf_probe(worker->owner, handle))
- {
- worker->conf.pf_stop(worker->owner, handle);
- TerminateTask(thread, task);
- break;
- }
- }
- }
-
- RemoveThread(thread);
-
- return NULL;
-}
-
-static bool SpawnThread(struct background_worker *worker)
-{
- vlc_mutex_assert(&worker->lock);
-
- struct background_thread *thread = background_thread_Create(worker);
- if (!thread)
- return false;
-
- if (vlc_clone_detach(NULL, Thread, thread, VLC_THREAD_PRIORITY_LOW))
- {
- free(thread);
- return false;
- }
- worker->nthreads++;
- vlc_list_append(&thread->node, &worker->threads);
-
- return true;
-}
-
-struct background_worker* background_worker_New( void* owner,
- struct background_worker_config* conf )
-{
- return background_worker_Create(owner, conf);
-}
-
-int background_worker_Push( struct background_worker* worker, void* entity,
- void* id, int timeout )
-{
- struct task *task = task_Create(worker, id, entity, timeout);
- if (unlikely(!task))
- return VLC_ENOMEM;
-
- vlc_mutex_lock(&worker->lock);
- QueuePush(worker, task);
- if (++worker->uncompleted > worker->nthreads
- && worker->nthreads < worker->conf.max_threads)
- SpawnThread(worker);
- vlc_mutex_unlock(&worker->lock);
-
- return VLC_SUCCESS;
-}
-
-static void BackgroundWorkerCancelLocked(struct background_worker *worker,
- void *id)
-{
- vlc_mutex_assert(&worker->lock);
-
- QueueRemoveAll(worker, id);
-
- struct background_thread *thread;
- vlc_list_foreach(thread, &worker->threads, node)
- {
- if (!id || (thread->task && thread->task->id == id && !thread->cancel))
- {
- thread->cancel = true;
- vlc_cond_signal(&thread->probe_cancel_wait);
- }
- }
-}
-
-void background_worker_Cancel( struct background_worker* worker, void* id )
-{
- vlc_mutex_lock(&worker->lock);
- BackgroundWorkerCancelLocked(worker, id);
- vlc_mutex_unlock(&worker->lock);
-}
-
-void background_worker_RequestProbe( struct background_worker* worker )
-{
- vlc_mutex_lock(&worker->lock);
-
- struct background_thread *thread;
- vlc_list_foreach(thread, &worker->threads, node)
- {
- thread->probe = true;
- vlc_cond_signal(&thread->probe_cancel_wait);
- }
-
- vlc_mutex_unlock(&worker->lock);
-}
-
-void background_worker_Delete( struct background_worker* worker )
-{
- vlc_mutex_lock(&worker->lock);
-
- worker->closing = true;
- BackgroundWorkerCancelLocked(worker, NULL);
- /* closing is now true, this will wake up any QueueTake() */
- vlc_cond_broadcast(&worker->queue_wait);
-
- while (worker->nthreads)
- vlc_cond_wait(&worker->nothreads_wait, &worker->lock);
-
- vlc_mutex_unlock(&worker->lock);
-
- /* no threads use the worker anymore, we can destroy it */
- background_worker_Destroy(worker);
-}
diff --git a/src/misc/background_worker.h b/src/misc/background_worker.h
deleted file mode 100644
index abe65159ff..0000000000
--- a/src/misc/background_worker.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 2017 VLC authors and VideoLAN
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-#ifndef BACKGROUND_WORKER_H__
-#define BACKGROUND_WORKER_H__
-
-struct background_worker_config {
- /**
- * Default timeout for completing a task
- *
- * If less-than 0 a task can run indefinitely without being killed, whereas
- * a positive value denotes the maximum number of milliseconds a task can
- * run before \ref pf_stop is called to kill it.
- **/
- vlc_tick_t default_timeout;
-
- /**
- * Maximum number of threads used to execute tasks.
- */
- int max_threads;
-
- /**
- * Release an entity
- *
- * This callback will be called in order to decrement the ref-count of a
- * entity within the background-worker. It will happen either when \ref
- * pf_stop has finished executing, or if the entity is removed from the
- * queue (through \ref background_worker_Cancel)
- *
- * \warning As each task might be executed in parallel by different threads,
- * this callback must be thread-safe.
- *
- * \param entity the entity to release
- **/
- void( *pf_release )( void* entity );
-
- /**
- * Hold a queued item
- *
- * This callback will be called in order to increment the ref-count of an
- * entity. It will happen when the entity is pushed into the queue of
- * pending tasks as part of \ref background_worker_Push.
- *
- * \warning As each task might be executed in parallel by different threads,
- * this callback must be thread-safe.
- *
- * \param entity the entity to hold
- **/
- void( *pf_hold )( void* entity );
-
- /**
- * Start a new task
- *
- * This callback is called in order to construct a new background task. In
- * order for the background-worker to be able to continue processing
- * incoming requests, \ref pf_start is meant to start a task (such as a
- * thread), and then store the associated handle in `*out`.
- *
- * The value of `*out` will then be the value of the argument named `handle`
- * in terms of \ref pf_probe and \ref pf_stop.
- *
- * \warning As each task might be executed in parallel by different threads,
- * this callback must be thread-safe.
- *
- * \param owner the owner of the background-worker
- * \param entity the entity for which a task is to be created
- * \param out [out] `*out` shall, on success, refer to the handle associated
- * with the running task.
- * \return VLC_SUCCESS if a task was created, an error-code on failure.
- **/
- int( *pf_start )( void* owner, void* entity, void** out );
-
- /**
- * Probe a running task
- *
- * This callback is called in order to see whether or not a running task has
- * finished or not. It can be called anytime between a successful call to
- * \ref pf_start, and the corresponding call to \ref pf_stop.
- *
- * \warning As each task might be executed in parallel by different threads,
- * this callback must be thread-safe.
- *
- * \param owner the owner of the background-worker
- * \param handle the handle associated with the running task
- * \return 0 if the task is still running, any other value if finished.
- **/
- int( *pf_probe )( void* owner, void* handle );
-
- /**
- * Stop a running task
- *
- * This callback is called in order to stop a running task. If \ref pf_start
- * has created a non-detached thread, \ref pf_stop is where you would
- * interrupt and then join it.
- *
- * \warning This function is called either after \ref pf_probe has stated
- * that the task has finished, or if the timeout (if any) for the
- * task has been reached.
- *
- * \warning As each task might be executed in parallel by different threads,
- * this callback must be thread-safe.
- *
- * \param owner the owner of the background-worker
- * \parma handle the handle associated with the task to be stopped
- **/
- void( *pf_stop )( void* owner, void* handle );
-};
-
-/**
- * Create a background-worker
- *
- * This function creates a new background-worker using the passed configuration.
- *
- * \warning all members of `config` shall have been set by the caller.
- * \warning the returned resource must be destroyed using \ref
- * background_worker_Delete on success.
- *
- * \param owner the owner of the background-worker
- * \param config the background-worker's configuration
- * \return a pointer-to the created background-worker on success,
- * `NULL` on failure.
- **/
-struct background_worker* background_worker_New( void* owner,
- struct background_worker_config* config );
-
-/**
- * Request the background-worker to probe the current task
- *
- * This function is used to signal the background-worker that it should do
- * another probe to see whether the current task is still alive.
- *
- * \warning Note that the function will not wait for the probing to finish, it
- * will simply ask the background worker to recheck it as soon as
- * possible.
- *
- * \param worker the background-worker
- **/
-void background_worker_RequestProbe( struct background_worker* worker );
-
-/**
- * Push an entity into the background-worker
- *
- * This function is used to push an entity into the queue of pending work. The
- * entities will be processed in the order in which they are received (in terms
- * of the order of invocations in a single-threaded environment).
- *
- * \param worker the background-worker
- * \param entity the entity which is to be queued
- * \param id a value suitable for identifying the entity, or `NULL`
- * \param timeout the timeout of the entity in milliseconds, `0` denotes no
- * timeout, a negative value will use the default timeout
- * associated with the background-worker.
- * \return VLC_SUCCESS if the entity was successfully queued, an error-code on
- * failure.
- **/
-int background_worker_Push( struct background_worker* worker, void* entity,
- void* id, int timeout );
-
-/**
- * Remove entities from the background-worker
- *
- * This function is used to remove processing of a certain entity given its
- * associated id, or to remove all queued (including currently running)
- * entities.
- *
- * \warning if the `id` passed refers to an entity that is currently being
- * processed, the call will block until the task has been terminated.
- *
- * \param worker the background-worker
- * \param id NULL if every entity shall be removed, and the currently running
- * task (if any) shall be cancelled.
- **/
-void background_worker_Cancel( struct background_worker* worker, void* id );
-
-/**
- * Delete a background-worker
- *
- * This function will destroy a background-worker created through \ref
- * background_worker_New. It will effectively stop the currently running task,
- * if any, and empty the queue of pending entities.
- *
- * \warning If there is a currently running task, the function will block until
- * it has been stopped.
- *
- * \param worker the background-worker
- **/
-void background_worker_Delete( struct background_worker* worker );
-#endif
More information about the vlc-commits
mailing list