Я искал ответ для этот вопрос и я наткнулся на функции timerfd_create
а также epoll
в линуксе В учебнике было сказано, что epoll_ctl()
имеет epoll_data_t
член профсоюза epoll_event
структура, которая может быть использована для выполнения callback
функция на timerfd
стрельба события. Но я не уверен, как это сделать. Может кто-нибудь, пожалуйста, помогите.
Вы не можете поместить указатель на функцию обратного вызова в epoll_event
потому что он не может поместиться ни в один из следующих слотов:
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
Вместо этого вы можете сохранить таймер fd в epoll_event
и проверьте, запускает ли это:
epoll_event ev;
ev.data.fd = timerfd;
epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &ev);
С этой настройкой, то когда мы позвоним epoll_wait
мы можем проверить, если event
это было сделано для 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
}
}
В качестве альтернативы, если вы готовы отказаться от некоторой производительности, вы можете просто создать полную иерархию объектов для событий:
class EventHandler {
public:
virtual ~EventHandler() = default;
virtual int fd() const = 0;
virtual void fire() = 0;
};
Вы можете хранить EventHandler*
в ptr
:
EventHandler* handler = new TimerHandler();
ev.data.ptr = handler;
epoll_ctl(epollfd, EPOLL_CTL_ADD, handler->fd(), &ev);
И таким образом, если все мы вкладываем в epoll
является 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();
}