2017-01-28 1 views
2

Решение Найдено
Я использованияКонтактная VS2013, подталкивание 1.59.0
У меня есть следующий пример из boost c++ application development cookbook
У меня есть проблема, чтобы остановить boost::ioservice на Windows. Теперь я нашел обходной способ остановить его, используя ios_.stopped().Как остановить повышение :: ioservice на Windows,

#include <boost/thread/thread.hpp> 
#include <boost/asio/io_service.hpp> 

namespace detail 
{ 

    template <class T> 
    struct task_wrapped 
    { 
    private: 
     T task_unwrapped_; 
    public: 
     explicit task_wrapped(const T& task_unwrapped) 
      : task_unwrapped_(task_unwrapped) 
     {} 
     void operator()() const 
     { 
      // resetting interruption 
      try 
      { 
       boost::this_thread::interruption_point(); 
      } 
      catch (const boost::thread_interrupted&){} 

      try 
      { 
       // Executing task 
       task_unwrapped_(); 
      } 
      catch (const std::exception& e) 
      { 
       std::cerr << "Exception: " << e.what() << '\n'; 
      } 
      catch (const boost::thread_interrupted&) 
      { 
       std::cerr << "Thread interrupted\n"; 
      } 
      catch (...) 
      { 
       std::cerr << "Unknown exception\n"; 
      } 
     } 
    }; 

    template <class T> 
    task_wrapped<T> make_task_wrapped(const T& task_unwrapped) 
    { 
     return task_wrapped<T>(task_unwrapped); 
    } 
} // namespace detail 

class tasks_processor; 
tasks_processor* pProcessor = nullptr; 
class tasks_processor : private boost::noncopyable { 
    boost::asio::io_service ios_; 
    boost::asio::io_service::work work_; 
    tasks_processor() 
     : ios_() 
     , work_(ios_) 
    {} 
public: 
    static tasks_processor& get() 
    { 
     if (pProcessor == nullptr) 
     { 
      pProcessor = new tasks_processor; 
     } 
     return *pProcessor; 
    } 

    template <class T> 
    inline void push_task(const T& task_unwrapped) { 
     ios_.post(detail::make_task_wrapped(task_unwrapped)); 
    } 

    void start() { 
     ios_.run(); 
    } 
    void stop() { 
     ios_.stop(); 
    } 
    bool IsStopped() { 
     return ios_.stopped(); 
    } 
}; // tasks_processor 

int g_val = 0; 
void func_test() 
{ 
    if (tasks_processor::get().IsStopped()) 
     return; 
    ++g_val; 
    if (g_val == 3) 
    { 
     throw std::logic_error("Just checking"); 
    } 
    boost::this_thread::interruption_point(); 
    if (g_val == 10) 
    { 
     // Emulation of thread interruption. 
     // Will be caught and won't stop execution. 
     throw boost::thread_interrupted(); 
    } 
    if (g_val == 90) 
    { 
     tasks_processor::get().stop(); 
    } 
} 


int main() 
{ 
    static const std::size_t tasks_count = 100; 
    // stop() is called at 90 
    BOOST_STATIC_ASSERT(tasks_count > 90); 
    for (std::size_t i = 0; i < tasks_count; ++i) 
    { 
     tasks_processor::get().push_task(&func_test); 
    } 

    // We can also use result of boost::bind call 
    // as a task 
    tasks_processor::get().push_task(
     boost::bind(std::plus<int>(), 2, 2) // counting 2 + 2 
     ); 

    // Processing was not started. 
    assert(g_val == 0); 
    // Will not throw, but blocks till 
    // one of the tasks it is owning 
    // calls stop(). 
    tasks_processor::get().start(); 
    assert(g_val == 90); 
    return 0; 
} 

Проблема в том, переменная g_val равно 100, что означает, что ios_.stop(); не работает. Я запускаю отладку, и эта команда была вызвана. Как остановить boost::ioservice?

ответ

1

io_service::stop() просто изменяет состояние цикла событий io_service, он вызывает как можно скорее звонок io_service::run(). Не зарегистрировано ли stop() отменить уже поставленные в очередь обработчики, похоже, что он зависит от ОС в соответствии с этим post. Поэтому, когда g_val == 90, io_service::stop() вызывается, но оставшееся func_test() все равно может быть выполнено.

+0

Вы знаете какой-либо метод обхода, чтобы остановить «ioservice» на окнах? Я пробовал ссылку, которую вы предоставили, но она не работает /. \ – sflee

+1

Возможно, вы можете уничтожить 'io_service' после' stop() ', [doc] (http://www.boost.org/doc/libs/ 1_63_0/doc/html/boost_asio/reference.html # boost_asio.reference.io_service._io_service) говорит, что при его уничтожении уничтожаются неинвинированные объекты обработчика, которые были запланированы для отложенного вызова в 'io_service' или любой связанной нити. Если это не сработает, используйте флаг 'boost :: atomic ', чтобы указать, запущен ли 'io_service'. – jfly

Смежные вопросы