blob: 51c125e2ff6dd53935670cae7fe71305cbda2218 [file] [log] [blame]
Zane Shelley6e365872020-10-23 22:00:05 -05001#pragma once
2
3#include <unistd.h> // for close()
4
5namespace 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 */
19class 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()()
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