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
Post a Comment