diff options
-rw-r--r-- | include/libcamera/file_descriptor.h | 5 | ||||
-rw-r--r-- | src/libcamera/file_descriptor.cpp | 85 |
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) { |