Повышение потоков и таймеров, C ++ - PullRequest
0 голосов
/ 27 августа 2009

У меня есть этот код для пользовательского класса 'sau_timer':

sau_timer::sau_timer(int secs, timerparam f, vector<string> params) : strnd(io), 
    t(io, boost::posix_time::seconds(secs))
{
    assert(secs > 0);
    this->f = f;
    this->params = params;
    t.async_wait(strnd.wrap(boost::bind(&sau_timer::exec, this, _1)));
    boost::thread thrd(boost::bind(&boost::asio::io_service::run, &io));
    io.run();
}

void sau_timer::exec(const boost::system::error_code&) {
    (f)(params);
}

Я хочу, чтобы при создании объекта sau_timer таймер запускался, но продолжал выполнение программы. Например, это main ():

int main(int argc, char* argv[])
{
    vector<string> args(1);
    args[0] = "Hello!";
    sau_timer timer_test(3, sau_prompt, args);
    args[0] = "First!";
    sau_prompt(args);
    timer_test.thrd.join();
    return 0;
}

Мое намерение здесь состоит в том, чтобы выполнить timer_test, запустив таймер, который ждет три секунды перед вызовом sau_prompt («Hello!»), Но этот sau_prompt («First!») Будет вызван первым. В данный момент в приглашении перед First отображается Hello, указывая, что таймер останавливает всю программу на три секунды, прежде чем продолжить. Я хочу, чтобы таймер работал в фоновом режиме.

Что я делаю не так? Код компилируется ...

Спасибо.

Ответы [ 2 ]

6 голосов
/ 27 августа 2009

Вы вызываете «io.run ()» в sau_timer - это, по сути, говорит реактору asio обрабатывать любые / все ожидающие асинхронные события, если это возможно.

Вы должны вызывать run или post после установки событий, как обычно. посмотрите примеры в документации по asio.

#include <iostream>
#include <asio.hpp>

#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/date_time.hpp>
#include <boost/thread.hpp>


class event_timer
{
public:

   event_timer(asio::io_service& io_service,
               const std::size_t& tid,
               const std::size_t& interval = 5)
   : io_service_(io_service),
     timer_(io_service),
     tid_(tid),
     interval_(interval),
     tick_count_(0),
     total_diff_(0)
   {
   }

   void start()
   {
      timer_.cancel();
      initiate_timer();
   }

   void stop()
   {
      timer_.cancel();
   }

   void set_interval(const std::size_t& milliseconds)
   {
      interval_ = milliseconds;
   }

private:

   inline void initiate_timer()
   {
      if (interval_)
      {
         timer_.expires_from_now(boost::posix_time::milliseconds(interval_));
         timer_.async_wait(
            boost::bind(&event_timer::handle_timer_event,this,
               asio::placeholders::error));
         before_ = boost::posix_time::microsec_clock::universal_time();
      }
   }

   inline void handle_timer_event(const asio::error_code& error)
   {
      if (!error && interval_)
      {
         after_ = boost::posix_time::microsec_clock::universal_time();
         boost::posix_time::time_duration duration = after_ - before_;
         total_diff_ += std::abs(interval_ - duration.total_milliseconds());
         ++tick_count_;
         if (tick_count_ < 200)
            initiate_timer();
         else
            std::cout << "Timer["<< tid_ <<"]\tTick["<< tick_count_ <<"] Average Diff: " << total_diff_ / (1.0 * tick_count_) << std::endl;
      }
   }

   asio::io_service& io_service_;
   std::size_t tid_;
   std::size_t interval_;
   std::size_t tick_count_;
   asio::deadline_timer timer_;
   boost::posix_time::ptime before_;
   boost::posix_time::ptime after_;
   std::size_t total_diff_;
};

int main()
{

   std::cout << "Timer Test" << std::endl;

   asio::io_service io_service;

   try
   {
      const std::size_t et_cnt = 1000;
      std::vector<event_timer*> et_lst;

      for(unsigned int i = 0; i < et_cnt; ++i)
      {
         et_lst.push_back(new event_timer(io_service,i,10));
      }

      for(unsigned int i = 0; i < et_cnt;)
      {
         et_lst[i++]->start();
      }

      std::size_t thread_pool_size = 100;

      //Create a pool of threads to run all of the io_services.
      std::vector<boost::shared_ptr<boost::thread> > threads;
      for (std::size_t i = 0; i < thread_pool_size; ++i)
      {
         boost::shared_ptr<boost::thread> thread(new boost::thread(boost::bind(&asio::io_service::run, &io_service)));
         threads.push_back(thread);
      }

      // Wait for all threads in the pool to exit.
      for (std::size_t i = 0; i < threads.size(); ++i)
         threads[i]->join();
      for(unsigned int i = 0; i < et_cnt; delete et_lst[i++]);

   }
   catch(std::exception& e)
   {
      std::cout << "Exception: " << e.what() << std::endl;
      return 1;
   }

   return 0;
}
0 голосов
/ 15 декабря 2018

, учитывая пространство имен и версию Boost 1.69, нужно сделать три модификации:

  1. изменить #include <asio.hpp> на #include <boost/asio.hpp>
  2. добавить: using namespace boost; using namespace boost:asio;
  3. изменить inline void handle_timer_event(const asio::error_code& error) на void handle_timer_event(const boost::system::error_code& error)
...