简单的定时器事件循环

Simple timer event loop

用例

我正在编写一个需要多个计时器的 C 程序。我首先编写了一个快速原型,它为每个计时器启动了一个 pthread。只是一个带有 sleep 命令的简单 while 循环,因为 1 秒分辨率就足够了。

但是如果有 10 个以上的定时器,它的效率就不是很高,也不是生产级的代码质量。因此我想使用事件循环。我已经多次阅读有关 libuv 的文章,并想尝试一下。

所以我的想法很简单。有 1 个计时器线程运行计时器事件循环并动态添加和删除计时器。定时器是非常简单的倒计时定时器,当它们达到 0 时执行函数指针,并且可以取消。所以不需要重复。

问题

我认为这里真正的问题是文档,libuv 文档对于如何实现这一点并不是很清楚。所以我认为我目前拥有的代码是垃圾。让我带您了解一下。

在我的程序开始时,我使用以下入口点启动一个 phtread:

static void* _uv_loop_thread_entry_point(void *args)
{
    /* Initialize the timer event loop */
    timer_event_loop = malloc(sizeof(uv_loop_t));
    uv_loop_init(timer_event_loop);

    /* Keep running the eventloop */
    while(uv_run(timer_event_loop, UV_RUN_DEFAULT) == 0) {
        /* Wait 1 second for new handles */
        sleep(1);
    };

    /* The timer event loop has stopped, free all resources */
    uv_loop_close(timer_event_loop);
    free(timer_event_loop);

    return NULL;
}

每当我想使用计时器时,我都会执行以下操作:

uv_timer_init(timer_event_loop, uv_timer);
uv_timer_start(uv_timer, timeout_ms, ??);

现在我有几个问题:

  1. 如何不重复使用定时器
  2. 这个定时器的回调函数在哪里设置
  3. 我怎么知道这个计时器还剩多少时间

在这个问题上我真的需要一些帮助。

更新 1

好的,我正在取得一些进展,基本上可以了。 libuv 事件循环在单独的线程中运行。并且已经回答了我的一些问题:

  1. uv_timer_start 中的最后一个参数为 0 时,计时器将不会重复。

  2. 定时器超时事件的回调是uv_timer_start

  3. 的第二个参数

我还不知道第三个问题的最佳答案。但是现在我会记录我的计时器开始的时间和当前时间,并计算两者之间的差异。我然后从计时器的总时间中减去差异,以了解计时器结束之前需要多长时间。

我仍然想知道我的 uv_run 实施是否正确。

亲切的问候, 大安

您正在玩未定义的行为领域。 libuv 不是线程安全的 see the docs here 因此,虽然 运行 一个线程中的循环是可以的,但在另一个线程中创建一个计时器而循环是 运行 则不是。

您仍然可以通过使用 uv_async_t 句柄和信号量来完成此操作:uv_async_send 是线程安全的,因此您可以从外部调用它,停止循环并向信号量发出信号。调用线程将等待信号量发出信号。此时循环停止,那么新建一个timer并添加就可以了。

没有API知道计时器还剩多少时间。

如果你只需要一个循环来控制一些定时器,那么 libuv 可能就太过分了。如果你在 Linux,你可以使用 timerfd,或者一个只在 select 之上做定时器的手工构建的事件循环。