blob: 0fc2690c5806a60a43e56ae2d5d64e6d698ec484 [file] [log] [blame]
#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()() const
{
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