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 30namespace 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 */ 41class DefaultDeleter { 42public: 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 */ 50 static void Close(int fd) 51 { 52 if (fd >= 0) { 53 close(fd); 54 } 55 } 56}; 57 58template <typename Deleter> 59class UniqueFdAddDeletor; 60template <typename Deleter> 61bool operator==(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs); 62template <typename Deleter> 63bool operator!=(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs); 64template <typename Deleter> 65bool operator>=(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs); 66template <typename Deleter> 67bool operator>(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs); 68template <typename Deleter> 69bool operator<=(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs); 70template <typename Deleter> 71bool 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 */ 85template <typename Deleter = DefaultDeleter> 86class 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 99public: 100 /** 101 * @brief Creates a `UniqueFdAddDeletor` object to manage an FD. 102 * 103 * @param value Indicates the FD to be managed. 104 */ 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 */ 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 */ 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 */ 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 */ 150 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 */ 159 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 */ 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 */ 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 */ 203 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 */ 217 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 */ 231 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 */ 245 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 */ 259 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 */ 273 bool operator<(const int& rhs) const 274 { 275 return fd_ < rhs; 276 } 277 278private: 279 int fd_ = -1; 280 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 */ 305template <typename Deleter = DefaultDeleter> 306bool 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 */ 323template <typename Deleter = DefaultDeleter> 324bool 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 */ 341template <typename Deleter = DefaultDeleter> 342bool 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 */ 359template <typename Deleter = DefaultDeleter> 360bool 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 */ 377template <typename Deleter = DefaultDeleter> 378bool 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 */ 395template <typename Deleter = DefaultDeleter> 396bool operator<(const int& lhs, const UniqueFdAddDeletor<Deleter>& rhs) 397{ 398 return lhs < rhs.fd_; 399} 400 401using UniqueFd = UniqueFdAddDeletor<DefaultDeleter>; 402} // namespace OHOS 403#endif 404