From patchwork Mon Oct 28 10:49:05 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2274 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D4FCC6017E for ; Mon, 28 Oct 2019 11:49:25 +0100 (CET) Received: from pendragon.ideasonboard.com (unknown [91.217.168.176]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7E0CE9C2 for ; Mon, 28 Oct 2019 11:49:25 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1572259765; bh=v/OpZsArzT+Zf/lqelVeH/VCkVhny0DLIylZF2B19zE=; h=From:To:Subject:Date:In-Reply-To:References:From; b=EARnHxndFQDPEtjrB9NFfZd+EGKZrcF9rgbKaOLqbhLxSOiYT1BB5DbqBskn2BJEn VFIPFIL8kQxTVQAs3aNldjeP3adb/fTzj4hANbMwxF6MywWdUKENAhC53rDY38Y6Je 0lnvL7WrpKqvk5go8jHF8VGa9CAV6iNaz4xOmdSg= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 28 Oct 2019 12:49:05 +0200 Message-Id: <20191028104913.14985-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191028104913.14985-1-laurent.pinchart@ideasonboard.com> References: <20191028104913.14985-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 1/9] libcamera: Add Semaphore class X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 28 Oct 2019 10:49:26 -0000 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 2c74d29bd925..64c2155f90cf 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 000000000000..c6b286536eb3 --- /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 d329820b9582..dab5dbff77b7 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -27,6 +27,7 @@ libcamera_sources = files([ 'pipeline_handler.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 000000000000..ce1eae4914ed --- /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 */