blob: 1a390ba188e85b689fa1f0f7508e3ad34772acde [file] [log] [blame]
Roman Stratiienko0fade372021-02-20 13:59:55 +02001/*
2 * Copyright (C) 2015, 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef UNIQUEFD_H_
18#define UNIQUEFD_H_
19
20#include <unistd.h>
21
22#include <memory>
23
24namespace android {
25
26/*
27 * Using UniqueFd:
28 * 1. Create UniqueFd object:
29 * auto fd_obj = UniqueFd(open("SomeFile", xxx));
30 *
31 * 2. Check whether the fd_obj is empty:
32 * if (!fd_obj) { return -errno; }
33 *
34 * 3. Accessing the file descriptor:
35 * int ret = read(fd_obj.Get(), buf, buf_size);
36 *
37 * 4. Closing the file:
38 * FD will be closed once execution leaves fd_obj scope (on any return,
39 * exception, destruction of class/struct where object is member, etc.).
40 * User can also force closing the fd_obj by calling:
41 * fd_obj = UniqueFd();
42 * // fd is closed and fd_obj is empty now.
43 *
44 * 5. File descriptor may be transferred to the code, which will close it after
45 * using. This can be done in 2 ways:
46 * a. Duplicate the fd, in this case both fds should be closed separately:
47 * int out_fd = dup(fd_obj.Get();
48 * ...
49 * close(out_fd);
50 * b. Transfer ownership, use this method if you do not need the fd anymore.
51 * int out_fd = fd_obj.Release();
52 * // fd_obj is empty now.
53 * ...
54 * close(out_fd);
55 *
56 * 6. Transferring fd into another UniqueFD object:
57 * UniqueFd fd_obj_2 = std::move(fd_obj);
58 * // fd_obj empty now
59 */
60
61constexpr int kEmptyFd = -1;
62
63class UniqueFd {
64 public:
65 UniqueFd() = default;
66 explicit UniqueFd(int fd) : fd_(fd){};
67
68 auto Release [[nodiscard]] () -> int {
69 return std::exchange(fd_, kEmptyFd);
70 }
71
72 auto Get [[nodiscard]] () const -> int {
73 return fd_;
74 }
75
76 explicit operator bool() const {
77 return fd_ != kEmptyFd;
78 }
79
80 ~UniqueFd() {
81 Set(kEmptyFd);
82 }
83
84 /* Allow move semantics */
85 UniqueFd(UniqueFd &&rhs) noexcept {
86 Set(rhs.Release());
87 }
88
89 auto operator=(UniqueFd &&rhs) noexcept -> UniqueFd & {
90 Set(rhs.Release());
91 return *this;
92 }
93
94 /* Disable copy semantics */
95 UniqueFd(const UniqueFd &) = delete;
96 auto operator=(const UniqueFd &) = delete;
97
98 private:
99 void Set(int new_fd) {
100 if (fd_ != kEmptyFd) {
101 close(fd_);
102 }
103 fd_ = new_fd;
104 }
105
106 int fd_ = kEmptyFd;
107};
108
109} // namespace android
110
111#endif