summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libcamera/file_descriptor.h5
-rw-r--r--src/libcamera/file_descriptor.cpp85
2 files changed, 67 insertions, 23 deletions
diff --git a/include/libcamera/file_descriptor.h b/include/libcamera/file_descriptor.h
index 8612f865..d514aac7 100644
--- a/include/libcamera/file_descriptor.h
+++ b/include/libcamera/file_descriptor.h
@@ -14,7 +14,8 @@ namespace libcamera {
class FileDescriptor final
{
public:
- explicit FileDescriptor(int fd = -1);
+ explicit FileDescriptor(const int &fd = -1);
+ explicit FileDescriptor(int &&fd);
FileDescriptor(const FileDescriptor &other);
FileDescriptor(FileDescriptor &&other);
~FileDescriptor();
@@ -30,7 +31,7 @@ private:
class Descriptor
{
public:
- Descriptor(int fd);
+ Descriptor(int fd, bool duplicate);
~Descriptor();
int fd() const { return fd_; }
diff --git a/src/libcamera/file_descriptor.cpp b/src/libcamera/file_descriptor.cpp
index ee60064b..640e66e6 100644
--- a/src/libcamera/file_descriptor.cpp
+++ b/src/libcamera/file_descriptor.cpp
@@ -33,44 +33,82 @@ LOG_DEFINE_CATEGORY(FileDescriptor)
* shared with all FileDescriptor instances constructed as copies.
*
* When constructed from a numerical file descriptor, the FileDescriptor
- * instance duplicates the file descriptor and wraps the duplicate as a
- * Descriptor. The copy constructor and assignment operator create copies that
- * share the Descriptor, while the move versions of those methods additionally
- * make the other FileDescriptor invalid. When the last FileDescriptor that
- * references a Descriptor is destroyed, the file descriptor is closed.
- *
- * The numerical file descriptor is available through the fd() method. As
- * constructing a FileDescriptor from a numerical file descriptor duplicates
- * the file descriptor, the value returned by fd() will be different than the
- * value passed to the constructor. All FileDescriptor instances created as
- * copies of a FileDescriptor will report the same fd() value. Callers can
- * perform operations on the fd(), but shall never close it manually.
+ * 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
+ * descriptor and wraps it in a Descriptor. The caller is 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.
+ *
+ * The copy constructor and assignment operator create copies that share the
+ * Descriptor, while the move versions of those methods additionally make the
+ * other FileDescriptor invalid. When the last FileDescriptor that references a
+ * Descriptor is destroyed, the file descriptor is closed.
+ *
+ * The numerical file descriptor is available through the fd() method. All
+ * FileDescriptor instances created as copies of a FileDescriptor will report
+ * the same fd() value. Callers can perform operations on the fd(), but shall
+ * never close it manually.
*/
/**
- * \brief Create a FileDescriptor wrapping a copy of a given \a fd
+ * \brief Create a FileDescriptor copying a given \a fd
* \param[in] fd File descriptor
*
- * Constructing a FileDescriptor from a numerical file descriptor duplicates the
- * \a fd and takes ownership of the copy. The original \a fd is left untouched,
- * and the caller is responsible for closing it when appropriate. The duplicated
- * file descriptor will be closed automatically when all FileDescriptor
- * instances that reference it are destroyed.
+ * Construct a FileDescriptor from a numerical file descriptor by duplicating
+ * the \a fd, and take ownership of the copy. The original \a fd is left
+ * untouched, and the caller is responsible for closing it when appropriate.
+ * 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)
+FileDescriptor::FileDescriptor(const int &fd)
{
if (fd < 0)
return;
- fd_ = std::make_shared<Descriptor>(fd);
+ 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
*
@@ -183,8 +221,13 @@ FileDescriptor FileDescriptor::dup() const
return FileDescriptor(fd());
}
-FileDescriptor::Descriptor::Descriptor(int fd)
+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) {