@@ -32,6 +32,7 @@ libcamera_internal_headers = files([
'media_device.h',
'media_object.h',
'pipeline_handler.h',
+ 'pool.h',
'process.h',
'pub_key.h',
'request.h',
new file mode 100644
@@ -0,0 +1,119 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Google Inc.
+ *
+ * pool.h - Template class for generic pool
+ *
+ * Common usage:
+ *
+ * Unique tokens:
+ * Pool<uint32_t, BasicContainer<uint32_t>>;
+ *
+ * Auto closed Fds:
+ * Pool<int, UniqueFD>;
+ *
+ * Auto destructed FrameBuffers:
+ * Pool<FrameBuffer *, std::unique_ptr<FrameBuffer>>;
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <deque>
+#include <set>
+#include <string>
+#include <vector>
+
+#include <libcamera/base/log.h>
+#include <libcamera/base/mutex.h>
+
+namespace libcamera {
+
+LOG_DEFINE_CATEGORY(Pool)
+
+template<typename T, typename UniquePtr>
+class Pool : public Loggable
+{
+public:
+ Pool() = default;
+ ~Pool() = default;
+
+ /* Loggable */
+ std::string logPrefix() const override { return "Pool"; }
+
+ void setData(std::vector<UniquePtr> &pool)
+ {
+ pool_.swap(pool);
+ free_.clear();
+ inUse_.clear();
+
+ for (auto &fd : pool_) {
+ free_.emplace_back(fd.get());
+ }
+ }
+
+ void release()
+ {
+ pool_.clear();
+ free_.clear();
+ inUse_.clear();
+ }
+
+ std::vector<UniquePtr> &content()
+ {
+ return pool_;
+ }
+
+ size_t size()
+ {
+ return pool_.size();
+ }
+
+ T get()
+ {
+ std::scoped_lock lock(mutex_);
+
+ if (free_.empty())
+ LOG(Pool, Fatal) << "not enough data in the Pool";
+
+ T fd = free_.front();
+ free_.pop_front();
+ inUse_.emplace(fd);
+
+ return fd;
+ }
+
+ void put(T data)
+ {
+ std::scoped_lock lock(mutex_);
+
+ auto iter = std::find(inUse_.begin(), inUse_.end(), data);
+ if (iter == inUse_.end())
+ LOG(Pool, Fatal) << "return data not belonging to the pool";
+
+ inUse_.erase(iter);
+ free_.emplace_front(data);
+ }
+
+private:
+ LIBCAMERA_DISABLE_COPY_AND_MOVE(Pool)
+
+ std::vector<UniquePtr> pool_;
+ std::deque<T> free_;
+ std::set<T> inUse_;
+ Mutex mutex_;
+};
+
+template<typename T>
+class BasicContainer
+{
+public:
+ BasicContainer(T &value)
+ : value_(value) {}
+ T get() { return value_; }
+
+private:
+ T value_;
+};
+
+} /* namespace libcamera */
@@ -43,6 +43,7 @@ libcamera_internal_sources = files([
'media_device.cpp',
'media_object.cpp',
'pipeline_handler.cpp',
+ 'pool.cpp',
'process.cpp',
'pub_key.cpp',
'shared_mem_object.cpp',
new file mode 100644
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Google Inc.
+ *
+ * pool.cpp - Template class for generic pool
+ */
+
+/**
+ * \class libcamera::Pool
+ * \brief Pool that owns a list of objects
+ *
+ * A Pool that owns a list of objects, and allows users to request objects and
+ * recycle them. It's mostly used as a buffer pool, holding a list of buffers
+ * as std::unique_ptr.
+ */
+
+/**
+ * \fn Pool::setData(std::vector<UniquePtr> &pool)
+ * \brief Set and claim ownership of objects. Swap the previously owned objects
+ * not empty.
+ * \param[inout] pool The objects to be set and the swapped out ones
+ */
+
+/**
+ * \fn Pool::release()
+ * \brief Release the ownership of objects and reset states
+ */
+
+/**
+ * \fn Pool::content()
+ * \return The reference of objects
+ */
+
+/**
+ * \fn Pool::size()
+ * \brief The size of objects
+ */
+
+/**
+ * \fn Pool::get()
+ * \brief Get one object. Fatal if there's none available
+ *
+ * \return An available object
+ */
+
+/**
+ * \fn Pool::put(T data)
+ * \brief Recycle one object that was retrieved by get()
+ * \param[in] data The object to be recycled
+ */
+
+/**
+ * \class libcamera::BasicContainer
+ * \brief A container for basic types
+ *
+ * When using Pool with a basic type (e.g. `int`), it'd be easier to get an
+ * object by value instead of by pointer. BasicContainer makes it possible as a
+ * helper class.
+ */
+
+/**
+ * \fn BasicContainer::BasicContainer(T &value)
+ * \brief Create a BasicContainer with a value
+ * \param[in] value The value to be contained
+ */
+
+/**
+ * \fn BasicContainer::get()
+ * \return Return the object by value
+ */