#pragma once
#include <folly/io/async/Epoll.h>
#if FOLLY_HAS_EPOLL
#include <chrono>
#include <map>
#include <optional>
#include <set>
#include <vector>
#include <folly/container/IntrusiveHeap.h>
#include <folly/io/async/EventBaseBackendBase.h>
namespace folly {
class EpollBackend : public EventBaseBackendBase {
public:
struct Options {
size_t numLoopEvents{128};
Options& setNumLoopEvents(size_t val) {
numLoopEvents = val;
return *this;
}
};
explicit EpollBackend(Options options);
~EpollBackend() override;
int getEpollFd() const { return epollFd_; }
int getPollableFd() const override { return epollFd_; }
event_base* getEventBase() override { return nullptr; }
int eb_event_base_loop(int flags) override;
int eb_event_base_loopbreak() override;
int eb_event_add(Event& event, const struct timeval* timeout) override;
int eb_event_del(Event& event) override;
bool eb_event_active(Event&, int) override { return false; }
bool setEdgeTriggered(Event& event) override;
private:
struct TimerInfo;
class SocketPair {
public:
SocketPair();
SocketPair(const SocketPair&) = delete;
SocketPair& operator=(const SocketPair&) = delete;
~SocketPair();
int readFd() const { return fds_[1]; }
int writeFd() const { return fds_[0]; }
private:
std::array<int, 2> fds_{{-1, -1}};
};
void updateTimerFd();
void addTimerEvent(Event& event, const struct timeval* timeout);
int removeTimerEvent(Event& event);
void processTimers();
void setProcessTimers();
void addSignalEvent(Event& event);
int removeSignalEvent(Event& event);
void processSignals();
const Options options_;
int epollFd_{-1};
size_t numInsertedEvents_{0};
size_t numInternalEvents_{0};
bool loopBreak_{false};
std::vector<struct epoll_event> events_;
int timerFd_{-1};
std::optional<std::chrono::steady_clock::time_point> timerFdExpiration_;
IntrusiveHeap<TimerInfo> timers_;
SocketPair signalFds_;
std::map<int, std::set<struct event*>> signals_;
};
}
#endif