new file mode 100644
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Google Inc.
+ *
+ * mailbox.h - Template class for generic mailbox
+ */
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <vector>
+
+#include <libcamera/base/log.h>
+
+namespace libcamera {
+
+template<class T>
+class MailBox
+{
+public:
+ using Recycler = std::function<void(T &)>;
+
+ MailBox()
+ : valid_(false) {}
+ ~MailBox()
+ {
+ if (valid_ && recycler_)
+ recycler_(item_);
+ }
+
+ void put(const T &item, Recycler recycler)
+ {
+ ASSERT(!valid_);
+
+ valid_ = true;
+ recycler_ = recycler;
+ item_ = item;
+ }
+
+ const T &get()
+ {
+ ASSERT(valid_);
+ return item_;
+ }
+
+ bool valid() { return valid_; }
+
+private:
+ T item_;
+ bool valid_;
+ std::function<void(T &)> recycler_;
+};
+
+template<class T>
+using SharedMailBox = std::shared_ptr<MailBox<T>>;
+
+template<class T>
+SharedMailBox<T> makeMailBox()
+{
+ return std::make_shared<MailBox<T>>();
+}
+
+template<class T>
+std::vector<SharedMailBox<T>> makeMailBoxVector(const unsigned int count)
+{
+ std::vector<SharedMailBox<T>> mailBoxes;
+ mailBoxes.resize(count);
+ for (unsigned int i = 0; i < count; i++)
+ mailBoxes[i] = makeMailBox<T>();
+
+ return mailBoxes;
+}
+
+} /* namespace libcamera */
@@ -27,6 +27,7 @@ libcamera_internal_headers = files([
'ipa_proxy.h',
'ipc_pipe.h',
'ipc_unixsocket.h',
+ 'mailbox.h',
'mapped_framebuffer.h',
'media_device.h',
'media_object.h',
new file mode 100644
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Google Inc.
+ *
+ * mailbox.cpp - Template class for generic mailbox
+ */
+
+/**
+ * \class libcamera::MailBox
+ * \brief MailBox of data
+ *
+ * A MailBox contains a block of data that has a single producer, and one or
+ * multiple consumers. It's often used as a shared_ptr (SharedMailBox) and
+ * being held by different tasks in pipelines.
+ */
+
+/**
+ * \typedef MailBox::Recycler
+ * \brief A function that recycles the data when the mailbox is destructed
+ */
+
+/**
+ * \fn MailBox::put(const T &item, MailBox<T>::Recycler recycler)
+ * \brief Set the data as the producer. Should be called only once
+ * \param[in] item The data to be stored
+ * \param[in] recycler The function that recycles \a data when destructing the
+ * mailbox. Mostly used for recycling buffers.
+ */
+
+/**
+ * \fn MailBox::get()
+ * \brief Get the data as a consumer. put() function should be called ahead
+ *
+ * \return The stored data
+ */
+
+/**
+ * \fn MailBox::valid()
+ * \return True if put() function has been called
+ */
+
+/**
+ * \typedef libcamera::SharedMailBox
+ * \brief A mailbox as a shared_ptr
+ */
+
+/**
+ * \fn libcamera::makeMailBox()
+ * \brief A helper function to create a SharedMailBox
+ *
+ * \return A mailbox as a SharedMailBox
+ */
+
+/**
+ * \fn libcamera::makeMailBoxVector(const unsigned int count)
+ * \brief A helper function to create a list of mailboxes
+ * \param[in] count The number of mailboxes requested
+ *
+ * \return Mailboxes as a vector
+ */
@@ -38,6 +38,7 @@ libcamera_internal_sources = files([
'ipc_pipe.cpp',
'ipc_pipe_unixsocket.cpp',
'ipc_unixsocket.cpp',
+ 'mailbox.cpp',
'mapped_framebuffer.cpp',
'media_device.cpp',
'media_object.cpp',