diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 31f4b091..4c250598 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -236,10 +236,7 @@ rule requirements ( properties * ) } } } - if ! vacpp in $(properties) || 11.1 in $(properties) - { - result += /boost/chrono//boost_chrono ; - } + result += BOOST_THREAD_DONT_USE_CHRONO ; return $(result) ; } diff --git a/include/boost/thread/detail/thread.hpp b/include/boost/thread/detail/thread.hpp index 0e94ae9c..712951b0 100644 --- a/include/boost/thread/detail/thread.hpp +++ b/include/boost/thread/detail/thread.hpp @@ -364,29 +364,17 @@ namespace boost #endif #if defined(BOOST_THREAD_PLATFORM_WIN32) bool timed_join(const system_time& abs_time); - -#ifdef BOOST_THREAD_USES_CHRONO - bool try_join_until(const chrono::time_point& tp); -// bool try_join_until(const chrono::time_point& tp) -// { -// if (this_thread::get_id() == get_id()) -// { -// boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself")); -// } -// detail::thread_data_ptr local_thread_info=(get_thread_info)(); -// if(local_thread_info) -// { -// chrono::milliseconds rel_time= chrono::ceil(tp-chrono::system_clock::now()); -// if(!this_thread::interruptible_wait(local_thread_info->thread_handle,rel_time.count())) -// { -// return false; -// } -// release_handle(); -// } -// return true; -// } -#endif + private: + bool do_try_join_until(uintmax_t milli); public: +#ifdef BOOST_THREAD_USES_CHRONO + bool try_join_until(const chrono::time_point& tp) + { + chrono::milliseconds rel_time= chrono::ceil(tp-chrono::system_clock::now()); + return do_try_join_until(rel_time.count()); + } +#endif + #else bool timed_join(const system_time& abs_time) diff --git a/include/boost/thread/win32/thread_data.hpp b/include/boost/thread/win32/thread_data.hpp index 5af4fd3e..397ec143 100644 --- a/include/boost/thread/win32/thread_data.hpp +++ b/include/boost/thread/win32/thread_data.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef BOOST_THREAD_USES_CHRONO #include #endif @@ -58,8 +59,18 @@ namespace boost namespace detail { + struct tss_cleanup_function; struct thread_exit_callback_node; - struct tss_data_node; + struct tss_data_node + { + boost::shared_ptr func; + void* value; + + tss_data_node(boost::shared_ptr func_, + void* value_): + func(func_),value(value_) + {} + }; struct thread_data_base; void intrusive_ptr_add_ref(thread_data_base * p); @@ -71,14 +82,14 @@ namespace boost detail::win32::handle_manager thread_handle; detail::win32::handle_manager interruption_handle; boost::detail::thread_exit_callback_node* thread_exit_callbacks; - boost::detail::tss_data_node* tss_data; + std::map tss_data; bool interruption_enabled; unsigned id; thread_data_base(): count(0),thread_handle(detail::win32::invalid_handle_value), interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)), - thread_exit_callbacks(0),tss_data(0), + thread_exit_callbacks(0),tss_data(), interruption_enabled(true), id(0) {} diff --git a/src/win32/thread.cpp b/src/win32/thread.cpp index 9b6670a6..9177786f 100644 --- a/src/win32/thread.cpp +++ b/src/win32/thread.cpp @@ -128,19 +128,6 @@ namespace boost {} }; - struct tss_data_node - { - void const* key; - boost::shared_ptr func; - void* value; - tss_data_node* next; - - tss_data_node(void const* key_,boost::shared_ptr func_,void* value_, - tss_data_node* next_): - key(key_),func(func_),value(value_),next(next_) - {} - }; - } namespace @@ -150,7 +137,7 @@ namespace boost detail::thread_data_ptr current_thread_data(get_current_thread_data(),false); if(current_thread_data) { - while(current_thread_data->tss_data || current_thread_data->thread_exit_callbacks) + while(! current_thread_data->tss_data.empty() || current_thread_data->thread_exit_callbacks) { while(current_thread_data->thread_exit_callbacks) { @@ -163,15 +150,18 @@ namespace boost } boost::detail::heap_delete(current_node); } - while(current_thread_data->tss_data) + for(std::map::iterator next=current_thread_data->tss_data.begin(), + current, + end=current_thread_data->tss_data.end(); + next!=end;) { - detail::tss_data_node* const current_node=current_thread_data->tss_data; - current_thread_data->tss_data=current_node->next; - if(current_node->func) + current=next; + ++next; + if(current->second.func && (current->second.value!=0)) { - (*current_node->func)(current_node->value); + (*current->second.func)(current->second.value); } - boost::detail::heap_delete(current_node); + current_thread_data->tss_data.erase(current); } } @@ -301,7 +291,6 @@ namespace boost { return (get_thread_info)(); } - void thread::join() { if (this_thread::get_id() == get_id()) @@ -318,45 +307,27 @@ namespace boost bool thread::timed_join(boost::system_time const& wait_until) { - if (this_thread::get_id() == get_id()) - { - boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself")); - } - detail::thread_data_ptr local_thread_info=(get_thread_info)(); - if(local_thread_info) - { - if(!this_thread::interruptible_wait(local_thread_info->thread_handle,get_milliseconds_until(wait_until))) - { - return false; - } - release_handle(); - } - return true; + return do_try_join_until(get_milliseconds_until(wait_until)); } -#ifdef BOOST_THREAD_USES_CHRONO - - bool thread::try_join_until(const chrono::time_point& tp) + bool thread::do_try_join_until(uintmax_t milli) { if (this_thread::get_id() == get_id()) { - boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself")); + boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself")); } detail::thread_data_ptr local_thread_info=(get_thread_info)(); if(local_thread_info) { - chrono::milliseconds rel_time= chrono::ceil(tp-chrono::system_clock::now()); - if(!this_thread::interruptible_wait(local_thread_info->thread_handle,rel_time.count())) - { - return false; - } - release_handle(); + if(!this_thread::interruptible_wait(local_thread_info->thread_handle,milli)) + { + return false; + } + release_handle(); } return true; } -#endif - void thread::detach() BOOST_NOEXCEPT { release_handle(); @@ -636,14 +607,11 @@ namespace boost detail::thread_data_base* const current_thread_data(get_current_thread_data()); if(current_thread_data) { - detail::tss_data_node* current_node=current_thread_data->tss_data; - while(current_node) + std::map::iterator current_node= + current_thread_data->tss_data.find(key); + if(current_node!=current_thread_data->tss_data.end()) { - if(current_node->key==key) - { - return current_node; - } - current_node=current_node->next; + return ¤t_node->second; } } return NULL; @@ -658,23 +626,43 @@ namespace boost return NULL; } - void set_tss_data(void const* key,boost::shared_ptr func,void* tss_data,bool cleanup_existing) + void add_new_tss_node(void const* key, + boost::shared_ptr func, + void* tss_data) + { + detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); + current_thread_data->tss_data.insert(std::make_pair(key,tss_data_node(func,tss_data))); + } + + void erase_tss_node(void const* key) + { + detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); + current_thread_data->tss_data.erase(key); + } + + void set_tss_data(void const* key, + boost::shared_ptr func, + void* tss_data,bool cleanup_existing) { if(tss_data_node* const current_node=find_tss_data(key)) { - if(cleanup_existing && current_node->func.get() && current_node->value) + if(cleanup_existing && current_node->func && (current_node->value!=0)) { (*current_node->func)(current_node->value); } - current_node->func=func; - current_node->value=tss_data; + if(func || (tss_data!=0)) + { + current_node->func=func; + current_node->value=tss_data; + } + else + { + erase_tss_node(key); + } } - else if(func && tss_data) + else { - detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); - tss_data_node* const new_node= - heap_new(key,func,tss_data,current_thread_data->tss_data); - current_thread_data->tss_data=new_node; + add_new_tss_node(key,func,tss_data); } } } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 65843594..352c9065 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -44,7 +44,7 @@ project clang:-pedantic clang:-Wno-long-long clang:-ansi - #clang:-fpermissive # doesn't work + #clang:-fpermissive # doesn't work gcc-mingw-4.4.0:-fdiagnostics-show-option gcc-mingw-4.5.0:-fdiagnostics-show-option @@ -80,13 +80,13 @@ rule thread-run ( sources ) rule thread-test ( sources ) { return - [ run $(sources) ../build//boost_thread : : : - /boost/test//boost_unit_test_framework/static + [ run $(sources) ../build//boost_thread : : : + /boost/test//boost_unit_test_framework/static ] [ run $(sources) ../src/tss_null.cpp ../build//boost_thread/static - : : : - /boost/test//boost_unit_test_framework/static - : $(sources[1]:B)_lib + : : : + /boost/test//boost_unit_test_framework/static + : $(sources[1]:B)_lib ] ; } diff --git a/test/threads/thread/members/join_pass.cpp b/test/threads/thread/members/join_pass.cpp index 72977be0..35248d9e 100644 --- a/test/threads/thread/members/join_pass.cpp +++ b/test/threads/thread/members/join_pass.cpp @@ -53,7 +53,6 @@ public: void operator()() { BOOST_TEST(alive_ == 1); - std::cout << __FILE__ << ":" << __LINE__ <<" " << n_alive << std::endl; BOOST_TEST(n_alive == 1); op_run = true; } @@ -62,58 +61,73 @@ public: int G::n_alive = 0; bool G::op_run = false; -boost::thread* resource_deadlock_would_occur_th; +boost::thread* resource_deadlock_would_occur_th=0; boost::mutex resource_deadlock_would_occur_mtx; void resource_deadlock_would_occur_tester() { try { - std::cout << __FILE__ << ":" << __LINE__ <<" " << std::endl; boost::unique_lock lk(resource_deadlock_would_occur_mtx); - std::cout << __FILE__ << ":" << __LINE__ <<" " << std::endl; + resource_deadlock_would_occur_th->join(); - std::cout << __FILE__ << ":" << __LINE__ <<" " << std::endl; BOOST_TEST(false); - std::cout << __FILE__ << ":" << __LINE__ <<" " << std::endl; } catch (boost::system::system_error& e) { - std::cout << __FILE__ << ":" << __LINE__ <<" " << std::endl; BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); } catch (...) { - std::cout << __FILE__ << ":" << __LINE__ <<" " << std::endl; BOOST_TEST(false&&"exception thrown"); } } +void throws_thread_resource_error_tester() +{ + { + try { + boost::throw_exception( + boost::thread_resource_error( + boost::system::errc::resource_deadlock_would_occur, + "boost thread: trying joining itself" + )); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + catch (...) + { + BOOST_TEST(false&&"exception thrown"); + } + } +} + int main() { { - std::cout << __FILE__ << ":" << __LINE__ <<" " << std::endl; boost::thread t0( (G())); BOOST_TEST(t0.joinable()); t0.join(); BOOST_TEST(!t0.joinable()); } + { - std::cout << __FILE__ << ":" << __LINE__ <<" " << std::endl; - boost::unique_lock lk(resource_deadlock_would_occur_mtx); - std::cout << __FILE__ << ":" << __LINE__ <<" " << std::endl; - boost::thread t0( resource_deadlock_would_occur_tester ); - std::cout << __FILE__ << ":" << __LINE__ <<" " << std::endl; - resource_deadlock_would_occur_th = &t0; - std::cout << __FILE__ << ":" << __LINE__ <<" " << std::endl; - BOOST_TEST(t0.joinable()); - std::cout << __FILE__ << ":" << __LINE__ <<" " << std::endl; - lk.unlock(); - std::cout << __FILE__ << ":" << __LINE__ <<" " << std::endl; + boost::thread t0( throws_thread_resource_error_tester ); + t0.join(); + } + { + boost::unique_lock lk(resource_deadlock_would_occur_mtx); + boost::thread t0( resource_deadlock_would_occur_tester ); + resource_deadlock_would_occur_th = &t0; + BOOST_TEST(t0.joinable()); + lk.unlock(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(100)); + boost::unique_lock lk2(resource_deadlock_would_occur_mtx); t0.join(); - std::cout << __FILE__ << ":" << __LINE__ <<" " << std::endl; BOOST_TEST(!t0.joinable()); - std::cout << __FILE__ << ":" << __LINE__ <<" " << std::endl; } // {