Files
BloomPatched/src/Helpers/EventNotifier.hpp

83 lines
2.5 KiB
C++

#pragma once
#include <sys/eventfd.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <atomic>
#include "src/Exceptions/Exception.hpp"
namespace Bloom
{
/**
* The EventNotifier class provides a means to interrupt a thread that is blocked by an IO call.
*
* It's implementation is rather simple: It uses a Linux event file descriptor (sys/eventfd.h), which should be used
* along side epoll() to interrupt a blocking call that is waiting on the epoll file descriptor.
*
* The EventListener can hold an instance to EventNotifier, where it will invoke EventNotifier::notify() everytime
* a new event is registered on the listener.
*
* @TODO: This could do with some cleaning. It's a bit hacky. Also, maybe add the ability to register the event
* file descriptor to an epoll instance within a public method (instead of relying on the caller to do this
* themselves via EventNotifier::getFileDescriptor()).
*/
class EventNotifier
{
private:
int fileDescriptor = -1;
std::atomic<bool> initialised = false;
void init() {
this->fileDescriptor = ::eventfd(0, EFD_NONBLOCK);
if (this->fileDescriptor < -1) {
throw Exceptions::Exception("Failed to create new eventfd object - error number: "
+ std::to_string(errno));
}
this->initialised = true;
}
void close() {
::close(this->fileDescriptor);
this->initialised = false;
}
public:
EventNotifier() {
this->init();
};
~EventNotifier() {
if (this->initialised) {
this->close();
}
}
int getFileDescriptor() const {
return this->fileDescriptor;
}
bool isInitialised() {
return this->initialised;
}
void notify() {
if (::eventfd_write(this->fileDescriptor, 1) < 0) {
throw Exceptions::Exception("Failed to increment eventfd counter - error number: "
+ std::to_string(errno));
}
}
void clear() {
eventfd_t counter;
if (::eventfd_read(this->fileDescriptor, &counter) < 0 && errno != EAGAIN) {
throw Exceptions::Exception("Failed to clear EventNotifier object - eventfd_read failed - "
"error number: " + std::to_string(errno));
}
}
};
}