From 86f9480da4c8fbdd53ddcd14cf7ed16cb9c0e18d Mon Sep 17 00:00:00 2001 From: Anthony Williams Date: Thu, 10 Apr 2008 13:14:43 +0000 Subject: [PATCH] fix for notify problem in trac ticket #1803 [SVN r44146] --- .../boost/thread/win32/condition_variable.hpp | 64 +++++++++++++++---- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/include/boost/thread/win32/condition_variable.hpp b/include/boost/thread/win32/condition_variable.hpp index 6bd4efd6..01ba1703 100644 --- a/include/boost/thread/win32/condition_variable.hpp +++ b/include/boost/thread/win32/condition_variable.hpp @@ -34,6 +34,12 @@ namespace boost list_entry(): semaphore(0),count(0),notified(0) {} + + void release(unsigned count=1) + { + detail::win32::ReleaseSemaphore(semaphore,count,0); + } + }; BOOST_STATIC_CONSTANT(unsigned,generation_count=3); @@ -77,7 +83,7 @@ namespace boost { detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0); } - detail::win32::ReleaseSemaphore(entry.semaphore,count_to_wake,0); + entry.release(count_to_wake); entry.count=0; dispose_entry(entry); } @@ -124,6 +130,7 @@ namespace boost void start_wait_loop_first_time(relocker& locker, detail::win32::handle_manager& local_wake_sem) { + detail::interlocked_write_release(&total_count,total_count+1); locker.unlock(); if(!wake_sem) { @@ -141,6 +148,15 @@ namespace boost active_generation_count=1; } } + + void ensure_generation_present() + { + if(!generations[0].semaphore) + { + generations[0].semaphore=detail::win32::create_anonymous_semaphore(0,LONG_MAX); + BOOST_ASSERT(generations[0].semaphore); + } + } template void start_wait_loop(relocker& locker, @@ -148,16 +164,11 @@ namespace boost detail::win32::handle_manager& sem) { boost::mutex::scoped_lock internal_lock(internal_mutex); - detail::interlocked_write_release(&total_count,total_count+1); if(!local_wake_sem) { start_wait_loop_first_time(locker,local_wake_sem); } - if(!generations[0].semaphore) - { - generations[0].semaphore=detail::win32::create_anonymous_semaphore(0,LONG_MAX); - BOOST_ASSERT(generations[0].semaphore); - } + ensure_generation_present(); ++generations[0].count; sem=detail::win32::duplicate_handle(generations[0].semaphore); } @@ -222,15 +233,23 @@ namespace boost if(detail::interlocked_read_acquire(&total_count)) { boost::mutex::scoped_lock internal_lock(internal_mutex); + if(!total_count) + { + return; + } detail::win32::ReleaseSemaphore(wake_sem,1,0); + detail::interlocked_write_release(&total_count,total_count-1); + + unsigned waiting_count=0; + for(unsigned generation=active_generation_count;generation!=0;--generation) { list_entry& entry=generations[generation-1]; + waiting_count+=entry.count; if(entry.count) { - detail::interlocked_write_release(&total_count,total_count-1); entry.notified=true; - detail::win32::ReleaseSemaphore(entry.semaphore,1,0); + entry.release(); if(!--entry.count) { dispose_entry(entry); @@ -241,6 +260,11 @@ namespace boost } } } + if(waiting_count<=total_count) + { + ensure_generation_present(); + generations[0].release(); + } } } @@ -265,9 +289,18 @@ namespace boost } class condition_variable: - public detail::basic_condition_variable + private detail::basic_condition_variable { + private: + condition_variable(condition_variable&); + void operator=(condition_variable&); public: + condition_variable() + {} + + using detail::basic_condition_variable::notify_one; + using detail::basic_condition_variable::notify_all; + void wait(unique_lock& m) { do_wait(m,detail::timeout::sentinel()); @@ -313,9 +346,18 @@ namespace boost }; class condition_variable_any: - public detail::basic_condition_variable + private detail::basic_condition_variable { + private: + condition_variable_any(condition_variable_any&); + void operator=(condition_variable_any&); public: + condition_variable_any() + {} + + using detail::basic_condition_variable::notify_one; + using detail::basic_condition_variable::notify_all; + template void wait(lock_type& m) {