{"id":12534,"url":"https://patchwork.libcamera.org/api/patches/12534/?format=json","web_url":"https://patchwork.libcamera.org/patch/12534/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20210610075027.523672-2-hiroh@chromium.org>","date":"2021-06-10T07:50:18","name":"[libcamera-devel,v2,01/10] libcamera: ScopedFD: Introduce ScopedFD","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"53d62daa1e602a6da0e9a8ec63e998216f35c84a","submitter":{"id":63,"url":"https://patchwork.libcamera.org/api/people/63/?format=json","name":"Hirokazu Honda","email":"hiroh@chromium.org"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/12534/mbox/","series":[{"id":2115,"url":"https://patchwork.libcamera.org/api/series/2115/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=2115","date":"2021-06-10T07:50:17","name":"Introduce ScopedFD","version":2,"mbox":"https://patchwork.libcamera.org/series/2115/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/12534/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/12534/checks/","tags":{},"headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 97A07BD78E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 10 Jun 2021 07:50:39 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6991568936;\n\tThu, 10 Jun 2021 09:50:38 +0200 (CEST)","from mail-pf1-x429.google.com (mail-pf1-x429.google.com\n\t[IPv6:2607:f8b0:4864:20::429])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A57C6602C5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 10 Jun 2021 09:50:36 +0200 (CEST)","by mail-pf1-x429.google.com with SMTP id u126so904995pfu.13\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 10 Jun 2021 00:50:36 -0700 (PDT)","from hiroh2.tok.corp.google.com\n\t([2401:fa00:8f:203:98e0:b356:1c8a:25d4])\n\tby smtp.gmail.com with ESMTPSA id\n\td66sm1565161pfa.32.2021.06.10.00.50.33\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tThu, 10 Jun 2021 00:50:34 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=chromium.org header.i=@chromium.org\n\theader.b=\"IpnhTORn\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org;\n\ts=google; \n\th=from:to:cc:subject:date:message-id:in-reply-to:references\n\t:mime-version:content-transfer-encoding;\n\tbh=VK/FliDppCrFRUYd6LB558bOEJnuwUUhkrgBuRhSYhg=;\n\tb=IpnhTORnWQ7xNYJdxDWxfErZyKzUIklfLh+NBVL4saeC+8WlWLtojYYw5Pg5dL9oqI\n\tEvzJ9JnCZh2zqIKHux65bL8sdrfWGBAEooaKigcYRCyhiDjFaWpweyuOpC52mIB+R9Kx\n\tEoARLxmMJyA6J7NApH3BOqgqw1/dNgv/g7oiE=","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references:mime-version:content-transfer-encoding;\n\tbh=VK/FliDppCrFRUYd6LB558bOEJnuwUUhkrgBuRhSYhg=;\n\tb=cKCYSJeJbro++cE/6ZB1BzDK44NGtt1Z23k0MpXs4Rra+vcPbw23xepkRiCRjwdO8c\n\tx8hOs5bORfdi6RWTiErszNLquqi7/ldi0PJwahElEls/KtvmV2fq1iaLp9xFdcSuFoHG\n\tqlwcddaHRcEytvTQjUIbCd8TGel6l3M9OFNlygBzQ0AicqaMshP05H7CNXBdHz6f6L40\n\tQInk4fqZVAZSD9monYqus40x03kI1JYJCf5sgy+0mzsTHohm5pfep2tYXYcZ63bKPaAW\n\tpxFK3KcfIzusxe38y4vFsTKB7obf1PsbiCoXSlwJ1kzvlylzmG/DJPyNoxvLHsHMuKrA\n\t4dGA==","X-Gm-Message-State":"AOAM5317xGBsJTGVIAJOWWqjpndshG24WrVjK/e0EmcacTePMvCI7wW8\n\tQ5R/rGXK8ngHF7gut0jKEkH8ialEnP4iqA==","X-Google-Smtp-Source":"ABdhPJyBF34RPS7l34siTXSNTbWMAvRSu489JUW1rSoRinLZ0ennB9tQeyEzVCRy4Dxczlrmsm9xhg==","X-Received":"by 2002:a63:ee11:: with SMTP id\n\te17mr3711858pgi.323.1623311434901; \n\tThu, 10 Jun 2021 00:50:34 -0700 (PDT)","From":"Hirokazu Honda <hiroh@chromium.org>","To":"libcamera-devel@lists.libcamera.org","Date":"Thu, 10 Jun 2021 16:50:18 +0900","Message-Id":"<20210610075027.523672-2-hiroh@chromium.org>","X-Mailer":"git-send-email 2.32.0.rc1.229.g3e70b5a671-goog","In-Reply-To":"<20210610075027.523672-1-hiroh@chromium.org>","References":"<20210610075027.523672-1-hiroh@chromium.org>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","Subject":"[libcamera-devel] [PATCH v2 01/10] libcamera: ScopedFD: Introduce\n\tScopedFD","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"},"content":"This introduces ScopedFD. It acts like unique_ptr to a file\ndescriptor.\n\nSigned-off-by: Hirokazu Honda <hiroh@chromium.org>\n---\n include/libcamera/file_descriptor.h |   3 +\n include/libcamera/meson.build       |   1 +\n include/libcamera/scoped_fd.h       |  36 ++++++++\n src/libcamera/file_descriptor.cpp   |  20 +++++\n src/libcamera/meson.build           |   1 +\n src/libcamera/scoped_fd.cpp         | 129 ++++++++++++++++++++++++++++\n 6 files changed, 190 insertions(+)\n create mode 100644 include/libcamera/scoped_fd.h\n create mode 100644 src/libcamera/scoped_fd.cpp","diff":"diff --git a/include/libcamera/file_descriptor.h b/include/libcamera/file_descriptor.h\nindex d514aac7..1d71d58c 100644\n--- a/include/libcamera/file_descriptor.h\n+++ b/include/libcamera/file_descriptor.h\n@@ -11,11 +11,14 @@\n \n namespace libcamera {\n \n+class ScopedFD;\n+\n class FileDescriptor final\n {\n public:\n \texplicit FileDescriptor(const int &fd = -1);\n \texplicit FileDescriptor(int &&fd);\n+\texplicit FileDescriptor(ScopedFD &&fd);\n \tFileDescriptor(const FileDescriptor &other);\n \tFileDescriptor(FileDescriptor &&other);\n \t~FileDescriptor();\ndiff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\nindex 086c958b..e1c8b253 100644\n--- a/include/libcamera/meson.build\n+++ b/include/libcamera/meson.build\n@@ -15,6 +15,7 @@ libcamera_public_headers = files([\n     'object.h',\n     'pixel_format.h',\n     'request.h',\n+    'scoped_fd.h',\n     'signal.h',\n     'span.h',\n     'stream.h',\ndiff --git a/include/libcamera/scoped_fd.h b/include/libcamera/scoped_fd.h\nnew file mode 100644\nindex 00000000..d91b53b4\n--- /dev/null\n+++ b/include/libcamera/scoped_fd.h\n@@ -0,0 +1,36 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2021, Google Inc.\n+ *\n+ * scoped_fd.h - File descriptor wrapper that owns a file descriptor.\n+ */\n+#ifndef __LIBCAMERA_SCOPED_FD_H__\n+#define __LIBCAMERA_SCOPED_FD_H__\n+\n+#include <libcamera/class.h>\n+#include <libcamera/compiler.h>\n+\n+namespace libcamera {\n+\n+class ScopedFD final\n+{\n+public:\n+\texplicit ScopedFD(const int fd = -1);\n+\t~ScopedFD();\n+\tScopedFD(ScopedFD &&other);\n+\tScopedFD &operator=(ScopedFD &&other);\n+\n+\tbool isValid() const { return fd_ == -1; }\n+\tint get() const { return fd_; }\n+\tvoid reset(int fd = -1);\n+\t__nodiscard int release();\n+\n+private:\n+\tint fd_;\n+\n+\tLIBCAMERA_DISABLE_COPY(ScopedFD)\n+};\n+\n+} /* namespace libcamera */\n+\n+#endif /* __LIBCAMERA_SCOPED_FD_H__ */\ndiff --git a/src/libcamera/file_descriptor.cpp b/src/libcamera/file_descriptor.cpp\nindex 8b505ed3..4d30b757 100644\n--- a/src/libcamera/file_descriptor.cpp\n+++ b/src/libcamera/file_descriptor.cpp\n@@ -11,6 +11,8 @@\n #include <unistd.h>\n #include <utility>\n \n+#include <libcamera/scoped_fd.h>\n+\n #include \"libcamera/internal/log.h\"\n \n /**\n@@ -108,6 +110,24 @@ FileDescriptor::FileDescriptor(int &&fd)\n \tfd = -1;\n }\n \n+/**\n+ * \\brief Create a FileDescriptor taking ownership of a given ScopedFD \\a fd\n+ * \\param[in] fd ScopedFD\n+ *\n+ * Construct a FileDescriptor from ScopedFD by taking ownership of the \\a fd.\n+ * The original \\a fd becomes invalid. In particular, the caller shall not close\n+ * the original \\a fd manually. The duplicated file descriptor will be closed\n+ * automatically when all FileDescriptor instances that reference it are\n+ * destroyed.\n+ *\n+ * If the \\a fd is negative, the FileDescriptor is constructed as invalid and\n+ * the fd() method will return -1.\n+ */\n+FileDescriptor::FileDescriptor(ScopedFD &&fd)\n+\t: FileDescriptor(fd.release())\n+{\n+}\n+\n /**\n  * \\brief Copy constructor, create a FileDescriptor from a copy of \\a other\n  * \\param[in] other The other FileDescriptor\ndiff --git a/src/libcamera/meson.build b/src/libcamera/meson.build\nindex 7e19a177..ed311acf 100644\n--- a/src/libcamera/meson.build\n+++ b/src/libcamera/meson.build\n@@ -44,6 +44,7 @@ libcamera_sources = files([\n     'process.cpp',\n     'pub_key.cpp',\n     'request.cpp',\n+    'scoped_fd.cpp',\n     'semaphore.cpp',\n     'signal.cpp',\n     'stream.cpp',\ndiff --git a/src/libcamera/scoped_fd.cpp b/src/libcamera/scoped_fd.cpp\nnew file mode 100644\nindex 00000000..106386dd\n--- /dev/null\n+++ b/src/libcamera/scoped_fd.cpp\n@@ -0,0 +1,129 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2021, Google Inc.\n+ *\n+ * scoped_fd.cpp - File descriptor wrapper that owns a file descriptor.\n+ */\n+\n+#include <libcamera/scoped_fd.h>\n+\n+#include <unistd.h>\n+\n+#include \"libcamera/internal/log.h\"\n+\n+/**\n+ * \\file scoped_fd.h\n+ * \\brief File descriptor wrapper that owns a file descriptor\n+ */\n+\n+namespace libcamera {\n+\n+LOG_DEFINE_CATEGORY(ScopedFD)\n+\n+/**\n+ * \\class ScopedFD\n+ * \\brief unique_ptr like wrapper for a file descriptor\n+ *\n+ * The ScopedFD provides RAII-style lifetime management of a file descriptor.\n+ * It doesn't allow the shared ownership unlike FileDescriptor. It is\n+ * constructed from a numerical file descriptor and takes over the ownership of\n+ * the file descriptor. When the ScopedFD is destroyed, the managed file\n+ * descriptor is closed.\n+ */\n+\n+/**\n+ * \\brief Create a ScopedFD taking over a given \\a fd\n+ * \\param[in] fd a numerical file descriptor\n+ *\n+ * Construct a ScopedFD from a numerical file descriptor and take ownership of\n+ * the file descriptor. The given file descriptor is automatically closed when\n+ * the ScopedFD is destructed.\n+ */\n+ScopedFD::ScopedFD(const int fd)\n+\t: fd_(fd >= 0 ? fd : -1)\n+{\n+}\n+\n+/**\n+ * \\brief Destroy the ScopedFD instance\n+ *\n+ * The owned file descriptor is automatically closed if it is valid.\n+ */\n+ScopedFD::~ScopedFD()\n+{\n+\treset();\n+}\n+\n+/**\n+ * \\brief Move constructor, create a ScopedFD by taking over \\a other\n+ * \\param[in] other The other ScopedFD\n+ *\n+ * Create a ScopedFD that takes the ownership of the file descriptor owned by \\a\n+ * other. Upon return, the \\a other ScopedFD is invalid.\n+ */\n+ScopedFD::ScopedFD(ScopedFD &&other)\n+\t: fd_(other.release())\n+{\n+}\n+\n+/**\n+ * \\brief Move assignment operator, replace a ScopedFD by taking over \\a other\n+ * \\param[in] other The other ScopedFD\n+ *\n+ * If this ScopedFD has a valid file descriptor, the file descriptor is closed\n+ * first. The file descriptor is then replaced by the one of \\a other. Upon\n+ * return, \\a other is invalid.\n+ *\n+ * \\return A reference to this ScopedFD\n+ */\n+ScopedFD &ScopedFD::operator=(ScopedFD &&other)\n+{\n+\treset(other.release());\n+\n+\treturn *this;\n+}\n+\n+/**\n+ * \\fn ScopedFD::isValid()\n+ * \\brief Check if the ScopedFD has a valid file descriptor\n+ * \\return True if the ScopedFD has a valid file descriptor, false otherwise\n+ */\n+\n+/**\n+ * \\fn ScopedFD::get()\n+ * \\brief Retrieve the numerical file descriptor\n+ * \\return The numerical file descriptor\n+ */\n+\n+/**\n+ * \\fn ScopedFD::reset()\n+ * \\brief Swap the owned file descriptor with \\a fd. The originally owned file\n+ * descriptor is closed.\n+ * \\param[in] fd a numerical file descriptor\n+ */\n+void ScopedFD::reset(int fd)\n+{\n+\tASSERT(!isValid() || fd != fd_);\n+\tif (isValid())\n+\t\tclose(fd_);\n+\tfd_ = fd;\n+}\n+\n+/**\n+ * \\fn ScopedFD::release()\n+ * \\brief Release ownership of the file descriptor without closing it\n+ *\n+ * This function releases and returns the owned file descriptor without closing\n+ * it. The caller owns the returned value and must take care of handling its\n+ * life time to avoid file descriptor leakages. Upon return the ScopedFD is\n+ * invalid.\n+ *\n+ * \\return The numerical file descriptor\n+ */\n+int ScopedFD::release()\n+{\n+\tint fd = fd_;\n+\tfd_ = -1;\n+\treturn fd;\n+}\n+} /* namespace libcamera */\n","prefixes":["libcamera-devel","v2","01/10"]}