1 #pragma once 2 3 #include <unistd.h> // for close() 4 5 namespace util 6 { 7 8 /** 9 * @class FileDescriptor 10 * 11 * This class manages an open file descriptor. 12 * 13 * The file descriptor can be closed by calling close(). Otherwise it will be 14 * closed by the destructor. 15 * 16 * FileDescriptor objects cannot be copied, but they can be moved. This enables 17 * them to be stored in containers like std::vector. 18 */ 19 class FileDescriptor 20 { 21 public: 22 FileDescriptor() = default; 23 FileDescriptor(const FileDescriptor&) = delete; 24 FileDescriptor& operator=(const FileDescriptor&) = delete; 25 26 /** 27 * Constructor. 28 * 29 * @param[in] fd - File descriptor 30 */ 31 explicit FileDescriptor(int fd) : fd(fd) {} 32 33 /** 34 * Move constructor. 35 * 36 * Transfers ownership of a file descriptor. 37 * 38 * @param other - FileDescriptor object being moved 39 */ 40 FileDescriptor(FileDescriptor&& other) : fd(other.fd) 41 { 42 other.fd = -1; 43 } 44 45 /** 46 * Move assignment operator. 47 * 48 * Closes the file descriptor owned by this object, if any. Then transfers 49 * ownership of the file descriptor owned by the other object. 50 * 51 * @param other - FileDescriptor object being moved 52 */ 53 FileDescriptor& operator=(FileDescriptor&& other) 54 { 55 // Verify not assigning object to itself (a = std::move(a)) 56 if (this != &other) 57 { 58 set(other.fd); 59 other.fd = -1; 60 } 61 return *this; 62 } 63 64 /** 65 * Destructor. 66 * 67 * Closes the file descriptor if necessary. 68 */ 69 ~FileDescriptor() 70 { 71 close(); 72 } 73 74 /** 75 * Returns the file descriptor. 76 * 77 * @return File descriptor. Returns -1 if this object does not contain an 78 * open file descriptor. 79 */ 80 int operator()() const 81 { 82 return fd; 83 } 84 85 /** 86 * Returns whether this object contains an open file descriptor. 87 * 88 * @return true if object contains an open file descriptor, false otherwise. 89 */ 90 operator bool() const 91 { 92 return fd != -1; 93 } 94 95 /** 96 * Closes the file descriptor. 97 * 98 * Does nothing if the file descriptor was not set or was already closed. 99 * 100 * @return 0 if descriptor was successfully closed. Returns -1 if an error 101 * occurred; errno will be set appropriately. 102 */ 103 int close() 104 { 105 int rc = 0; 106 if (fd >= 0) 107 { 108 rc = ::close(fd); 109 fd = -1; 110 } 111 return rc; 112 } 113 114 /** 115 * Sets the file descriptor. 116 * 117 * Closes the previous file descriptor if necessary. 118 * 119 * @param[in] descriptor - File descriptor 120 */ 121 void set(int descriptor) 122 { 123 close(); 124 fd = descriptor; 125 } 126 127 private: 128 /** 129 * File descriptor. 130 */ 131 int fd = -1; 132 }; 133 134 } // namespace util 135