есть ли под linux аналог виндового таймера TimeSetEvent? а именно высокоточный таймер, выделяющий для наших нужд отдельный поток
Аналог таймера TimeSetEvent
Поток - это одно, таймер - другое. Посмотрите
man setitimer
man sigaction
man pthread_create
Пётр.
как вариант setitimer() только он не создаёт поток. и не знаю, на сколько он на самом деле точен...
усё. написал свой таймер :З вопрос считаю закрытым
dedm0zaj, поделитесь решением то?
усё. написал свой таймер :З вопрос считаю закрытым
А напрасно wink ... поскольку он будет заведомо хуже реализации из POSIX API.
Fat-Zer,
я не гуру, а только любитель, так что критику не приму
c_timer.h
Показать
#ifndef C_TIMER_H_INCLUDED
#define C_TIMER_H_INCLUDED
#include <time.h>
#include <pthread.h>
class c_timer
{
private:
int step_t;
void (*timer_make)();
void thread_make();
static void* thread_func(void *);
public:
c_timer(int, void ());
};
#endif // C_TIMER_H_INCLUDED
c_timer.cpp
Показать
#include "c_timer.h"
c_timer::c_timer(int msek, void (*ati)())
{
if (msek<1) msek = 1;
step_t = msek*10; //шаг таймера, мс*10
pthread_t thread1;
timer_make = ati; //указатель на адрес функции с выполнением нужных нам действий при тике таймера
pthread_create(&thread1, NULL, thread_func, this); //создание потока
}
void* c_timer::thread_func(void *arg)
{
c_timer* p = reinterpret_cast<c_timer*>(arg); //поскольку динамический метод нельзя передать в качестве функции потока, то приходится так изощряться
p->thread_make();
return NULL;
}
void c_timer::thread_make() //собственно создание тика таймера
{
timespec req;
req.tv_sec = 0;
req.tv_nsec = 1000000L;
int t1, tt;
timespec req2;
clockid_t clid = CLOCK_MONOTONIC;
clock_gettime(clid, &req2);
tt = req2.tv_sec*10000 + req2.tv_nsec/100000 + step_t;
while (1>0){
clock_gettime(clid, &req2);
t1 = req2.tv_sec*10000 + req2.tv_nsec/100000;
if (t1>tt) {
tt = tt + step_t;
timer_make(); //выполнение наших действий при тике
}
nanosleep(&req, (struct timespec *)NULL); //задержка в 1 мсек, чтобы не нагружать проц
}
}
пример использования, в котором один таймер считает раз в секунду количество тиков другого таймера
Показать
#include <iostream>
#include "c_timer.h"
using namespace std;
int a,b;
void a1()
{
a++;
}
void a2()
{
cout << a << " тиков в секунду таймера а1" << endl;
a = 0;
}
int main()
{
c_timer tim(10,a1);
c_timer tim2(1000,a2);
cin >> b; //для остановки основного потока, чтобы программа не завершилась заранее
return 0;
}
я не гуру, а только любитель, так что критику не приму
всё равно покритикую, а принимать/не принимать дело ваше =)
в общем то неплохо
reinterpret_cast
1) тут статика хватило бы...
2) действительно косо выглядит запуск нового потока, но тут решение - только отдельную абстракцию для потока надстраивать.
ну и на будущее: не хватает корректной остановки таймера, а то при смерти c_timer может произойти страшное.
ещё как вариант: спать можно и подольше... и так и так нет ни каких гарантий, что нас вовремя разбудят.
2) действительно косо выглядит запуск нового потока, но тут решение - только отдельную абстракцию для потока надстраивать.
Создание нового потока в конструкторе объекта - это то, что первое просится для "красивого" решения, и то, что потом всегда оказывается плохим решением. Это близко к тому, что в Oberon называется "активный объект". Вот это место:
c_timer::c_timer(int msek, void (*ati)())
{
if (msek<1) msek = 1;
step_t = msek*10; //шаг таймера, мс*10
pthread_t thread1;
timer_make = ati; //указатель на адрес функции с выполнением нужных нам действий при тике таймера
pthread_create(&thread1, NULL, thread_func, this); //создание потока
}
А что, если у вас поток, по каким-то причинам, не стартует?
Объект есть, а потока нет ... вы дальше обращаетесь к методам класса в предположении, что там поток, а там ... пс-с-с-с... :(
Это ещё из Н.Вирта опытов с Modula-2/Oberon лучше реализовывать так, что:
- конструктор есть конструктор...
- а класс имеет метод Run(), который запускает поток и, самое главное, может возвратить код результата.