@@ -11,11 +11,14 @@
namespace libcamera {
+class ScopedFD;
+
class FileDescriptor final
{
public:
explicit FileDescriptor(const int &fd = -1);
explicit FileDescriptor(int &&fd);
+ explicit FileDescriptor(ScopedFD &&fd);
FileDescriptor(const FileDescriptor &other);
FileDescriptor(FileDescriptor &&other);
~FileDescriptor();
@@ -15,6 +15,7 @@ libcamera_public_headers = files([
'object.h',
'pixel_format.h',
'request.h',
+ 'scoped_fd.h',
'signal.h',
'span.h',
'stream.h',
new file mode 100644
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2021, Google Inc.
+ *
+ * scoped_fd.h - File descriptor wrapper that owns a file descriptor.
+ */
+#ifndef __LIBCAMERA_SCOPED_FD_H__
+#define __LIBCAMERA_SCOPED_FD_H__
+
+#include <libcamera/class.h>
+#include <libcamera/compiler.h>
+
+namespace libcamera {
+
+class ScopedFD final
+{
+public:
+ explicit ScopedFD(const int fd = -1);
+ ~ScopedFD();
+ ScopedFD(ScopedFD &&other);
+ ScopedFD &operator=(ScopedFD &&other);
+
+ bool isValid() const { return fd_ == -1; }
+ int get() const { return fd_; }
+ void reset(int fd = -1);
+ __nodiscard int release();
+
+private:
+ int fd_;
+
+ LIBCAMERA_DISABLE_COPY(ScopedFD)
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_SCOPED_FD_H__ */
@@ -11,6 +11,8 @@
#include <unistd.h>
#include <utility>
+#include <libcamera/scoped_fd.h>
+
#include "libcamera/internal/log.h"
/**
@@ -108,6 +110,24 @@ FileDescriptor::FileDescriptor(int &&fd)
fd = -1;
}
+/**
+ * \brief Create a FileDescriptor taking ownership of a given ScopedFD \a fd
+ * \param[in] fd ScopedFD
+ *
+ * Construct a FileDescriptor from ScopedFD by taking ownership of the \a fd.
+ * The original \a fd becomes invalid. In particular, the caller shall not close
+ * the original \a fd manually. The duplicated file descriptor will be closed
+ * automatically when all FileDescriptor instances that reference it are
+ * destroyed.
+ *
+ * If the \a fd is negative, the FileDescriptor is constructed as invalid and
+ * the fd() method will return -1.
+ */
+FileDescriptor::FileDescriptor(ScopedFD &&fd)
+ : FileDescriptor(fd.release())
+{
+}
+
/**
* \brief Copy constructor, create a FileDescriptor from a copy of \a other
* \param[in] other The other FileDescriptor
@@ -44,6 +44,7 @@ libcamera_sources = files([
'process.cpp',
'pub_key.cpp',
'request.cpp',
+ 'scoped_fd.cpp',
'semaphore.cpp',
'signal.cpp',
'stream.cpp',
new file mode 100644
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2021, Google Inc.
+ *
+ * scoped_fd.cpp - File descriptor wrapper that owns a file descriptor.
+ */
+
+#include <libcamera/scoped_fd.h>
+
+#include <unistd.h>
+
+#include "libcamera/internal/log.h"
+
+/**
+ * \file scoped_fd.h
+ * \brief File descriptor wrapper that owns a file descriptor
+ */
+
+namespace libcamera {
+
+LOG_DEFINE_CATEGORY(ScopedFD)
+
+/**
+ * \class ScopedFD
+ * \brief unique_ptr like wrapper for a file descriptor
+ *
+ * The ScopedFD provides RAII-style lifetime management of a file descriptor.
+ * It doesn't allow the shared ownership unlike FileDescriptor. It is
+ * constructed from a numerical file descriptor and takes over the ownership of
+ * the file descriptor. When the ScopedFD is destroyed, the managed file
+ * descriptor is closed.
+ */
+
+/**
+ * \brief Create a ScopedFD taking over a given \a fd
+ * \param[in] fd a numerical file descriptor
+ *
+ * Construct a ScopedFD from a numerical file descriptor and take ownership of
+ * the file descriptor. The given file descriptor is automatically closed when
+ * the ScopedFD is destructed.
+ */
+ScopedFD::ScopedFD(const int fd)
+ : fd_(fd >= 0 ? fd : -1)
+{
+}
+
+/**
+ * \brief Destroy the ScopedFD instance
+ *
+ * The owned file descriptor is automatically closed if it is valid.
+ */
+ScopedFD::~ScopedFD()
+{
+ reset();
+}
+
+/**
+ * \brief Move constructor, create a ScopedFD by taking over \a other
+ * \param[in] other The other ScopedFD
+ *
+ * Create a ScopedFD that takes the ownership of the file descriptor owned by \a
+ * other. Upon return, the \a other ScopedFD is invalid.
+ */
+ScopedFD::ScopedFD(ScopedFD &&other)
+ : fd_(other.release())
+{
+}
+
+/**
+ * \brief Move assignment operator, replace a ScopedFD by taking over \a other
+ * \param[in] other The other ScopedFD
+ *
+ * If this ScopedFD has a valid file descriptor, the file descriptor is closed
+ * first. The file descriptor is then replaced by the one of \a other. Upon
+ * return, \a other is invalid.
+ *
+ * \return A reference to this ScopedFD
+ */
+ScopedFD &ScopedFD::operator=(ScopedFD &&other)
+{
+ reset(other.release());
+
+ return *this;
+}
+
+/**
+ * \fn ScopedFD::isValid()
+ * \brief Check if the ScopedFD has a valid file descriptor
+ * \return True if the ScopedFD has a valid file descriptor, false otherwise
+ */
+
+/**
+ * \fn ScopedFD::get()
+ * \brief Retrieve the numerical file descriptor
+ * \return The numerical file descriptor
+ */
+
+/**
+ * \fn ScopedFD::reset()
+ * \brief Swap the owned file descriptor with \a fd. The originally owned file
+ * descriptor is closed.
+ * \param[in] fd a numerical file descriptor
+ */
+void ScopedFD::reset(int fd)
+{
+ ASSERT(!isValid() || fd != fd_);
+ if (isValid())
+ close(fd_);
+ fd_ = fd;
+}
+
+/**
+ * \fn ScopedFD::release()
+ * \brief Release ownership of the file descriptor without closing it
+ *
+ * This function releases and returns the owned file descriptor without closing
+ * it. The caller owns the returned value and must take care of handling its
+ * life time to avoid file descriptor leakages. Upon return the ScopedFD is
+ * invalid.
+ *
+ * \return The numerical file descriptor
+ */
+int ScopedFD::release()
+{
+ int fd = fd_;
+ fd_ = -1;
+ return fd;
+}
+} /* namespace libcamera */
This introduces ScopedFD. It acts like unique_ptr to a file descriptor. Signed-off-by: Hirokazu Honda <hiroh@chromium.org> --- include/libcamera/file_descriptor.h | 3 + include/libcamera/meson.build | 1 + include/libcamera/scoped_fd.h | 36 ++++++++ src/libcamera/file_descriptor.cpp | 20 +++++ src/libcamera/meson.build | 1 + src/libcamera/scoped_fd.cpp | 129 ++++++++++++++++++++++++++++ 6 files changed, 190 insertions(+) create mode 100644 include/libcamera/scoped_fd.h create mode 100644 src/libcamera/scoped_fd.cpp