Точный непрерывный обратный вызов таймера - PullRequest
1 голос
/ 25 июля 2010

У меня есть приложение, в котором я хочу отображать кадр каждые x миллисекунд.

Ранее я делал это так:

class SomeClass
{
    boost::thread thread_;
    boost::timer timer_;
public:
    SomeClass() : thread_([=]{Display();}) 
    {
    }

    void Display
    {    
        double wait = 1.0/fps*1000.0;    
        while(isRunning_)
        {
             double elapsed = timer.elapsed()*1000.0;
             if(elapsed < wait) 
                  boost::this_thread::sleep(boost::posix_time::milliseconds(static_cast<unsigned int>(wait - elapsed)));
             timer.restart();

             // ... Get Frame. This can block while no frames are being rendered.

             // ... Display Frame.
      }
    }
}

Однако я не думаю, что решение имеет очень хорошую точность. Я могу ошибаться?

Я надеялся использовать вместо него boost :: asio :: deadline_timer, но я не уверен, как его использовать.

Это то, что я попробовал, но, похоже, совсем не ждет. Кажется, он просто рендерит кадры так быстро, как только может.

class SomeClass
    {
        boost::thread thread_;
        boost::asio::io_service io_;
        boost::asio::deadline_timer timer_;

    public:
        SomeClass() : timer_(io_, 1.0/fps*1000.0)
        {
            timer_.async_wait([=]{Display();});
            thread_ = boost::thread([=]{io_.run();})
        }

        void Display
        {    
                double wait = 1.0/fps*1000.0;    
                while(isRunning_)
                {
                    timer_.expires_from_now(boost::posix_time::milliseconds(wait_)); // Could this overflow?

                    // ... Get Frame. This can block while no frames are being rendered.

                    // ... Display Frame.

                     timer_.async_wait([=]{Display();});
                }
        }
    }

Что я делаю не так? И если я получу это решение, будет ли оно лучше, чем первое?

Ответы [ 2 ]

3 голосов
/ 26 июля 2010

Вот довольно тривиальный пример использования boost::asio::deadline_timer, надеюсь, это поможет

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>

#include <iostream>

class Timer : public boost::enable_shared_from_this<Timer>
{
public:
    Timer(
            boost::asio::io_service& io_service
         ) :
        _io_service( io_service ),
        _timer( io_service )
    {

    }

    void start() {
        _timer.expires_from_now(
                boost::posix_time::seconds( 0 )
                );
        _timer.async_wait(
                boost::bind(
                    &Timer::handler,
                    shared_from_this(),
                    boost::asio::placeholders::error
                    )
                );
    }

private:
    void handler(
            const boost::system::error_code& error
            )
    {
        if ( error ) {
            std::cerr << error.message() << std::endl;
            return;
        }

        std::cout << "handler" << std::endl;
        _timer.expires_from_now(
                boost::posix_time::seconds( 1 )
                );
        _timer.async_wait(
                boost::bind(
                    &Timer::handler,
                    shared_from_this(),
                    boost::asio::placeholders::error
                    )
                );
    }

private:
    boost::asio::io_service& _io_service;
    boost::asio::deadline_timer _timer;
};

int
main()
{
    boost::asio::io_service io_service;
    boost::shared_ptr<Timer> timer(
            new Timer( io_service )
            );
    timer->start();
    io_service.run();
}
1 голос
/ 25 июля 2010

Помните, что точность отображения кадра ограничена частотой обновления вашего дисплея (обычно 17 мс для дисплея с частотой 60 Гц или 13 мс для дисплея с частотой 75 Гц).Если вы не синхронизируете с обновлением дисплея, то у вас есть неопределенная задержка в 0–17 мс для добавления к любому используемому вами методу синхронизации, следовательно, точность не обязательно должна быть намного лучше, чем 10 мс (даже 1 мс, вероятно, является избыточным)).

...