Мне понадобился таймер который по истечению какого то времени вызывает событие, например std::function. В Win32 API и в C# я очень часто использовал такие таймеры, но тут сходу их найти не смог -_-. Была идея реализовать такой класс самому запустив поток и всё время проверяя текущее время, но в моём проекте очень важна производительность и мне кажется это не самым разумным решением. Из сторонних библиотек я могу использовать только boost (я знаю, что подобный таймер есть в qt, но его я использовать никак не могу). Подскажите пожалуйста где мне взять в Linux дешёвый с точки зрения производительности таймер на события которого можно подписываться функторами std::function<___>.
В 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);
Камрад @yaroslav дал точный и правильный ответ. Но этот вариант достаточно низкоуровневый. Хотя и не требующий дополнительных библиотек со стороны. Но и обладающий рядом нюансов, связанных с контекстом обработки сигналов (изучите этот вопрос, если будете использовать этот метод).
Вы можете воспользоваться таймерами из libev, допустим.
Или воспользоваться Asio (в виде отдельной самодостаточно библиотеки или из состава Boost). Второе особенно актуально при использовании C++11/14/17/etc.
А если будете работать с графикой через Gtk+/Qt, то у них есть свой функционал, при помощи которого можно решить вашу задачу. ЕМНИП и в glib (которому графига и не нужна) есть что-то подобное.
Можно использовать 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;
}
Можно использовать функцию int timer_create(clockid_t clockid, struct sigevent *sevp, timer_t *timerid);.
В структуре sigevent есть поле void (*sigev_notify_function) (union sigval); которое может содержать адрес функции, вызываемой в отдельном потоке при срабатывании таймера.
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости