问题
I have been searching an answer for this question and I came across the functions timerfd_create and epollin 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();
}
来源:https://stackoverflow.com/questions/28446631/how-to-pass-a-callback-function-pointer-to-epoll-event-structure-in-c