#pragma once
#if defined(__linux__) && !defined(__ANDROID__)
#define FOLLY_HAVE_TIMERFD
#endif
#include <folly/io/async/EventBase.h>
#ifdef FOLLY_HAVE_TIMERFD
#include <folly/io/async/EventHandler.h>
#else
#include <folly/io/async/AsyncTimeout.h>
#endif
#include <chrono>
namespace folly {
#ifdef FOLLY_HAVE_TIMERFD
class TimerFD : public folly::EventHandler,
public folly::EventReadCallback,
public DelayedDestruction {
public:
explicit TimerFD(folly::EventBase* eventBase);
~TimerFD() override;
virtual void onTimeout() noexcept = 0;
void schedule(std::chrono::microseconds timeout);
void cancel();
void handlerReady(uint16_t events) noexcept override;
folly::EventReadCallback::IoVec* allocateData() noexcept override {
auto* ret = ioVecPtr_.release();
return (ret ? ret : new IoVec(this));
}
protected:
void close();
private:
struct IoVec : public folly::EventReadCallback::IoVec {
IoVec() = delete;
~IoVec() override = default;
explicit IoVec(TimerFD* eventFd) {
arg_ = eventFd;
freeFunc_ = IoVec::free;
cbFunc_ = IoVec::cb;
data_.iov_base = &timerData_;
data_.iov_len = sizeof(timerData_);
}
static void free(EventReadCallback::IoVec* ioVec) { delete ioVec; }
static void cb(EventReadCallback::IoVec* ioVec, int res) {
reinterpret_cast<TimerFD*>(ioVec->arg_)
->eventReadCallback(reinterpret_cast<IoVec*>(ioVec), res);
}
uint64_t timerData_{0};
};
void eventReadCallback(IoVec* ioVec, int res);
std::unique_ptr<IoVec> ioVecPtr_;
TimerFD(folly::EventBase* eventBase, int fd);
static int createTimerFd();
bool setTimer(std::chrono::microseconds useconds);
int fd_{-1};
};
#else
class TimerFD { … };
#endif
}