2010-07-25 74 views
1

我有一个应用程序,我希望每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();}); 
       } 
     } 
    } 

我在做什么错?如果我得到这个解决方案的工作会比第一个更好吗?

+0

我不熟悉这个语法'timer_.async_wait([=] {显示();});'它有什么作用? – 2010-07-26 14:40:23

+0

如果你的意思是[=] {Display();}),那么它只是一个C++ 11x lambda表达式。它是写函数对象的简写。 – ronag 2010-08-06 18:14:34

回答

1

请记住,帧的显示精度受显示器的刷新率限制(典型值为60 Hz显示器为17 ms,75 Hz显示器为13 ms)。如果你没有同步到显示刷新,那么你有一个不确定的延迟0-17毫秒,以添加到你使用的任何计时方法,因此精度并不需要比10毫秒好得多(甚至1毫秒可能是矫枉过正)。

+0

我不相信这是一个问题,因为我的最大帧率将是50帧/秒。也许我错了? 但我从你的答案中看出,准确度差异很小,从而有所作为。 尽管我仍然想知道第二种解决方案中最新的错误是什么? – ronag 2010-07-25 12:26:43

+0

我对使用boost进行计时并不熟悉,但底线是,对于此应用程序,您不需要担心精度优于〜10 ms,因为通常您已经有了那么多的错误。 – 2010-07-25 13:29:44

3

下面是使用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(); 
} 
+0

我不明白这和我的第二个例子有什么不同? – ronag 2010-07-27 22:11:22

+1

我的示例使用'shared_from_this'并且不使用线程,也许这些细微差别。 – 2010-07-30 13:07:45

+0

利用shared_from_this和定时器的周期性特性的组合,这并不意味着即使没有外部共享指针指向Timer对象也永远不会销毁,因为总会有共享回调中的指针? – oracal 2014-01-15 15:02:15