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 */ 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 */ Get()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 */ 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 */ 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 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> 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> 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> 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> 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> 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> 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