Какова цель таймера POSIX без обработчика сигнала? - PullRequest
3 голосов
/ 23 декабря 2019
void EventProviderLinux::waitForEvents (EventLoopTime wait_time)
{
    AIPSTACK_ASSERT(m_cur_epoll_event == m_num_epoll_events);

    namespace chrono = std::chrono;
    using Period = EventLoopTime::period;
    using Rep = EventLoopTime::rep;
    using SecType = decltype(itimerspec().it_value.tv_sec);
    using NsecType = decltype(itimerspec().it_value.tv_nsec);
    using NsecDuration = chrono::duration<NsecType, std::nano>;

    static_assert(Period::num == 1);
    static_assert(Period::den <= std::nano::den);
    static_assert(std::is_signed_v<Rep>);
    static_assert(std::is_signed_v<SecType>);
    static_assert(TypeMax<Rep> / Period::den <= TypeMax<SecType>);
    static_assert(TypeMin<Rep> / Period::den >= TypeMin<SecType> + 1);

    if (wait_time != m_timerfd_time || m_force_timerfd_update) {
        m_force_timerfd_update = true;

        EventLoopTime::duration time_dur = wait_time.time_since_epoch();

        SecType sec = time_dur.count() / Period::den;
        Rep subsec = time_dur.count() % Period::den;
        if (subsec < 0) {
            sec--;
            subsec += Period::den;
        }

        struct itimerspec itspec = {};
        itspec.it_value.tv_sec = sec;
        itspec.it_value.tv_nsec =
            chrono::duration_cast<NsecDuration>(EventLoopTime::duration(subsec)).count();

        // Prevent accidentally disarming the timerfd.
        if (itspec.it_value.tv_sec == 0 && itspec.it_value.tv_nsec == 0) {
            itspec.it_value.tv_nsec = 1;
        }

        if (::timerfd_settime(*m_timer_fd, TFD_TIMER_ABSTIME, &itspec, nullptr) < 0) {
            throw std::runtime_error(formatString(
                "EventProviderLinux: timerfd_settime failed, err=%d", errno));
        }

        m_timerfd_time = wait_time;
        m_force_timerfd_update = false;
    }

    int wait_res;
    while (true) {
        wait_res = ::epoll_wait(*m_epoll_fd, m_epoll_events, MaxEpollEvents, -1);
        if (AIPSTACK_LIKELY(wait_res >= 0)) {
            break;
        }

        int err = errno;
        if (err != EINTR) {
            throw std::runtime_error(formatString(
                "EventProviderLinux: epoll_wait failed, err=%d", err));
        }
    }

    AIPSTACK_ASSERT(wait_res <= MaxEpollEvents);

    m_cur_epoll_event = 0;
    m_num_epoll_events = wait_res;
}

Эта функция должна блокироваться до тех пор, пока на m_epoll_fd не произойдут события. Вы можете видеть, что есть таймер m_timer_fd, который создан, но никогда не получает обработчик. Какой смысл запускать таймер без какого-либо обработчика?

Кроме того, я больше нигде не использую этот таймер. Поскольку он создан локально, в его классе нет использования. Он должен иметь локальное использование.

Функция взята из здесь

1 Ответ

1 голос
/ 23 декабря 2019

Со страницы руководства timerfd_create (выделено мной):

Эти системные вызовы создают и работают с таймером, который доставляет уведомления об истечении таймера через дескриптор файла. Они предоставляют альтернативу использованию setitimer (2) или timer_create (2), с тем преимуществом, что файловый дескриптор может отслеживаться с помощью select (2), poll (2) и epoll (7) .

Из исходного исходного кода:

control_epoll(EPOLL_CTL_ADD, *m_timer_fd, EPOLLIN, &m_timer_fd);

Из приведенного выше видно, что события таймера были настроены для мониторинга с помощью epoll.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...