Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 29.05.2014, 18:11   #1
gunsoy
Форумчанин
 
Регистрация: 30.12.2010
Сообщений: 280
Вопрос Проблема с таймером alarm() signal()

Здравствуйте.

Нужен был таймер, который бы запускал нужную функцию каждые 5 секунд (система Ubuntu). Выбрал alarm()
Возникла проблема с Linux-функцией signal.

Код:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <signal.h>
#include <sys/time.h>

void signal_handler(int sigma)
{
    std::cout << "\nTrueAlarm";
    alarm(5);
}

int main()
{
    alarm(5);
    signal(SIGALRM, signal_handler);
    while(true)
    {
    }
    return 0;
}
Вот этот код рабочий, но если я делаю функцию signal_handler, методом класса

void WorkerThread::signal_handler(int sigma)
{
std::cout << "\nTrueAlarm";
alarm(5);
}

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

Подскажите пожалуйста, можно ли исправить проблему? Есть ли аналог функции signal, с возможностью вызова метода класса или с возможностью передать ссылку на класс в качестве аргумента?

Спасибо за внимание.
gunsoy вне форума Ответить с цитированием
Старый 29.05.2014, 23:38   #2
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

пример использования:
http://rextester.com/FDWPA92795

//хэадер
Код:
#pragma once

#include <functional>
#include <stdint.h>
#include <chrono>

namespace tools
{
    struct Timer
    {
        //если функция-будильник вернет true, то таймер перезапустится
        typedef ::std::function<bool()> EventWakeUp;

        typedef std::chrono::high_resolution_clock Clock;

        typedef uint64_t    MicroSeconds;
        typedef double      Seconds;

    public:
       ~Timer();

        //укажите :
        // --- время, через которое должен сработать будильник,
        // --- функтор, который должен будет запуститься в момент срабатывания будильника,
        // --- числовой идентификатор таймера (если он вам нужен).
        //Имейте ввиду, если функтор будильника вернет true, то будильник снова перезапустится.  
        Timer( const Seconds      delay, const EventWakeUp& wakeup=EventWakeUp(), const int id=0 );
        Timer( const MicroSeconds delay, const EventWakeUp& wakeup=EventWakeUp(), const int id=0 );
        Timer(const int id=0);

        //перезапуск будильника, с возможностью указать другой функутор
        void Restart(const Seconds delay,      const EventWakeUp& wakeup=EventWakeUp() );
        void Restart(const MicroSeconds delay, const EventWakeUp& wakeup=EventWakeUp() );

        int GetID()const{ return mId;}
    public:
        //вернет промежуток времени с момента последнего запуска этого же метода
        static MicroSeconds QuantMS();
        static Seconds QuantS();

        //спать все время в отдельном потоке, а потом пробудиться и вызвать функцию-будильник
        static void BackGround(const Timer::Seconds delay, const Timer::EventWakeUp& wakeup=EventWakeUp());

        //усыпить текущий поток, а потом пробудиться и вызвать функцию-будильник
        static void Sleep(const Timer::Seconds delay, const Timer::EventWakeUp& wakeup=EventWakeUp());
    public:
        //засечь время.
        void Mark();

        //через какое время сработает будильник
        MicroSeconds RemainingMS()const;
        Seconds RemainingS()const;

        //сколько времени уже прошло с момента запуска будильника
        MicroSeconds ElapsedMS()const;
        Seconds ElapsedS()const;

        //Приводит механизм будильника в действие
        //вернет true, если будильник ещё не сработал. 
        //В момент срабатывания запустит функцию-будильник
        bool TickTock();
    private:
        int mId; 
        MicroSeconds        mDelay; 
        EventWakeUp         mEvent;
        Clock::time_point   mMark; 
    };

}//namespace tools

Последний раз редактировалось _Bers; 29.05.2014 в 23:58.
_Bers вне форума Ответить с цитированием
Старый 29.05.2014, 23:39   #3
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

реализация:
Код:
#include "tools/timer.h"

namespace tools
{

    namespace{

        typedef Timer::EventWakeUp  EventWakeUp;
        typedef Timer::MicroSeconds MicroSeconds;
        typedef Timer::Seconds      Seconds;
        typedef Timer::Clock        Clock;
        
        typedef std::chrono::microseconds MSec;
        typedef std::chrono::seconds      Sec;

        template<class T> T DeltaTime(Clock::time_point& last)
        {
            const Clock::time_point now = Clock::now();
            const auto result = std::chrono::duration_cast<T>(now - last);
            last = now;
            return result;
        }

        Clock::time_point& Quant()
        {
            static Clock::time_point quant;
            return quant;
        }

        void Sleeping(const MicroSeconds pause, const EventWakeUp& wakeup)
        {
            do
            {
                std::this_thread::sleep_for(std::chrono::microseconds(pause) );

            }while ( wakeup && wakeup() );
        }

    }//namespace

    MicroSeconds Timer::QuantMS() { return DeltaTime<MSec>(Quant()).count();         }
    Seconds Timer::QuantS()       { return (Seconds)DeltaTime<Sec>(Quant()).count(); }

    Timer::Timer(const int id):mId(id){}

    Timer::Timer( const Seconds delay, const EventWakeUp& wakeup, const int id):mId(id)
    {
        Restart(delay,wakeup);
    }

    Timer::Timer( const MicroSeconds delay, const EventWakeUp& wakeup, const int id):mId(id)
    {
        Restart(delay,wakeup);
    }
    
    

    void Timer::Restart(const Seconds delay, const EventWakeUp& wakeup)
    {
        mDelay = static_cast<MicroSeconds>(delay*1000000);
        mEvent = wakeup;
        Mark();
    }
    void Timer::Restart(const MicroSeconds delay,const EventWakeUp& wakeup)
    {
        mDelay = delay;
        mEvent = wakeup;
        Mark();
    }

    Timer::~Timer(){}


    void Timer::Mark() { mMark = Clock::now(); }

    MicroSeconds Timer::ElapsedMS()const
    {
        return std::chrono::duration_cast<MSec>(Clock::now() - mMark).count();
    }
    Seconds Timer::ElapsedS()const
    {
        return static_cast<Seconds>( ElapsedMS()/1000000.0 );
    }

    MicroSeconds Timer::RemainingMS()const
    {
        if(mMark == Clock::time_point() || mDelay==0) 
            return 0;
        
        const auto elapsed = ElapsedMS(); 
        return (mDelay<=elapsed)? 0: mDelay-elapsed;
    }
    Seconds Timer::RemainingS()const
    {
        if(mMark == Clock::time_point() || mDelay==0) 
            return 0;

        const auto elapsed = ElapsedMS(); 
        return (mDelay<=elapsed)? 0.0: (mDelay-elapsed)/1000000.0;
    }

    bool Timer::TickTock()
    {
        if(mMark == Clock::time_point())
            return false;

        if(RemainingMS()!=0)
            return true;

        if(mEvent && mEvent())
            Mark();
        else
            mMark=Clock::time_point();
        
        return false;
    }


//-----------------------------------------------------------
    void Timer::BackGround(const Timer::Seconds delay, const Timer::EventWakeUp& wakeup)
    {
        const MicroSeconds pause = static_cast<MicroSeconds>(delay*1000000);
        auto lambda = [pause, wakeup ]() 
        {
            Sleeping(pause, wakeup); 
        };
        std::thread(lambda).detach();
    }

    void Timer::Sleep(const Timer::Seconds delay, const Timer::EventWakeUp& wakeup)
    {
        const auto pause = static_cast<MicroSeconds>(delay*1000000);
        Sleeping(pause, wakeup);
    }
    
}//namespace tools
_Bers вне форума Ответить с цитированием
Старый 29.05.2014, 23:50   #4
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

делделделделделделделделдел

Последний раз редактировалось _Bers; 30.05.2014 в 00:34.
_Bers вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Проблема с сис таймером Lauri Общие вопросы Delphi 7 08.11.2012 22:26
Проблема с таймером в службе varelik Общие вопросы Delphi 10 17.04.2012 15:40
Работа с сигналом alarm thornish Помощь студентам 2 11.10.2011 22:32
Проблема с таймером обратного отсчета nursak Помощь студентам 10 05.06.2011 17:58
проблема с таймером javascript storm296 JavaScript, Ajax 1 03.08.2010 15:38