[libcamera-devel] [PATCH] [WIP] libcamera: FileDescriptor: Make FileDescriptor own a fd
Hirokazu Honda
hiroh at chromium.org
Wed Apr 14 11:17:03 CEST 2021
Multiple FileDescriptors can share the same file descriptor. It
leads that the ownership of a fd managed by the class is unclear.
This makes FileDescriptor own a fd, similar to std::unique_ptr.
Signed-off-by: Hirokazu Honda <hiroh at chromium.org>
---
include/libcamera/file_descriptor.h | 26 ++-----
src/libcamera/file_descriptor.cpp | 112 ++++------------------------
2 files changed, 22 insertions(+), 116 deletions(-)
diff --git a/include/libcamera/file_descriptor.h b/include/libcamera/file_descriptor.h
index d514aac7..aaaf7f10 100644
--- a/include/libcamera/file_descriptor.h
+++ b/include/libcamera/file_descriptor.h
@@ -13,34 +13,22 @@ namespace libcamera {
class FileDescriptor final
{
+ static constexpr int kInvalidFd = -1;
public:
- explicit FileDescriptor(const int &fd = -1);
- explicit FileDescriptor(int &&fd);
- FileDescriptor(const FileDescriptor &other);
+ explicit FileDescriptor(const int fd = kInvalidFd);
FileDescriptor(FileDescriptor &&other);
~FileDescriptor();
- FileDescriptor &operator=(const FileDescriptor &other);
FileDescriptor &operator=(FileDescriptor &&other);
+ FileDescriptor &operator=(const FileDescriptor &other) = delete;
+ FileDescriptor(const FileDescriptor &other) = delete;
- bool isValid() const { return fd_ != nullptr; }
- int fd() const { return fd_ ? fd_->fd() : -1; }
+ bool isValid() const { return fd_ != kInvalidFd; }
+ int fd() const { return fd_; }
FileDescriptor dup() const;
private:
- class Descriptor
- {
- public:
- Descriptor(int fd, bool duplicate);
- ~Descriptor();
-
- int fd() const { return fd_; }
-
- private:
- int fd_;
- };
-
- std::shared_ptr<Descriptor> fd_;
+ int fd_;
};
} /* namespace libcamera */
diff --git a/src/libcamera/file_descriptor.cpp b/src/libcamera/file_descriptor.cpp
index 8b505ed3..5757aca0 100644
--- a/src/libcamera/file_descriptor.cpp
+++ b/src/libcamera/file_descriptor.cpp
@@ -7,6 +7,7 @@
#include <libcamera/file_descriptor.h>
+#include <algorithm>
#include <string.h>
#include <unistd.h>
#include <utility>
@@ -35,13 +36,7 @@ LOG_DEFINE_CATEGORY(FileDescriptor)
* When constructed from a numerical file descriptor, the FileDescriptor
* instance either duplicates or takes over the file descriptor:
*
- * - The FileDescriptor(const int &) constructor duplicates the numerical file
- * descriptor and wraps the duplicate in a Descriptor. The caller is
- * responsible for closing the original file descriptor, and the value
- * returned by fd() will be different from the value passed to the
- * constructor.
- *
- * - The FileDescriptor(int &&) constructor takes over the numerical file
+ * - The FileDescriptor(const int &) constructor takes over the numerical file
* descriptor and wraps it in a Descriptor. The caller shall not touch the
* original file descriptor once the function returns, and the value returned
* by fd() will be identical to the value passed to the constructor.
@@ -70,56 +65,9 @@ LOG_DEFINE_CATEGORY(FileDescriptor)
* If the \a fd is negative, the FileDescriptor is constructed as invalid and
* the fd() method will return -1.
*/
-FileDescriptor::FileDescriptor(const int &fd)
-{
- if (fd < 0)
- return;
-
- fd_ = std::make_shared<Descriptor>(fd, true);
- if (fd_->fd() < 0)
- fd_.reset();
-}
-/**
- * \brief Create a FileDescriptor taking ownership of a given \a fd
- * \param[in] fd File descriptor
- *
- * Construct a FileDescriptor from a numerical file descriptor by taking
- * ownership of the \a fd. The original \a fd is set to -1 and shall not be
- * touched by the caller anymore. 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(int &&fd)
-{
- if (fd < 0)
- return;
-
- fd_ = std::make_shared<Descriptor>(fd, false);
- /*
- * The Descriptor constructor can't have failed here, as it took over
- * the fd without duplicating it. Just set the original fd to -1 to
- * implement move semantics.
- */
- fd = -1;
-}
-
-/**
- * \brief Copy constructor, create a FileDescriptor from a copy of \a other
- * \param[in] other The other FileDescriptor
- *
- * Copying a FileDescriptor implicitly shares ownership of the wrapped file
- * descriptor. The original FileDescriptor is left untouched, and the caller is
- * responsible for destroying it when appropriate. The wrapped file descriptor
- * will be closed automatically when all FileDescriptor instances that
- * reference it are destroyed.
- */
-FileDescriptor::FileDescriptor(const FileDescriptor &other)
- : fd_(other.fd_)
+FileDescriptor::FileDescriptor(const int fd)
+ : fd_(fd)
{
}
@@ -134,8 +82,9 @@ FileDescriptor::FileDescriptor(const FileDescriptor &other)
* reference it are destroyed.
*/
FileDescriptor::FileDescriptor(FileDescriptor &&other)
- : fd_(std::move(other.fd_))
+ : fd_(other.fd_)
{
+ other.fd_ = -1;
}
/**
@@ -147,27 +96,8 @@ FileDescriptor::FileDescriptor(FileDescriptor &&other)
*/
FileDescriptor::~FileDescriptor()
{
-}
-
-/**
- * \brief Copy assignment operator, replace the wrapped file descriptor with a
- * copy of \a other
- * \param[in] other The other FileDescriptor
- *
- * Copying a FileDescriptor creates a new reference to the wrapped file
- * descriptor owner by \a other. If \a other is invalid, *this will also be
- * invalid. The original FileDescriptor is left untouched, and the caller is
- * responsible for destroying it when appropriate. The wrapped file descriptor
- * will be closed automatically when all FileDescriptor instances that
- * reference it are destroyed.
- *
- * \return A reference to this FileDescriptor
- */
-FileDescriptor &FileDescriptor::operator=(const FileDescriptor &other)
-{
- fd_ = other.fd_;
-
- return *this;
+ if (isValid())
+ close(fd_);
}
/**
@@ -186,7 +116,7 @@ FileDescriptor &FileDescriptor::operator=(const FileDescriptor &other)
*/
FileDescriptor &FileDescriptor::operator=(FileDescriptor &&other)
{
- fd_ = std::move(other.fd_);
+ std::swap(fd_, other.fd_);
return *this;
}
@@ -218,29 +148,17 @@ FileDescriptor &FileDescriptor::operator=(FileDescriptor &&other)
*/
FileDescriptor FileDescriptor::dup() const
{
- return FileDescriptor(fd());
-}
+ if (!isValid())
+ return FileDescriptor();
-FileDescriptor::Descriptor::Descriptor(int fd, bool duplicate)
-{
- if (!duplicate) {
- fd_ = fd;
- return;
- }
-
- /* Failing to dup() a fd should not happen and is fatal. */
- fd_ = ::dup(fd);
- if (fd_ == -1) {
+ int dupFd = ::dup(fd);
+ if (dupFd == -1) {
int ret = -errno;
LOG(FileDescriptor, Fatal)
<< "Failed to dup() fd: " << strerror(-ret);
+ return FileDescriptor();
}
-}
-FileDescriptor::Descriptor::~Descriptor()
-{
- if (fd_ != -1)
- close(fd_);
+ return FileDescriptor(dupFd);
}
-
} /* namespace libcamera */
--
2.31.1.295.g9ea45b61b8-goog
More information about the libcamera-devel
mailing list