2
0
mirror of https://github.com/boostorg/thread.git synced 2026-01-23 18:12:12 +00:00

fix for notify problem in trac ticket #1803

[SVN r44146]
This commit is contained in:
Anthony Williams
2008-04-10 13:14:43 +00:00
parent 8696b610ca
commit 86f9480da4

View File

@@ -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<lock_type>& 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<typename lock_type>
void start_wait_loop(relocker<lock_type>& 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<mutex>& 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<typename lock_type>
void wait(lock_type& m)
{