<commit_before>#include <vector>
#include <utility>

#include <sys/timerfd.h>
#include <time.h>

#include "dasynq-timerbase.h"
#include "dasynq-binaryheap.h"

namespace dasynq {

// We could use one timerfd per timer, but then we need to differentiate timer
// descriptors from regular file descriptors when events are reported by the loop
// mechanism so that we can correctly report a timer event or fd event.

// With a file descriptor or signal, we can use the item itself as the identifier for
// adding/removing watches. For timers, it's more complicated. When we add a timer,
// we are given a handle; we need to use this to modify the watch. We delegate the
// process of allocating a handle to a priority heap implementation (BinaryHeap).

template <class Base> class TimerFdEvents : public timer_base<Base>
{
    private:
    int timerfd_fd = -1;
    int systemtime_fd = -1;

    timer_queue_t timer_queue;
    timer_queue_t wallclock_queue;
    
    // Set the timerfd timeout to match the first timer in the queue (disable the timerfd
    // if there are no active timers).
    static void set_timer_from_queue(int fd, timer_queue_t &queue) noexcept
    {
        struct itimerspec newtime;
        if (queue.empty()) {
            newtime.it_value = {0, 0};
            newtime.it_interval = {0, 0};
        }
        else {
            newtime.it_value = queue.get_root_priority();
            newtime.it_interval = {0, 0};
        }
        timerfd_settime(fd, TFD_TIMER_ABSTIME, &newtime, nullptr);
    }
    
    void process_timer(clock_type clock, int fd, timer_queue_t &queue) noexcept
    {
        struct timespec curtime;
        switch (clock) {
        case clock_type::SYSTEM:
            clock_gettime(CLOCK_REALTIME, &curtime);
            break;
        case clock_type::MONOTONIC:
            clock_gettime(CLOCK_MONOTONIC, &curtime);
            break;
        default:
            DASYNQ_UNREACHABLE;
        }

        process_timer_queue(queue, curtime);

        // arm timerfd with timeout from head of queue
        set_timer_from_queue(fd, queue);
    }

    void setTimer(timer_handle_t & timer_id, struct timespec &timeout, struct timespec &interval,
            timer_queue_t &queue, int fd, bool enable) noexcept
    {
        auto &ts = queue.node_data(timer_id);
        ts.interval_time = interval;
        ts.expiry_count = 0;
        ts.enabled = enable;

        if (queue.is_queued(timer_id)) {
            // Already queued; alter timeout
            if (queue.set_priority(timer_id, timeout)) {
                set_timer_from_queue(fd, queue);
            }
        }
        else {
            if (queue.insert(timer_id, timeout)) {
                set_timer_from_queue(fd, queue);
            }
        }

        // TODO locking (here and everywhere)
    }<commit_msg>timerfd: minor syntax fix after recent refactorings.<commit_after>#include <vector>
#include <utility>

#include <sys/timerfd.h>
#include <time.h>

#include "dasynq-timerbase.h"
#include "dasynq-binaryheap.h"

namespace dasynq {

// We could use one timerfd per timer, but then we need to differentiate timer
// descriptors from regular file descriptors when events are reported by the loop
// mechanism so that we can correctly report a timer event or fd event.

// With a file descriptor or signal, we can use the item itself as the identifier for
// adding/removing watches. For timers, it's more complicated. When we add a timer,
// we are given a handle; we need to use this to modify the watch. We delegate the
// process of allocating a handle to a priority heap implementation (BinaryHeap).

template <class Base> class TimerFdEvents : public timer_base<Base>
{
    private:
    int timerfd_fd = -1;
    int systemtime_fd = -1;

    timer_queue_t timer_queue;
    timer_queue_t wallclock_queue;
    
    // Set the timerfd timeout to match the first timer in the queue (disable the timerfd
    // if there are no active timers).
    static void set_timer_from_queue(int fd, timer_queue_t &queue) noexcept
    {
        struct itimerspec newtime;
        if (queue.empty()) {
            newtime.it_value = {0, 0};
            newtime.it_interval = {0, 0};
        }
        else {
            newtime.it_value = queue.get_root_priority();
            newtime.it_interval = {0, 0};
        }
        timerfd_settime(fd, TFD_TIMER_ABSTIME, &newtime, nullptr);
    }
    
    void process_timer(clock_type clock, int fd, timer_queue_t &queue) noexcept
    {
        struct timespec curtime;
        switch (clock) {
        case clock_type::SYSTEM:
            clock_gettime(CLOCK_REALTIME, &curtime);
            break;
        case clock_type::MONOTONIC:
            clock_gettime(CLOCK_MONOTONIC, &curtime);
            break;
        default:
            DASYNQ_UNREACHABLE;
        }

        timer_base<Base>::process_timer_queue(queue, curtime);

        // arm timerfd with timeout from head of queue
        set_timer_from_queue(fd, queue);
    }

    void setTimer(timer_handle_t & timer_id, struct timespec &timeout, struct timespec &interval,
            timer_queue_t &queue, int fd, bool enable) noexcept
    {
        auto &ts = queue.node_data(timer_id);
        ts.interval_time = interval;
        ts.expiry_count = 0;
        ts.enabled = enable;

        if (queue.is_queued(timer_id)) {
            // Already queued; alter timeout
            if (queue.set_priority(timer_id, timeout)) {
                set_timer_from_queue(fd, queue);
            }
        }
        else {
            if (queue.insert(timer_id, timeout)) {
                set_timer_from_queue(fd, queue);
            }
        }

        // TODO locking (here and everywhere)
    }
{'fraction_non_alphanumeric': 0.083844939484301, 'fraction_numerical': 0.003157340817400456, 'mean_word_length': 2.346244131455399, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '458460', 'n_tokens_mistral': 1725, 'n_tokens_neox': 1681, 'n_words': 526}