2016-08-13 8 views
1

UseCaseПростой таймер цикла событий

Я пишу программу C, которая требует несколько таймеров. Сначала я написал быстрый прототип, который запустил pthread для каждого таймера. Просто просто while -loop с командой sleep, потому что достаточно 1 секунды разрешения.

Но с более чем 10 таймерами это не очень эффективное и качественное качество кода. Поэтому я хотел использовать eventloop. Я несколько раз читал о libuv и думал попробовать.

Так что моя идея была простой. Имейте 1 таймерную нить, которая запускает таймер eventloop и добавляет и удаляет таймеры на лету. Таймеры - очень простые таймеры обратного отсчета, которые выполняют указатель функции, когда они достигают 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. Как я могу знать, сколько времени осталось в этом таймере

я могу реально использовать некоторую помощь по этому вопросу.

Update 1

Хорошо, я некоторый прогресс, и он в основном работает. Цикл событий libuv выполняется в отдельном потоке. И уже ответить на некоторые из моих вопросов:

  1. Когда последний аргумент в uv_timer_start равен 0, то таймер не будет повторяться.

  2. обратный вызов для события тайма-аута таймера является вторым аргументом uv_timer_start

Я пока не знаю, лучший ответ на мой третий вопрос. Но на данный момент я отслеживаю время, когда мой таймер запустился, и текущее время, и примите к сведению. Я чем-то вычтую разницу от общего времени таймера, чтобы узнать, сколько времени потребуется, прежде чем таймер закончится.

Я все еще хотел бы знать, правильно ли выполнена моя uv_run.

С наилучшими пожеланиями, Даан

+2

Вы говорите о pthreads, которые очень хорошо документированы, но используют libuv. Таким образом, вы не используете pthreads в первую очередь. Используйте pthreads, и ваша проблема с документацией будет решена. – Olaf

+0

Как определяется 'timer_event_loop'? – alk

+0

Это указатель в верхней части файла C. –

ответ

2

Вы играете в неопределенной территории поведения. libuv не является потокобезопасным see the docs here Таким образом, при запуске цикла в потоке нормально, создание таймера в другом потоке во время работы цикла не выполняется.

Вы все еще можете сделать это с помощью дескриптора uv_async_t и семафора: uv_async_send является потокобезопасным, поэтому вы можете называть его снаружи, останавливать цикл и сигнализировать семафор. Вызывающий поток будет ждать, пока не будет сигнализирован семафор. На этом этапе цикл остановлен, поэтому можно создать новый таймер и добавить его.

Нет никакого API, чтобы узнать, сколько времени осталось от таймера.

Если все, что вам нужно, это петля для управления некоторыми таймерами libuv, возможно, будет излишним. Вы можете использовать timerfd, если вы работаете в Linux, или ручной цикл событий, который, например, выполняет только таймеры.

+0

Большое спасибо Я написал eventloop с epoll и timerfd, теперь он потокобезопасен и работает без накладных ресурсов libuv. –