Где в Linux взять таймер вызывающий события?

179
27 апреля 2018, 14:10

Мне понадобился таймер который по истечению какого то времени вызывает событие, например std::function. В Win32 API и в C# я очень часто использовал такие таймеры, но тут сходу их найти не смог -_-. Была идея реализовать такой класс самому запустив поток и всё время проверяя текущее время, но в моём проекте очень важна производительность и мне кажется это не самым разумным решением. Из сторонних библиотек я могу использовать только boost (я знаю, что подобный таймер есть в qt, но его я использовать никак не могу). Подскажите пожалуйста где мне взять в Linux дешёвый с точки зрения производительности таймер на события которого можно подписываться функторами std::function<___>.

Answer 1

В Linux есть posix функция

#include <sys/time.h>
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue); 

по обнулению таймера в программу приходит сигнал SIGALRM который можно обработать вашей функцией которую ставят на обработчик сигналов используя функцию

#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); 
Answer 2

Камрад @yaroslav дал точный и правильный ответ. Но этот вариант достаточно низкоуровневый. Хотя и не требующий дополнительных библиотек со стороны. Но и обладающий рядом нюансов, связанных с контекстом обработки сигналов (изучите этот вопрос, если будете использовать этот метод).

Вы можете воспользоваться таймерами из libev, допустим.

Или воспользоваться Asio (в виде отдельной самодостаточно библиотеки или из состава Boost). Второе особенно актуально при использовании C++11/14/17/etc.

А если будете работать с графикой через Gtk+/Qt, то у них есть свой функционал, при помощи которого можно решить вашу задачу. ЕМНИП и в glib (которому графига и не нужна) есть что-то подобное.

Answer 3

Можно использовать libevent

#include <event.h>
#include <sys/time.h>
#include <iostream>
void On_Timer(int fd, short id, void * param) noexcept
{
    ::std::cout << "Time" << ::std::endl;
    auto const p_event{static_cast<struct ::event *>(param)};
    ::event_del(p_event); // отписываем событие, циклу больше нечего будет делать и он вернет управление в main
}
int main(int argc, const char* argv[])
{
    auto const p_event_base{::event_base_new()};
    auto const p_event{::event_new(p_event_base, -1, EV_PERSIST, &::On_Timer, ::event_self_cbarg())};
    struct ::timeval tv{1, 0}; // 1 секунда
    ::evtimer_add(p_event, &tv); // подписываем событие
    ::event_dispatch(); // запускаем цикл
    ::event_free(p_event);
    ::event_base_free(p_event_base);
    return 0;
}
Answer 4

Можно использовать функцию int timer_create(clockid_t clockid, struct sigevent *sevp, timer_t *timerid);.

В структуре sigevent есть поле void (*sigev_notify_function) (union sigval); которое может содержать адрес функции, вызываемой в отдельном потоке при срабатывании таймера.

READ ALSO
Оформить в виде класса

Оформить в виде класса

Помогите переделать програмку, чтобы она была оформлена как 3 файла - maincpp, class

172
Как сделать для Combobox SCROLL?

Как сделать для Combobox SCROLL?

Мне нужно сделать для Combobox SCROLL, но я не нашелДля едита есть ES_AUTOVSCROLL, а от для Combobox нету

162
Отключение звука в WebView JavaFX

Отключение звука в WebView JavaFX

Всем привет, делаю лаунчер для своего проектаВ рамках проекта необходимо отключить звук при работе самого лаунчера или же при загрузке страницы...

164
Как создать игру с лобби?

Как создать игру с лобби?

У меня есть бот для бесед вк написанный на nodejsКак можно реализовать систему лобби

178