2017-01-28 6 views
2

ソリューションが見つかり
私はuseingいVS2013、ブースト1.59.0
を私はWindows上でboost::ioserviceを停止する問題を抱えているboost c++ application development cookbook
から、次の例があります。私は今、それを停止する回避策を見つけた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; 
} 

問題はios_.stop();が動作していないことを意味する100に等しい変数g_valあります。私はデバッグとして実行し、このコマンドが呼び出されました。 boost::ioserviceを停止するには?

答えて

1

io_service::stop()は、io_serviceのイベントループの状態を変更するだけで、io_service::run()コールができるだけ早く返されます。 stop()がすでにキューに入っているハンドラをキャンセルしているかどうかは文書化されていませんが、それはこのpostに従ってOSに依存しているようです。したがって、g_val == 90の場合、io_service::stop()が呼び出されますが、残っているのはfunc_test()です。

+0

ウィンドウ上で 'ioservice'を停止する回避策を知っていますか?あなたが提供したリンクを試しましたが、動作しません。\ – sflee

+1

多分 'stop()'、[the doc](http://www.boost.org/doc/libs/)の後に 'io_service'を破壊することができます。 1_63_0/doc/html/boost_asio/reference.html#boost_asio.reference.io_service._io_service)は、それを破壊したとき、 'io_service'または任意の関連するストランドの遅延呼び出しのためにスケジューリングされた呼び出されていないハンドラオブジェクトが破棄されると言います。それでもうまくいかない場合は、 'boost :: atomic 'フラグを使って 'io_service'が動作しているかどうかを示します。 – jfly

関連する問題