From 66e7c5b774e288faa3a9b413861d6a77723db3ad Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 28 Oct 2019 04:14:52 +0200 Subject: libcamera: Add Semaphore class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a general-purpose counting semaphore class. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- src/libcamera/include/meson.build | 1 + src/libcamera/include/semaphore.h | 34 +++++++++++++ src/libcamera/meson.build | 1 + src/libcamera/semaphore.cpp | 103 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 139 insertions(+) create mode 100644 src/libcamera/include/semaphore.h create mode 100644 src/libcamera/semaphore.cpp diff --git a/src/libcamera/include/meson.build b/src/libcamera/include/meson.build index 2c74d29b..64c2155f 100644 --- a/src/libcamera/include/meson.build +++ b/src/libcamera/include/meson.build @@ -17,6 +17,7 @@ libcamera_headers = files([ 'message.h', 'pipeline_handler.h', 'process.h', + 'semaphore.h', 'thread.h', 'utils.h', 'v4l2_controls.h', diff --git a/src/libcamera/include/semaphore.h b/src/libcamera/include/semaphore.h new file mode 100644 index 00000000..c6b28653 --- /dev/null +++ b/src/libcamera/include/semaphore.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * semaphore.h - General-purpose counting semaphore + */ +#ifndef __LIBCAMERA_SEMAPHORE_H__ +#define __LIBCAMERA_SEMAPHORE_H__ + +#include + +#include "thread.h" + +namespace libcamera { + +class Semaphore +{ +public: + Semaphore(unsigned int n = 0); + + unsigned int available(); + void acquire(unsigned int n = 1); + bool tryAcquire(unsigned int n = 1); + void release(unsigned int n = 1); + +private: + Mutex mutex_; + std::condition_variable cv_; + unsigned int available_; +}; + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_SEMAPHORE_H__ */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index f201f408..afbca769 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -28,6 +28,7 @@ libcamera_sources = files([ 'pixelformats.cpp', 'process.cpp', 'request.cpp', + 'semaphore.cpp', 'signal.cpp', 'stream.cpp', 'thread.cpp', diff --git a/src/libcamera/semaphore.cpp b/src/libcamera/semaphore.cpp new file mode 100644 index 00000000..ce1eae49 --- /dev/null +++ b/src/libcamera/semaphore.cpp @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * semaphore.cpp - General-purpose counting semaphore + */ + +#include "semaphore.h" +#include "thread.h" + +/** + * \file semaphore.h + * \brief General-purpose counting semaphore + */ + +namespace libcamera { + +/** + * \class Semaphore + * \brief General-purpose counting semaphore + * + * A semaphore is a locking primitive that protects resources. It is created + * with an initial number of resources (which may be 0), and offers two + * primitives to acquire and release resources. The acquire() method tries to + * acquire a number of resources, and blocks if not enough resources are + * available until they get released. The release() method releases a number of + * resources, waking up any consumer blocked on an acquire() call. + */ + +/** + * \brief Construct a semaphore with \a n resources + * \param[in] n The resource count + */ +Semaphore::Semaphore(unsigned int n) + : available_(n) +{ +} + +/** + * \brief Retrieve the number of available resources + * \return The number of available resources + */ +unsigned int Semaphore::available() +{ + MutexLocker locker(mutex_); + return available_; +} + +/** + * \brief Acquire \a n resources + * \param[in] n The resource count + * + * This method attempts to acquire \a n resources. If \a n is higher than the + * number of available resources, the call will block until enough resources + * become available. + */ +void Semaphore::acquire(unsigned int n) +{ + MutexLocker locker(mutex_); + cv_.wait(locker, [&] { return available_ >= n; }); + available_ -= n; +} + +/** + * \brief Try to acquire \a n resources without blocking + * \param[in] n The resource count + * + * This method attempts to acquire \a n resources. If \a n is higher than the + * number of available resources, it returns false immediately without + * acquiring any resource. Otherwise it acquires the resources and returns + * true. + * + * \return True if the resources have been acquired, false otherwise + */ +bool Semaphore::tryAcquire(unsigned int n) +{ + MutexLocker locker(mutex_); + if (available_ < n) + return false; + + available_ -= n; + return true; +} + +/** + * \brief Release \a n resources + * \param[in] n The resource count + * + * This method releases \a n resources, increasing the available resource count + * by \a n. If the number of available resources becomes large enough for any + * consumer blocked on an acquire() call, those consumers get woken up. + */ +void Semaphore::release(unsigned int n) +{ + { + MutexLocker locker(mutex_); + available_ += n; + } + + cv_.notify_all(); +} + +} /* namespace libcamera */ -- cgit v1.2.1