-
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
filedescriptor: implent a new FileDescriptor class
makes you able to RAII the filedescriptor making it somewhat easier to not leak.
- Loading branch information
Showing
2 changed files
with
128 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
#pragma once | ||
|
||
#include <fcntl.h> | ||
namespace Hyprutils { | ||
namespace Utils { | ||
class CFileDescriptor { | ||
public: | ||
CFileDescriptor() = default; | ||
explicit CFileDescriptor(int const fd); | ||
CFileDescriptor(CFileDescriptor&&); | ||
CFileDescriptor& operator=(CFileDescriptor&&); | ||
~CFileDescriptor(); | ||
|
||
CFileDescriptor(const CFileDescriptor&) = delete; | ||
CFileDescriptor& operator=(const CFileDescriptor&) = delete; | ||
|
||
bool operator==(const CFileDescriptor& rhs) const { | ||
return m_fd == rhs.m_fd; | ||
} | ||
|
||
bool isValid() const; | ||
int get() const; | ||
int getFlags() const; | ||
bool setFlags(int flags); | ||
int take(); | ||
void reset(); | ||
CFileDescriptor duplicate(int flags = F_DUPFD_CLOEXEC) const; | ||
|
||
bool isReadable() const; | ||
bool isClosed() const; | ||
|
||
static bool isReadable(int fd); | ||
static bool isClosed(int fd); | ||
|
||
private: | ||
int m_fd = -1; | ||
}; | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
#include <cstdlib> | ||
#include <hyprutils/utils/FileDescriptor.hpp> | ||
#include <fcntl.h> | ||
#include <sys/poll.h> | ||
#include <unistd.h> | ||
#include <utility> | ||
|
||
using namespace Hyprutils::Utils; | ||
|
||
CFileDescriptor::CFileDescriptor(int const fd) : m_fd(fd) {} | ||
|
||
CFileDescriptor::CFileDescriptor(CFileDescriptor&& other) : m_fd(std::exchange(other.m_fd, -1)) {} | ||
|
||
CFileDescriptor& CFileDescriptor::operator=(CFileDescriptor&& other) { | ||
if (this == &other) // Shit will go haywire if there is duplicate ownership | ||
abort(); | ||
|
||
reset(); | ||
m_fd = std::exchange(other.m_fd, -1); | ||
return *this; | ||
} | ||
|
||
CFileDescriptor::~CFileDescriptor() { | ||
reset(); | ||
} | ||
|
||
bool CFileDescriptor::isValid() const { | ||
return m_fd != -1; | ||
} | ||
|
||
int CFileDescriptor::get() const { | ||
return m_fd; | ||
} | ||
|
||
int CFileDescriptor::getFlags() const { | ||
return fcntl(m_fd, F_GETFD); | ||
} | ||
|
||
bool CFileDescriptor::setFlags(int flags) { | ||
if (fcntl(m_fd, F_SETFD, flags) == -1) | ||
return false; | ||
|
||
return true; | ||
} | ||
|
||
int CFileDescriptor::take() { | ||
return std::exchange(m_fd, -1); | ||
} | ||
|
||
void CFileDescriptor::reset() { | ||
if (m_fd != -1) { | ||
close(m_fd); | ||
m_fd = -1; | ||
} | ||
} | ||
|
||
CFileDescriptor CFileDescriptor::duplicate(int flags) const { | ||
if (m_fd == -1) | ||
return {}; | ||
|
||
return CFileDescriptor{fcntl(m_fd, flags, 0)}; | ||
} | ||
|
||
bool CFileDescriptor::isClosed() const { | ||
return isClosed(m_fd); | ||
} | ||
|
||
bool CFileDescriptor::isReadable() const { | ||
return isReadable(m_fd); | ||
} | ||
|
||
bool CFileDescriptor::isClosed(int fd) { | ||
pollfd pfd = { | ||
.fd = fd, | ||
.events = POLLIN, | ||
.revents = 0, | ||
}; | ||
|
||
if (poll(&pfd, 1, 0) < 0) | ||
return true; | ||
|
||
return pfd.revents & (POLLHUP | POLLERR); | ||
} | ||
|
||
bool CFileDescriptor::isReadable(int fd) { | ||
pollfd pfd = {.fd = fd, .events = POLLIN, .revents = 0}; | ||
|
||
return poll(&pfd, 1, 0) > 0 && (pfd.revents & POLLIN); | ||
} |