| #pragma once | 
 |  | 
 | #include <unistd.h> // for close() | 
 |  | 
 | namespace util | 
 | { | 
 |  | 
 | /** | 
 |  * @class FileDescriptor | 
 |  * | 
 |  * This class manages an open file descriptor. | 
 |  * | 
 |  * The file descriptor can be closed by calling close().  Otherwise it will be | 
 |  * closed by the destructor. | 
 |  * | 
 |  * FileDescriptor objects cannot be copied, but they can be moved.  This enables | 
 |  * them to be stored in containers like std::vector. | 
 |  */ | 
 | class FileDescriptor | 
 | { | 
 |   public: | 
 |     FileDescriptor()                      = default; | 
 |     FileDescriptor(const FileDescriptor&) = delete; | 
 |     FileDescriptor& operator=(const FileDescriptor&) = delete; | 
 |  | 
 |     /** | 
 |      * Constructor. | 
 |      * | 
 |      * @param[in] fd - File descriptor | 
 |      */ | 
 |     explicit FileDescriptor(int fd) : fd(fd) {} | 
 |  | 
 |     /** | 
 |      * Move constructor. | 
 |      * | 
 |      * Transfers ownership of a file descriptor. | 
 |      * | 
 |      * @param other - FileDescriptor object being moved | 
 |      */ | 
 |     FileDescriptor(FileDescriptor&& other) : fd(other.fd) | 
 |     { | 
 |         other.fd = -1; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Move assignment operator. | 
 |      * | 
 |      * Closes the file descriptor owned by this object, if any.  Then transfers | 
 |      * ownership of the file descriptor owned by the other object. | 
 |      * | 
 |      * @param other - FileDescriptor object being moved | 
 |      */ | 
 |     FileDescriptor& operator=(FileDescriptor&& other) | 
 |     { | 
 |         // Verify not assigning object to itself (a = std::move(a)) | 
 |         if (this != &other) | 
 |         { | 
 |             set(other.fd); | 
 |             other.fd = -1; | 
 |         } | 
 |         return *this; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Destructor. | 
 |      * | 
 |      * Closes the file descriptor if necessary. | 
 |      */ | 
 |     ~FileDescriptor() | 
 |     { | 
 |         close(); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns the file descriptor. | 
 |      * | 
 |      * @return File descriptor.  Returns -1 if this object does not contain an | 
 |      *         open file descriptor. | 
 |      */ | 
 |     int operator()() | 
 |     { | 
 |         return fd; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Returns whether this object contains an open file descriptor. | 
 |      * | 
 |      * @return true if object contains an open file descriptor, false otherwise. | 
 |      */ | 
 |     operator bool() const | 
 |     { | 
 |         return fd != -1; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Closes the file descriptor. | 
 |      * | 
 |      * Does nothing if the file descriptor was not set or was already closed. | 
 |      * | 
 |      * @return 0 if descriptor was successfully closed.  Returns -1 if an error | 
 |      *         occurred; errno will be set appropriately. | 
 |      */ | 
 |     int close() | 
 |     { | 
 |         int rc = 0; | 
 |         if (fd >= 0) | 
 |         { | 
 |             rc = ::close(fd); | 
 |             fd = -1; | 
 |         } | 
 |         return rc; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Sets the file descriptor. | 
 |      * | 
 |      * Closes the previous file descriptor if necessary. | 
 |      * | 
 |      * @param[in] descriptor - File descriptor | 
 |      */ | 
 |     void set(int descriptor) | 
 |     { | 
 |         close(); | 
 |         fd = descriptor; | 
 |     } | 
 |  | 
 |   private: | 
 |     /** | 
 |      * File descriptor. | 
 |      */ | 
 |     int fd = -1; | 
 | }; | 
 |  | 
 | } // namespace util |