LinuxForum.Fans
Тема

Аналог таймера TimeSetEvent

Автор: dedm0zaj 9 сообщений 2612 просмотров
#206902

есть ли под linux аналог виндового таймера TimeSetEvent? а именно высокоточный таймер, выделяющий для наших нужд отдельный поток

#206908

Поток - это одно, таймер - другое. Посмотрите
man setitimer
man sigaction
man pthread_create

Пётр.

#206909

как вариант setitimer() только он не создаёт поток. и не знаю, на сколько он на самом деле точен...

#212631

усё. написал свой таймер :З вопрос считаю закрытым

#212643

dedm0zaj, поделитесь решением то?

#212713
dedm0zaj написал:
усё. написал свой таймер :З вопрос считаю закрытым

А напрасно wink ... поскольку он будет заведомо хуже реализации из POSIX API.

#212992

Fat-Zer,
я не гуру, а только любитель, так что критику не приму

c_timer.h

Показать
text

#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

Показать
text

#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 мсек, чтобы не нагружать проц } }

пример использования, в котором один таймер считает раз в секунду количество тиков другого таймера

Показать
text

#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;

}

#213002
dedm0zaj написал:
я не гуру, а только любитель, так что критику не приму

всё равно покритикую, а принимать/не принимать дело ваше =)
в общем то неплохо

dedm0zaj написал:
reinterpret_cast

1) тут статика хватило бы...
2) действительно косо выглядит запуск нового потока, но тут решение - только отдельную абстракцию для потока надстраивать.

ну и на будущее: не хватает корректной остановки таймера, а то при смерти c_timer может произойти страшное.
ещё как вариант: спать можно и подольше... и так и так нет ни каких гарантий, что нас вовремя разбудят.

#213013
Fat-Zer написал:

2) действительно косо выглядит запуск нового потока, но тут решение - только отдельную абстракцию для потока надстраивать.

Создание нового потока в конструкторе объекта - это то, что первое просится для "красивого" решения, и то, что потом всегда оказывается плохим решением. Это близко к тому, что в Oberon называется "активный объект". Вот это место:

text

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(), который запускает поток и, самое главное, может возвратить код результата.

Войдите или зарегистрируйтесь, чтобы ответить.