<commit_before>/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "ty/common.h"
#include "compat.h"
#include <sys/timerfd.h>
#include <unistd.h>
#include "ty/timer.h"
#include "ty/system.h"

struct ty_timer {
    int fd;
};

int ty_timer_new(ty_timer **rtimer)
{
    assert(rtimer);

    ty_timer *timer;
    int r;

    timer = calloc(1, sizeof(*timer));
    if (!timer) {
        r = ty_error(TY_ERROR_MEMORY, NULL);
        goto error;
    }

    timer->fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
    if (timer->fd < 0) {
        r = ty_error(TY_ERROR_SYSTEM, "timerfd_create() failed: %s", strerror(errno));
        goto error;
    }

    *rtimer = timer;
    return 0;

error:
    ty_timer_free(timer);
    return r;
}

void ty_timer_free(ty_timer *timer)
{
    if (timer)
        close(timer->fd);

    free(timer);
}

void ty_timer_get_descriptors(const ty_timer *timer, ty_descriptor_set *set, int id)
{
    assert(timer);
    assert(set);

    ty_descriptor_set_add(set, timer->fd, id);
}

int ty_timer_set(ty_timer *timer, int value, int flags)
{
    assert(timer);

    struct itimerspec ispec = {{0}};
    int r;

    if (value > 0) {
        ispec.it_value.tv_sec = (int)value / 1000;
        ispec.it_value.tv_nsec = (int)((value % 1000) * 1000000);

        if (!(flags & TY_TIMER_ONESHOT))
            ispec.it_interval = ispec.it_value;
    } else if (!value) {
        ispec.it_value.tv_nsec = 1;
    }

    r = timerfd_settime(timer->fd, 0, &ispec, NULL);
    if (r < 0)
        return ty_error(TY_ERROR_SYSTEM, "timerfd_settime() failed: %s", strerror(errno));

    return 0;
}

uint64_t ty_timer_rearm(ty_timer *timer)
{
    assert(timer);<commit_msg>Improve linux timer behavior with immediate timeout<commit_after>/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "ty/common.h"
#include "compat.h"
#include <sys/timerfd.h>
#include <unistd.h>
#include "ty/timer.h"
#include "ty/system.h"

struct ty_timer {
    int fd;
};

int ty_timer_new(ty_timer **rtimer)
{
    assert(rtimer);

    ty_timer *timer;
    int r;

    timer = calloc(1, sizeof(*timer));
    if (!timer) {
        r = ty_error(TY_ERROR_MEMORY, NULL);
        goto error;
    }

    timer->fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
    if (timer->fd < 0) {
        r = ty_error(TY_ERROR_SYSTEM, "timerfd_create() failed: %s", strerror(errno));
        goto error;
    }

    *rtimer = timer;
    return 0;

error:
    ty_timer_free(timer);
    return r;
}

void ty_timer_free(ty_timer *timer)
{
    if (timer)
        close(timer->fd);

    free(timer);
}

void ty_timer_get_descriptors(const ty_timer *timer, ty_descriptor_set *set, int id)
{
    assert(timer);
    assert(set);

    ty_descriptor_set_add(set, timer->fd, id);
}

int ty_timer_set(ty_timer *timer, int value, int flags)
{
    assert(timer);

    struct itimerspec ispec = {{0}};
    int tfd_flags = 0;
    int r;

    if (value > 0) {
        ispec.it_value.tv_sec = (int)value / 1000;
        ispec.it_value.tv_nsec = (int)((value % 1000) * 1000000);

        if (!(flags & TY_TIMER_ONESHOT))
            ispec.it_interval = ispec.it_value;
    } else if (!value) {
        tfd_flags |= TFD_TIMER_ABSTIME;
        ispec.it_value.tv_nsec = 1;
    }

    r = timerfd_settime(timer->fd, tfd_flags, &ispec, NULL);
    if (r < 0)
        return ty_error(TY_ERROR_SYSTEM, "timerfd_settime() failed: %s", strerror(errno));

    return 0;
}

uint64_t ty_timer_rearm(ty_timer *timer)
{
    assert(timer);
{'fraction_non_alphanumeric': 0.1348109517601043, 'fraction_numerical': 0.01564537157757497, 'mean_word_length': 2.930327868852459, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 19, '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': '2530593', 'n_tokens_mistral': 1514, 'n_tokens_neox': 1437, 'n_words': 342}