c++ - Boost::thread::interrupt() behaves differently for different interruption points. Why? -


i writing dll uses boost threads. i've had issues using boost::thread::interrupt() , catching thread_interrupted exception. interruption ponts, interruption thrown , caught in thread , others, interrupt thrown thread.interrupt() called. why happen? have written basic example illustate point, @ bottom of post

the program starts thread uses 1 of worker functions each have different interruption point in them. when user presses enter, thread interrupted , program closes. before each statement printed, thread id printed can see happening.

i expect this:

13c4 main thread  790 worker thread 790 thread iteration 1 press enter stop 790 thread iteration 2 press enter stop 790 thread iteration 3 press enter stop 790 thread stopped in threadfunction 13c4 main: thread ended  process returned 0 (0x0)   execution time : 0.200 s press key continue. 

where main thread runs, in parallel worker thread. when user presses enter, interrupt called in main thread caught in worker thread. thread destroyed. main thread continues , program exits.

what seeing interruption points i've tried (except interruption_point()) interrupt caught in main thread , seems though worker thread continues execution of main thread. so:

1364 main thread 964 worker thread 964 thread iteration 1 press enter stop 964 thread iteration 2 press enter stop 964 thread iteration 3 press enter stop  964 thread joined 964 main: thread ended  process returned 0 (0x0)   execution time : 1.510 s press key continue. 

what causing this? how can catch interrupt in worker function when using condition variable, example? have made mistake somewhere?

my code:

#define boost_thread_use_lib 1 #define boost_system_no_deprecated 1 #define _win32_winnt 0x0501 #define winver 0x0501  #include <boost/thread.hpp> #include <iostream>  using namespace std;  void threadfunctionsleep() {     cout <<  boost::this_thread::get_id() << " worker thread " << endl;     int counter = 0;      while(1)     {         cout <<  boost::this_thread::get_id() << " thread iteration " << ++counter << " press enter stop" << endl;          try         {             boost::this_thread::sleep(boost::posix_time::milliseconds(5000));         }         catch(boost::thread_interrupted&)         {             cout <<  boost::this_thread::get_id() << " thread stopped in threadfunction " << endl;             return;         }      }     }  void threadfunctionsleep2() {     cout <<  boost::this_thread::get_id() << " worker thread " << endl;     int counter = 0;      try     {         cout <<  boost::this_thread::get_id() << " thread iteration " << ++counter << " press enter stop" << endl;          while(1)         {             boost::this_thread::sleep(boost::posix_time::milliseconds(5000));         }      }     catch(boost::thread_interrupted&)     {         cout <<  boost::this_thread::get_id() << " thread stopped in threadfunction " << endl;         return;     }      }  void threadfunctioninterruptionpoint() {     cout <<  boost::this_thread::get_id() << " worker thread " << endl;     int counter = 0;      while(1)     {         cout <<  boost::this_thread::get_id() << " thread iteration " << ++counter << " press enter stop" << endl;          try         {              boost::this_thread::interruption_point();          }         catch(boost::thread_interrupted&)         {             cout <<  boost::this_thread::get_id() << " thread stopped in threadfunction " << endl;             return;         }      }  }  bool mypredicate() {     return false; }  boost::condition_variable full; boost::condition_variable empty; boost::mutex fullmut; boost::mutex emptymut;  void waitedconditionvariable() {       try     {         while(1)         {             boost::system_time const timeout=boost::get_system_time()+ boost::posix_time::milliseconds(1000);             boost::unique_lock<boost::mutex> lock(fullmut);             std::cout << boost::this_thread::get_id()<< "  waiting condition variable or timeout" << std::endl;               if (full.timed_wait(lock, timeout, mypredicate))             {                   std::cout << boost::this_thread::get_id()<< "  condition variable signalled " << std::endl;              }             else             {                 std::cout << boost::this_thread::get_id()<< " condition variable  timeout. "  << std::endl;              }            }     }     catch(boost::thread_interrupted & )     {         std::cout<< boost::this_thread::get_id() << " waitedconditionvariable thread_interrupted " << std::endl;         return;      }     catch (std::exception& e)     {          std::cerr << boost::this_thread::get_id()<< " waitedconditionvariable thread "                   << " caught std::exception" << e.what() << std::endl;                   return;      }     catch(...)     {         std::cout<< boost::this_thread::get_id() << " waitedconditionvariable other" << std::endl;         return;      }  }  void waitedconditionvariable2() {        while(1)     {         try         {             boost::system_time const timeout=boost::get_system_time()+ boost::posix_time::milliseconds(1000);             boost::unique_lock<boost::mutex> lock(fullmut);             std::cout << boost::this_thread::get_id()<< "  waiting condition variable or timeout" << std::endl;               if (full.timed_wait(lock, timeout, mypredicate))             {                   std::cout << boost::this_thread::get_id()<< "  condition variable signalled " << std::endl;              }             else             {                 std::cout << boost::this_thread::get_id()<< " condition variable  timeout. "  << std::endl;              }            }         catch(boost::thread_interrupted & )         {             std::cout<< boost::this_thread::get_id() << " waitedconditionvariable thread_interrupted " << std::endl;             return;          }         catch (std::exception& e)         {              std::cerr << boost::this_thread::get_id()<< " waitedconditionvariable thread "                       << " caught std::exception" << e.what() << std::endl;             return;          }         catch(...)         {             std::cout<< boost::this_thread::get_id() << " waitedconditionvariable other" << std::endl;             return;          }     }   }  void normalconditionvariable() {      try     {         boost::unique_lock<boost::mutex> lock(fullmut);         while(1)         {               std::cout << boost::this_thread::get_id()<< " waiting condition variable " << std::endl;             full.wait(lock);              std::cout << boost::this_thread::get_id()<< " wait done "  << std::endl;          }     }     catch(boost::thread_interrupted & )     {         std::cout<< boost::this_thread::get_id() << " normalconditionvariable thread_interrupted " << std::endl;         return;      }     catch (std::exception& e)     {          std::cerr << boost::this_thread::get_id()<< " normalconditionvariable thread "                   << " caught std::exception" << e.what() << std::endl;         return;      }     catch(...)     {         std::cout<< boost::this_thread::get_id() << " normalconditionvariable other" << std::endl;         return;      } }  void normalconditionvariable2() {      while(1)     {         boost::unique_lock<boost::mutex> lock(fullmut);         try         {               std::cout << boost::this_thread::get_id()<< " waiting condition variable " << std::endl;             full.wait(lock);              std::cout << boost::this_thread::get_id()<< " wait done "  << std::endl;          }         catch(boost::thread_interrupted & )         {             std::cout<< boost::this_thread::get_id() << " normalconditionvariable thread_interrupted " << std::endl;             return;          }         catch (std::exception& e)         {              std::cerr << boost::this_thread::get_id()<< " normalconditionvariable thread "                       << " caught std::exception" << e.what() << std::endl;             return;          }         catch(...)         {             std::cout<< boost::this_thread::get_id() << " normalconditionvariable other" << std::endl;             return;          }     }  }    int main() {     cout <<  boost::this_thread::get_id() << " main thread " << endl;     // start thread     //use thes functions:     // threadfunctionsleep     // threadfunctionsleep2     //threadfunctioninterruptionpoint     //threadfunctioninterruptionpoint2     // waitedconditionvariable     // waitedconditionvariable2     // normalconditionvariable     // normalconditionvariable2     boost::thread t(&waitedconditionvariable2);       // wait enter     char ch;     cin.get(ch);      // ask thread stop     try     {         t.interrupt();     }     catch(boost::thread_interrupted&)     {         cout <<  boost::this_thread::get_id() << " thread stopped" << endl;      }      // join - wait when thread exits     try     {         t.join();     }     catch(boost::thread_interrupted&)     {         cout <<  boost::this_thread::get_id() << " thread joined" << endl;      }     catch(...){         cout <<  boost::this_thread::get_id() << " other exception" << endl;      }      cout <<  boost::this_thread::get_id() << " main: thread ended" << endl;         return 0; } 

i using boost 1.53.0 , mingw 4.4.1. using runtime-link-static, multithreading libraries boost::thread , boost::system

thanks help

one should re-throw exception, or boost::thread not interrupted.

try code below. , can try different join() positions see different output shows state of thread.

#include <iostream> #include <boost/thread.hpp>  void foo() {     while(true) try     {         boost::this_thread::sleep_for(boost::chrono::milliseconds(1000));         std::cout << "thread running..." << std::endl;     }       catch (boost::thread_interrupted&)     {        std::cout << "the thread interrupted" << std::endl;         throw boost::thread_interrupted();     }  }  int main(int argc, char *argv[]) {     boost::thread t(foo);      std::cout << "press enter quit..." << std::endl;     std::cin.get();     t.interrupt();     //t.join();      if (!t.try_join_for(boost::chrono::milliseconds(1)))     {         std::cout << "thread running." << std::endl;     }     else     {         std::cout << "thread not running." << std::endl;     }      //t.join();     boost::this_thread::sleep_for(boost::chrono::milliseconds(1000));      // out put should "thread running.", because thread not joinalb, test function wrong.     if (!t.try_join_for(boost::chrono::milliseconds(1)))     {         std::cout << "thread running." << std::endl;     }     else     {         std::cout << "thread not running." << std::endl;     } } 

Comments

Popular posts from this blog

java.util.scanner - How to read and add only numbers to array from a text file -

rewrite - Trouble with Wordpress multiple custom querystrings -