Message ID | 20241001081824.960009-2-chenghaoyang@google.com |
---|---|
State | New |
Headers | show |
Series |
|
Related | show |
Hi 2024. október 1., kedd 10:10 keltezéssel, Harvey Yang <chenghaoyang@chromium.org> írta: > From: Han-Lin Chen <hanlinchen@chromium.org> > > MailBox is designed to be used to shares data, usually a frame buffer, among ^ share > tasks. A Mailbox can store a data which the producer task should set into, ^ MailBox > and multiple consumer tasks could read the data from it. The data could > be set only once, i.e., there should be only one producer. All tasks shares ^ share > the Mailbox with share_ptr and the data it contains should be recycled when ^ ^ MailBox shared_ptr > all tasks are finished. > > Signed-off-by: Hanlin Chen <hanlinchen@google.com> > Co-developed-by: Harvey Yang <chenghaoyang@chromium.org> > --- > include/libcamera/internal/mailbox.h | 50 +++++++++++++ > include/libcamera/internal/meson.build | 1 + > src/libcamera/mailbox.cpp | 97 ++++++++++++++++++++++++++ > src/libcamera/meson.build | 1 + > 4 files changed, 149 insertions(+) > create mode 100644 include/libcamera/internal/mailbox.h > create mode 100644 src/libcamera/mailbox.cpp > > diff --git a/include/libcamera/internal/mailbox.h b/include/libcamera/internal/mailbox.h > new file mode 100644 > index 00000000..fb27f5bb > --- /dev/null > +++ b/include/libcamera/internal/mailbox.h > @@ -0,0 +1,50 @@ > +/* 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> > + > +namespace libcamera { > + > +template<class T> > +class MailBox > +{ > +public: > + using Recycler = std::function<void(T &)>; > + > + MailBox() > + : valid_(false) {} > + ~MailBox(); > + > + void put(const T &item, Recycler recycler); > + > + const T &get(); > + > + 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); You have to put the definitions of templates in the header file, otherwise it won't work. Also, this whole concept looks to me to be very similar to a `const std::shared_ptr<T>` with a custom deleter (with the difference that you can only obtain a `const` reference here unlike with an `std::shared_ptr`). So I am wondering if utilizing `std::shared_ptr` with a custom deleter has been explored already. I am also wondering if it wouldn't make more sense to remove `MailBox::put()` and just have the two constructors taking `const T&` and `T&&`, and initializing `item_`. This would do away with the need for the `valid_` member. Is there a planned use case where that is not sufficient? Regards, Barnabás Pőcze > + > +} /* namespace libcamera */ > [...]
diff --git a/include/libcamera/internal/mailbox.h b/include/libcamera/internal/mailbox.h new file mode 100644 index 00000000..fb27f5bb --- /dev/null +++ b/include/libcamera/internal/mailbox.h @@ -0,0 +1,50 @@ +/* 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> + +namespace libcamera { + +template<class T> +class MailBox +{ +public: + using Recycler = std::function<void(T &)>; + + MailBox() + : valid_(false) {} + ~MailBox(); + + void put(const T &item, Recycler recycler); + + const T &get(); + + 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); + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index 1c5eef9c..4c1228b9 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -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', diff --git a/src/libcamera/mailbox.cpp b/src/libcamera/mailbox.cpp new file mode 100644 index 00000000..4d129224 --- /dev/null +++ b/src/libcamera/mailbox.cpp @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Google Inc. + * + * mailbox.cpp - Template class for generic mailbox + */ + +#include "libcamera/internal/mailbox.h" + +#include <libcamera/base/log.h> + +namespace libcamera { + +/** + * \class 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 + */ + +template<class T> +MailBox<T>::~MailBox() +{ + if (valid_ && recycler_) + recycler_(item_); +} + +/** + * \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. + */ +template<class T> +void MailBox<T>::put(const T &item, MailBox<T>::Recycler recycler) +{ + ASSERT(!valid_); + + valid_ = true; + recycler_ = recycler; + item_ = item; +} + +/** + * \brief Get the data as a consumer. put() function should be called ahead + * + * \return The stored data + */ +template<class T> +const T &MailBox<T>::get() +{ + ASSERT(valid_); + return item_; +} + +/** + * \fn MailBox::valid() + * \return True if put() function has been called + */ + +/** + * \typedef SharedMailBox + * \brief A mailbox as a shared_ptr + */ + +/** + * \fn makeMailBox() + * \brief A helper function to create a SharedMailBox + * + * \return A mailbox as a SharedMailBox + */ + +/** + * \brief A helper function to create a list of mailboxes + * \param[in] count The number of mailboxes requested + * + * \return Mailboxes as a vector + */ +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 */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index aa9ab029..6c3ef537 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -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',