1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 /**
17 * @file unique_fd.h
18 *
19 * @brief Provides APIs to manage file descriptors (FDs) implemented in c_utils.
20 *
21 * The manager class `UniqueFdAddDeletor`,
22 * the default deleter class `DefaultDeleter`,
23 * and related global overloaded operator functions are provided.
24 */
25 #ifndef UNIQUE_FD_H
26 #define UNIQUE_FD_H
27
28 #include <unistd.h>
29
30 namespace OHOS {
31
32 /**
33 * @brief Provides the default implementation for a deleter,
34 * including a static function to close FDs.
35 *
36 * The deleter is used for closing FDs. You can implement a deleter to
37 * deal with a different scenario. When `Deleter::Close()` is called to enable
38 * a `UniqueFdAddDeletor` object to release the management of an FD,
39 * the FD can no longer be taken over by other `UniqueFdAddDeletor` objects.
40 */
41 class DefaultDeleter {
42 public:
43 /**
44 * @brief Default function to close an FD.
45 *
46 * Call `close()` if the input FD is valid (greater than or equal to 0).
47 *
48 * @param fd Indicates an FD.
49 */
Close(int fd)50 static void Close(int fd)
51 {
52 if (fd >= 0) {
53 close(fd);
54 }
55 }
56 };
57
58 template <typename Deleter>
59 class UniqueFdAddDeletor;
60 template <typename Deleter>
61 bool operator==(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs);
62 template <typename Deleter>
63 bool operator!=(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs);
64 template <typename Deleter>
65 bool operator>=(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs);
66 template <typename Deleter>
67 bool operator>(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs);
68 template <typename Deleter>
69 bool operator<=(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs);
70 template <typename Deleter>
71 bool operator<(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs);
72
73 /**
74 * @brief Defines an FD manager.
75 *
76 * To ensure unique management on an FD, avoid the double-close issue,
77 * which may cause a file to be incorrectly closed./n
78 * The management of an FD can be delivered between `UniqueFdAddDeletor`
79 * objects. An FD will be closed if no `UniqueFdAddDeletor` object is available
80 * to take over its management.
81 *
82 * @tparam Deleter Indicates a deleter.
83 * @see DefaultDeleter
84 */
85 template <typename Deleter = DefaultDeleter>
86 class UniqueFdAddDeletor final {
87 friend bool operator==<Deleter>(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs);
88
89 friend bool operator!=<Deleter>(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs);
90
91 friend bool operator>=<Deleter>(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs);
92
93 friend bool operator><Deleter>(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs);
94
95 friend bool operator<=<Deleter>(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs);
96
97 friend bool operator< <Deleter>(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs);
98
99 public:
100 /**
101 * @brief Creates a `UniqueFdAddDeletor` object to manage an FD.
102 *
103 * @param value Indicates the FD to be managed.
104 */
UniqueFdAddDeletor(const int& value)105 explicit UniqueFdAddDeletor(const int& value)
106 : fd_(value)
107 {
108 }
109
110 /**
111 * @brief Constructor used to create a `UniqueFdAddDeletor` object
112 * with the FD set to `-1`.
113 */
UniqueFdAddDeletor()114 UniqueFdAddDeletor()
115 : fd_(-1)
116 {
117 }
118
119 /**
120 * @brief Destructor used to destroy this `UniqueFdAddDeletor` object.
121 *
122 * This function is used to close the FD and set the FD to `-1`.
123 */
~UniqueFdAddDeletor()124 ~UniqueFdAddDeletor() { Reset(-1); }
125
126 /**
127 * @brief Releases the management on the current FD and sets it to `-1`.
128 *
129 * @return Returns the original FD before release.
130 * @note The released FD needs to be taken over by another
131 * `UniqueFdAddDeletor` object; otherwise, it must be closed manually.
132 */
Release()133 int Release()
134 {
135 int tmp = fd_;
136 fd_ = -1;
137 return tmp;
138 }
139
140 // this is dangerous, when you use it , you should know it,
141 // do not operator on the ret
142 /**
143 * @brief An overloaded cast operator function.
144 *
145 * This function will be called when passing a `UniqueFdAddDeletor` object
146 * to a function that requires a parameter of `int`.
147 *
148 * @return Returns the current FD under management.
149 */
operator int() const150 operator int() const { return Get(); } // NOLINT
151
152 // this is dangerous, when you use it , you should know it, do not operator
153 // on the ret
154 /**
155 * @brief Obtains the current FD under management, without releasing it.
156 *
157 * @return Returns the current FD.
158 */
Get() const159 int Get() const
160 {
161 return fd_;
162 }
163
164 // we need move fd from one to another
165 /**
166 * @brief Move constructor used to deliver the management of an FD from a
167 * `UniqueFdAddDeletor` object to this object.
168 *
169 * @param rhs Indicates the source `UniqueFdAddDeletor` object.
170 */
UniqueFdAddDeletor(UniqueFdAddDeletor&& rhs)171 UniqueFdAddDeletor(UniqueFdAddDeletor&& rhs)
172 {
173 int rhsfd = rhs.Release();
174 fd_ = rhsfd;
175 }
176
177 /**
178 * @brief Overloaded move assignment operator function used to deliver the
179 * management of an FD from a `UniqueFdAddDeletor` object to this object.
180 *
181 * @param rhs Indicates the source `UniqueFdAddDeletor` object.
182 * @return Returns this `UniqueFdAddDeletor` object.
183 * @note The current FD manged by this `UniqueFdAddDeletor` object will be
184 * closed, and this object will take over
185 * the FD originally managed by `rhs`.
186 */
operator =(UniqueFdAddDeletor&& rhs)187 UniqueFdAddDeletor& operator=(UniqueFdAddDeletor&& rhs)
188 {
189 int rhsfd = rhs.Release();
190 Reset(rhsfd);
191 return *this;
192 }
193
194 /**
195 * @brief Checks whether the FD managed by this object and that managed by
196 * the source object are equal.
197 *
198 * @param rhs Indicates the source `UniqueFdAddDeletor` object.
199 *
200 * @return Returns `true` if the two FDs are equal; returns `false`
201 * otherwise.
202 */
operator ==(const int& rhs) const203 bool operator==(const int& rhs) const
204 {
205 return fd_ == rhs;
206 }
207
208 /**
209 * @brief Checks whether the FD managed by this object and that managed by
210 * the source object are not equal.
211 *
212 * @param rhs Indicates the source `UniqueFdAddDeletor` object.
213 *
214 * @return Returns `true` if the two FDs are not equal; returns `false`
215 * otherwise.
216 */
operator !=(const int& rhs) const217 bool operator!=(const int& rhs) const
218 {
219 return !(fd_ == rhs);
220 }
221
222 /**
223 * @brief Checks whether the FD managed by this object is greater than or
224 * equal to that managed by the source object.
225 *
226 * @param rhs Indicates the source `UniqueFdAddDeletor` object.
227 *
228 * @return Returns `true` if FD managed by this object is greater than or
229 * equal to that managed by the source object; returns `false` otherwise.
230 */
operator >=(const int& rhs) const231 bool operator>=(const int& rhs) const
232 {
233 return fd_ >= rhs;
234 }
235
236 /**
237 * @brief Checks whether the FD managed by this object is greater than that
238 * managed by the source object.
239 *
240 * @param rhs Indicates the source `UniqueFdAddDeletor` object.
241 *
242 * @return Returns `true` if FD managed by this object is greater than that
243 * managed by the source object; returns `false` otherwise.
244 */
operator >(const int& rhs) const245 bool operator>(const int& rhs) const
246 {
247 return fd_ > rhs;
248 }
249
250 /**
251 * @brief Checks whether the FD managed by this object is less than or equal
252 * to that managed by the source object.
253 *
254 * @param rhs Indicates the source `UniqueFdAddDeletor` object.
255 *
256 * @return Returns `true` if FD managed by this object is less than or equal
257 * to that managed by the source object; returns `false` otherwise.
258 */
operator <=(const int& rhs) const259 bool operator<=(const int& rhs) const
260 {
261 return fd_ <= rhs;
262 }
263
264 /**
265 * @brief Checks whether the FD managed by this object is less than that
266 * managed by the source object.
267 *
268 * @param rhs Indicates the source `UniqueFdAddDeletor` object.
269 *
270 * @return Returns `true` if FD managed by this object is less than that
271 * managed by the source object; returns `false` otherwise.
272 */
operator <(const int& rhs) const273 bool operator<(const int& rhs) const
274 {
275 return fd_ < rhs;
276 }
277
278 private:
279 int fd_ = -1;
280
Reset(int newValue)281 void Reset(int newValue)
282 {
283 if (fd_ >= 0) {
284 Deleter::Close(fd_);
285 }
286 fd_ = newValue;
287 }
288
289 // disallow copy ctor and copy assign
290 UniqueFdAddDeletor(const UniqueFdAddDeletor& rhs) = delete;
291 UniqueFdAddDeletor& operator=(const UniqueFdAddDeletor& rhs) = delete;
292 };
293
294 /**
295 * @brief Checks whether the FD managed by two objects (specified by `lhs` and
296 * `rhs` respectively) are equal.
297 *
298 * @tparam Deleter Indicates a deleter.
299 * @param lhs Indicates the first `UniqueFdAddDeletor` object.
300 * @param rhs Indicates the second `UniqueFdAddDeletor` object.
301 *
302 * @return Returns `true` if the two FDs are equal; returns `false` otherwise.
303 * @see DefaultDeleter
304 */
305 template <typename Deleter = DefaultDeleter>
operator ==(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs)306 bool operator==(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs)
307 {
308 return lhs == rhs.fd_;
309 }
310
311 /**
312 * @brief Checks whether the FD managed by two objects (specified by `lhs` and
313 * `rhs` respectively) are not equal.
314 *
315 * @tparam Deleter Indicates a deleter.
316 * @param lhs Indicates the first `UniqueFdAddDeletor` object.
317 * @param rhs Indicates the second `UniqueFdAddDeletor` object.
318 *
319 * @return Returns `true` if the two FDs are not equal; returns `false`
320 * otherwise.
321 * @see DefaultDeleter
322 */
323 template <typename Deleter = DefaultDeleter>
operator !=(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs)324 bool operator!=(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs)
325 {
326 return !(lhs == rhs.fd_);
327 }
328
329 /**
330 * @brief Checks whether the FD managed by `lhs` is greater than or equal to
331 * that managed by `rhs`.
332 *
333 * @tparam Deleter Indicates a deleter.
334 * @param lhs Indicates the first `UniqueFdAddDeletor` object.
335 * @param rhs Indicates the second `UniqueFdAddDeletor` object.
336 *
337 * @return Returns `true` if the FD managed by `lhs` is greater than or equal to
338 * that managed by `rhs`; returns `false` otherwise.
339 * @see DefaultDeleter
340 */
341 template <typename Deleter = DefaultDeleter>
operator >=(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs)342 bool operator>=(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs)
343 {
344 return lhs >= rhs.fd_;
345 }
346
347 /**
348 * @brief Checks whether the FD managed by `lhs` is greater than that
349 * managed by `rhs`.
350 *
351 * @tparam Deleter Indicates a deleter.
352 * @param lhs Indicates the first `UniqueFdAddDeletor` object.
353 * @param rhs Indicates the second `UniqueFdAddDeletor` object.
354 *
355 * @return Returns `true` if the FD managed by `lhs` is greater than that
356 * managed by `rhs`; returns `false` otherwise.
357 * @see DefaultDeleter
358 */
359 template <typename Deleter = DefaultDeleter>
operator >(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs)360 bool operator>(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs)
361 {
362 return lhs > rhs.fd_;
363 }
364
365 /**
366 * @brief Checks whether the FD managed by `lhs` is less than or equal to that
367 * managed by `rhs`.
368 *
369 * @tparam Deleter Indicates a deleter.
370 * @param lhs Indicates the first `UniqueFdAddDeletor` object.
371 * @param rhs Indicates the second `UniqueFdAddDeletor` object.
372 *
373 * @return Returns `true` if the FD managed by `lhs` is less than or equal to
374 * that managed by `rhs`; returns `false` otherwise.
375 * @see DefaultDeleter
376 */
377 template <typename Deleter = DefaultDeleter>
operator <=(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs)378 bool operator<=(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs)
379 {
380 return lhs <= rhs.fd_;
381 }
382
383 /**
384 * @brief Checks whether the FD managed by `lhs` is less than that
385 * managed by `rhs`.
386 *
387 * @tparam Deleter Indicates a deleter.
388 * @param lhs Indicates the first `UniqueFdAddDeletor` object.
389 * @param rhs Indicates the second `UniqueFdAddDeletor` object.
390 *
391 * @return Returns `true` if the FD managed by `lhs` is less than that
392 * managed by `rhs`; returns `false` otherwise.
393 * @see DefaultDeleter
394 */
395 template <typename Deleter = DefaultDeleter>
operator <(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs)396 bool operator<(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs)
397 {
398 return lhs < rhs.fd_;
399 }
400
401 using UniqueFd = UniqueFdAddDeletor<DefaultDeleter>;
402 } // namespace OHOS
403 #endif
404