mirror of
https://github.com/boostorg/thread.git
synced 2026-02-08 23:22:13 +00:00
Compare commits
2 Commits
fix/blocki
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
127b76747c | ||
|
|
f76037dd12 |
@@ -14,6 +14,8 @@
|
|||||||
#include <boost/thread/thread_time.hpp>
|
#include <boost/thread/thread_time.hpp>
|
||||||
#include "interlocked_read.hpp"
|
#include "interlocked_read.hpp"
|
||||||
#include <boost/thread/xtime.hpp>
|
#include <boost/thread/xtime.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <boost/intrusive_ptr.hpp>
|
||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
@@ -27,25 +29,43 @@ namespace boost
|
|||||||
|
|
||||||
struct list_entry
|
struct list_entry
|
||||||
{
|
{
|
||||||
detail::win32::handle semaphore;
|
detail::win32::handle_manager semaphore;
|
||||||
long count;
|
detail::win32::handle_manager wake_sem;
|
||||||
|
long waiters;
|
||||||
bool notified;
|
bool notified;
|
||||||
|
long references;
|
||||||
|
|
||||||
list_entry():
|
list_entry():
|
||||||
semaphore(0),count(0),notified(0)
|
semaphore(detail::win32::create_anonymous_semaphore(0,LONG_MAX)),
|
||||||
|
wake_sem(0),
|
||||||
|
waiters(1),notified(false),references(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void release(unsigned count_to_release=1)
|
void release(unsigned count_to_release)
|
||||||
{
|
{
|
||||||
|
notified=true;
|
||||||
detail::win32::ReleaseSemaphore(semaphore,count_to_release,0);
|
detail::win32::ReleaseSemaphore(semaphore,count_to_release,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friend void intrusive_ptr_add_ref(list_entry * p)
|
||||||
|
{
|
||||||
|
BOOST_INTERLOCKED_INCREMENT(&p->references);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend void intrusive_ptr_release(list_entry * p)
|
||||||
|
{
|
||||||
|
if(!BOOST_INTERLOCKED_DECREMENT(&p->references))
|
||||||
|
{
|
||||||
|
delete p;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
BOOST_STATIC_CONSTANT(unsigned,generation_count=3);
|
typedef boost::intrusive_ptr<list_entry> entry_ptr;
|
||||||
|
typedef std::vector<entry_ptr> generation_list;
|
||||||
|
|
||||||
list_entry generations[generation_count];
|
generation_list generations;
|
||||||
detail::win32::handle wake_sem;
|
detail::win32::handle_manager wake_sem;
|
||||||
|
|
||||||
void wake_waiters(long count_to_wake)
|
void wake_waiters(long count_to_wake)
|
||||||
{
|
{
|
||||||
@@ -53,53 +73,6 @@ namespace boost
|
|||||||
detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0);
|
detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool no_waiters(list_entry const& entry)
|
|
||||||
{
|
|
||||||
return entry.count==0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void shift_generations_down()
|
|
||||||
{
|
|
||||||
list_entry* const last_active_entry=std::remove_if(generations,generations+generation_count,no_waiters);
|
|
||||||
if(last_active_entry==generations+generation_count)
|
|
||||||
{
|
|
||||||
broadcast_entry(generations[generation_count-1]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
active_generation_count=unsigned(last_active_entry-generations)+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef BOOST_MSVC
|
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable:4996)
|
|
||||||
#endif
|
|
||||||
std::copy_backward(generations,generations+active_generation_count-1,generations+active_generation_count);
|
|
||||||
#ifdef BOOST_MSVC
|
|
||||||
#pragma warning(pop)
|
|
||||||
#endif
|
|
||||||
generations[0]=list_entry();
|
|
||||||
}
|
|
||||||
|
|
||||||
void broadcast_entry(list_entry& entry)
|
|
||||||
{
|
|
||||||
entry.release(entry.count);
|
|
||||||
entry.count=0;
|
|
||||||
dispose_entry(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void dispose_entry(list_entry& entry)
|
|
||||||
{
|
|
||||||
if(entry.semaphore)
|
|
||||||
{
|
|
||||||
BOOST_VERIFY(detail::win32::CloseHandle(entry.semaphore));
|
|
||||||
entry.semaphore=0;
|
|
||||||
}
|
|
||||||
entry.notified=false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename lock_type>
|
template<typename lock_type>
|
||||||
struct relocker
|
struct relocker
|
||||||
{
|
{
|
||||||
@@ -123,77 +96,79 @@ namespace boost
|
|||||||
|
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
relocker(relocker&);
|
||||||
void operator=(relocker&);
|
void operator=(relocker&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template<typename lock_type>
|
entry_ptr get_wait_entry()
|
||||||
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);
|
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
|
||||||
locker.unlock();
|
|
||||||
if(!wake_sem)
|
if(!wake_sem)
|
||||||
{
|
{
|
||||||
wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
||||||
BOOST_ASSERT(wake_sem);
|
BOOST_ASSERT(wake_sem);
|
||||||
}
|
}
|
||||||
local_wake_sem=detail::win32::duplicate_handle(wake_sem);
|
|
||||||
|
|
||||||
if(generations[0].notified)
|
|
||||||
{
|
|
||||||
shift_generations_down();
|
|
||||||
}
|
|
||||||
else if(!active_generation_count)
|
|
||||||
{
|
|
||||||
active_generation_count=1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ensure_generation_present()
|
detail::interlocked_write_release(&total_count,total_count+1);
|
||||||
{
|
if(generations.empty() || generations.back()->notified)
|
||||||
if(!generations[0].semaphore)
|
|
||||||
{
|
{
|
||||||
generations[0].semaphore=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
entry_ptr new_entry(new list_entry);
|
||||||
BOOST_ASSERT(generations[0].semaphore);
|
new_entry->wake_sem=wake_sem.duplicate();
|
||||||
|
generations.push_back(new_entry);
|
||||||
|
return new_entry;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_INTERLOCKED_INCREMENT(&generations.back()->waiters);
|
||||||
|
return generations.back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename lock_type>
|
struct entry_manager
|
||||||
void start_wait_loop(relocker<lock_type>& locker,
|
|
||||||
detail::win32::handle_manager& local_wake_sem,
|
|
||||||
detail::win32::handle_manager& sem)
|
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock internal_lock(internal_mutex);
|
entry_ptr const entry;
|
||||||
if(!local_wake_sem)
|
|
||||||
|
entry_manager(entry_ptr const& entry_):
|
||||||
|
entry(entry_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~entry_manager()
|
||||||
{
|
{
|
||||||
start_wait_loop_first_time(locker,local_wake_sem);
|
BOOST_INTERLOCKED_DECREMENT(&entry->waiters);
|
||||||
}
|
}
|
||||||
ensure_generation_present();
|
|
||||||
++generations[0].count;
|
list_entry* operator->()
|
||||||
sem=detail::win32::duplicate_handle(generations[0].semaphore);
|
{
|
||||||
}
|
return entry.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void operator=(entry_manager&);
|
||||||
|
entry_manager(entry_manager&);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template<typename lock_type>
|
template<typename lock_type>
|
||||||
bool do_wait(lock_type& lock,timeout wait_until)
|
bool do_wait(lock_type& lock,timeout wait_until)
|
||||||
{
|
{
|
||||||
detail::win32::handle_manager local_wake_sem;
|
|
||||||
detail::win32::handle_manager sem;
|
|
||||||
bool woken=false;
|
|
||||||
|
|
||||||
relocker<lock_type> locker(lock);
|
relocker<lock_type> locker(lock);
|
||||||
|
|
||||||
|
entry_manager entry(get_wait_entry());
|
||||||
|
|
||||||
|
locker.unlock();
|
||||||
|
|
||||||
|
bool woken=false;
|
||||||
while(!woken)
|
while(!woken)
|
||||||
{
|
{
|
||||||
start_wait_loop(locker,local_wake_sem,sem);
|
if(!this_thread::interruptible_wait(entry->semaphore,wait_until))
|
||||||
|
|
||||||
if(!this_thread::interruptible_wait(sem,wait_until))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long const woken_result=detail::win32::WaitForSingleObject(local_wake_sem,0);
|
unsigned long const woken_result=detail::win32::WaitForSingleObject(entry->wake_sem,0);
|
||||||
BOOST_ASSERT(woken_result==detail::win32::timeout || woken_result==0);
|
BOOST_ASSERT(woken_result==detail::win32::timeout || woken_result==0);
|
||||||
|
|
||||||
woken=(woken_result==0);
|
woken=(woken_result==0);
|
||||||
@@ -214,21 +189,19 @@ namespace boost
|
|||||||
|
|
||||||
basic_condition_variable(const basic_condition_variable& other);
|
basic_condition_variable(const basic_condition_variable& other);
|
||||||
basic_condition_variable& operator=(const basic_condition_variable& other);
|
basic_condition_variable& operator=(const basic_condition_variable& other);
|
||||||
|
|
||||||
|
static bool no_waiters(entry_ptr const& entry)
|
||||||
|
{
|
||||||
|
return !detail::interlocked_read_acquire(&entry->waiters);
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
basic_condition_variable():
|
basic_condition_variable():
|
||||||
total_count(0),active_generation_count(0),wake_sem(0)
|
total_count(0),active_generation_count(0),wake_sem(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~basic_condition_variable()
|
~basic_condition_variable()
|
||||||
{
|
{}
|
||||||
for(unsigned i=0;i<generation_count;++i)
|
|
||||||
{
|
|
||||||
dispose_entry(generations[i]);
|
|
||||||
}
|
|
||||||
detail::win32::CloseHandle(wake_sem);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void notify_one()
|
void notify_one()
|
||||||
{
|
{
|
||||||
if(detail::interlocked_read_acquire(&total_count))
|
if(detail::interlocked_read_acquire(&total_count))
|
||||||
@@ -239,33 +212,14 @@ namespace boost
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wake_waiters(1);
|
wake_waiters(1);
|
||||||
|
|
||||||
unsigned waiting_count=0;
|
for(generation_list::iterator it=generations.begin(),
|
||||||
|
end=generations.end();
|
||||||
for(unsigned generation=active_generation_count;generation!=0;--generation)
|
it!=end;++it)
|
||||||
{
|
{
|
||||||
list_entry& entry=generations[generation-1];
|
(*it)->release(1);
|
||||||
waiting_count+=entry.count;
|
|
||||||
if(entry.count)
|
|
||||||
{
|
|
||||||
entry.notified=true;
|
|
||||||
entry.release();
|
|
||||||
if(!--entry.count)
|
|
||||||
{
|
|
||||||
dispose_entry(entry);
|
|
||||||
if(generation==active_generation_count)
|
|
||||||
{
|
|
||||||
--active_generation_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(waiting_count<=total_count)
|
|
||||||
{
|
|
||||||
shift_generations_down();
|
|
||||||
ensure_generation_present();
|
|
||||||
generations[0].release();
|
|
||||||
}
|
}
|
||||||
|
generations.erase(std::remove_if(generations.begin(),generations.end(),no_waiters),generations.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,24 +228,18 @@ namespace boost
|
|||||||
if(detail::interlocked_read_acquire(&total_count))
|
if(detail::interlocked_read_acquire(&total_count))
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock internal_lock(internal_mutex);
|
boost::mutex::scoped_lock internal_lock(internal_mutex);
|
||||||
long waiting_count=total_count;
|
if(!total_count)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
wake_waiters(total_count);
|
wake_waiters(total_count);
|
||||||
for(unsigned generation=active_generation_count;generation!=0;--generation)
|
for(generation_list::iterator it=generations.begin(),
|
||||||
|
end=generations.end();
|
||||||
|
it!=end;++it)
|
||||||
{
|
{
|
||||||
list_entry& entry=generations[generation-1];
|
(*it)->release(detail::interlocked_read_acquire(&(*it)->waiters));
|
||||||
if(entry.count)
|
|
||||||
{
|
|
||||||
waiting_count-=entry.count;
|
|
||||||
broadcast_entry(entry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(waiting_count)
|
wake_sem=detail::win32::handle(0);
|
||||||
{
|
|
||||||
ensure_generation_present();
|
|
||||||
generations[0].release(waiting_count);
|
|
||||||
}
|
|
||||||
active_generation_count=0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -185,6 +185,9 @@ namespace boost
|
|||||||
{
|
{
|
||||||
f();
|
f();
|
||||||
}
|
}
|
||||||
|
private:
|
||||||
|
void operator=(thread_data&);
|
||||||
|
thread_data(thread_data&);
|
||||||
};
|
};
|
||||||
|
|
||||||
mutable boost::mutex thread_info_mutex;
|
mutable boost::mutex thread_info_mutex;
|
||||||
|
|||||||
0
src/pthread/once.cpp
Executable file → Normal file
0
src/pthread/once.cpp
Executable file → Normal file
Reference in New Issue
Block a user