I have been searching an answer for this question and I came across the functions timerfd_create
and epoll
in Linux. In a tutorial it was said that epoll_ctl()
has an epoll_data_t
union member of the epoll_event
structure which can be used to execute a callback
function on a timerfd
event firing. But I am not sure on how to do it. Can anyone please help.
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
回答1:
You can't put a callback function pointer into epoll_event
because it can't fit in any of these slots:
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
What you could do instead is store the timer fd in the epoll_event
and check to see if that's the one that fires:
epoll_event ev;
ev.data.fd = timerfd;
epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &ev);
With that setup, then when we call epoll_wait
, we can check to see if the event
that fired was for timerfd
:
int n = epoll_wait (epollfd, events , num_events, -1 );
for (int i = 0; i < n; ++i) {
if (events[i].data.fd == timerfd) {
handle_timer_callback();
}
else {
// something else
}
}
Alternatively, if you're open to giving up some performance, you can just create a complete object hierarchy for events:
class EventHandler {
public:
virtual ~EventHandler() = default;
virtual int fd() const = 0;
virtual void fire() = 0;
};
You can store an EventHandler*
into ptr
:
EventHandler* handler = new TimerHandler();
ev.data.ptr = handler;
epoll_ctl(epollfd, EPOLL_CTL_ADD, handler->fd(), &ev);
And that way, if everything we put into epoll
is an EventHandler
:
int n = epoll_wait (epollfd, events , num_events, -1 );
for (int i = 0; i < n; ++i) {
static_cast<EventHandler*>(events[i].data.ptr)->fire();
}