2
0
mirror of https://github.com/boostorg/thread.git synced 2026-02-11 00:02:12 +00:00

merged from trunk

[SVN r45230]
This commit is contained in:
Eric Niebler
2008-05-08 21:41:48 +00:00
parent 8cf2782777
commit 3ec58d02ba
16 changed files with 439 additions and 86 deletions

View File

@@ -6,6 +6,9 @@
#ifndef BOOST_THREAD_MOVE_HPP
#define BOOST_THREAD_MOVE_HPP
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_convertible.hpp>
namespace boost
{
namespace detail
@@ -14,7 +17,7 @@ namespace boost
struct thread_move_t
{
T& t;
thread_move_t(T& t_):
explicit thread_move_t(T& t_):
t(t_)
{}
@@ -31,6 +34,18 @@ namespace boost
void operator=(thread_move_t&);
};
}
template<typename T>
typename enable_if<boost::is_convertible<T&,detail::thread_move_t<T> >, detail::thread_move_t<T> >::type move(T& t)
{
return t;
}
template<typename T>
detail::thread_move_t<T> move(detail::thread_move_t<T> t)
{
return t;
}
}

View File

@@ -62,6 +62,10 @@ namespace boost
explicit unique_lock(unique_lock&);
unique_lock& operator=(unique_lock&);
public:
unique_lock():
m(0),is_locked(false)
{}
explicit unique_lock(Mutex& m_):
m(&m_),is_locked(false)
{
@@ -204,18 +208,6 @@ namespace boost
friend class upgrade_lock<Mutex>;
};
template<typename Mutex>
inline detail::thread_move_t<unique_lock<Mutex> > move(unique_lock<Mutex> & x)
{
return x.move();
}
template<typename Mutex>
inline detail::thread_move_t<unique_lock<Mutex> > move(detail::thread_move_t<unique_lock<Mutex> > x)
{
return x;
}
template<typename Mutex>
class shared_lock
{
@@ -226,6 +218,10 @@ namespace boost
explicit shared_lock(shared_lock&);
shared_lock& operator=(shared_lock&);
public:
shared_lock():
m(0),is_locked(false)
{}
explicit shared_lock(Mutex& m_):
m(&m_),is_locked(false)
{
@@ -252,26 +248,29 @@ namespace boost
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
other->m=0;
}
shared_lock(detail::thread_move_t<unique_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
if(is_locked)
{
m->unlock_and_lock_shared();
}
other->is_locked=false;
other->m=0;
}
shared_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
if(is_locked)
{
m->unlock_upgrade_and_lock_shared();
}
other->is_locked=false;
other->m=0;
}
operator detail::thread_move_t<shared_lock<Mutex> >()
@@ -372,19 +371,6 @@ namespace boost
};
template<typename Mutex>
inline detail::thread_move_t<shared_lock<Mutex> > move(shared_lock<Mutex> & x)
{
return x.move();
}
template<typename Mutex>
inline detail::thread_move_t<shared_lock<Mutex> > move(detail::thread_move_t<shared_lock<Mutex> > x)
{
return x;
}
template<typename Mutex>
class upgrade_lock
{
@@ -395,6 +381,10 @@ namespace boost
explicit upgrade_lock(upgrade_lock&);
upgrade_lock& operator=(upgrade_lock&);
public:
upgrade_lock():
m(0),is_locked(false)
{}
explicit upgrade_lock(Mutex& m_):
m(&m_),is_locked(false)
{
@@ -415,16 +405,18 @@ namespace boost
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
other->m=0;
}
upgrade_lock(detail::thread_move_t<unique_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
if(is_locked)
{
m->unlock_and_lock_upgrade();
}
other->is_locked=false;
other->m=0;
}
operator detail::thread_move_t<upgrade_lock<Mutex> >()
@@ -511,18 +503,6 @@ namespace boost
};
template<typename Mutex>
inline detail::thread_move_t<upgrade_lock<Mutex> > move(upgrade_lock<Mutex> & x)
{
return x.move();
}
template<typename Mutex>
inline detail::thread_move_t<upgrade_lock<Mutex> > move(detail::thread_move_t<upgrade_lock<Mutex> > x)
{
return x;
}
template<typename Mutex>
unique_lock<Mutex>::unique_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
@@ -595,6 +575,9 @@ namespace boost
{
typedef unique_lock<Mutex> base;
public:
try_lock_wrapper()
{}
explicit try_lock_wrapper(Mutex& m):
base(m,try_to_lock)
{}

View File

@@ -139,6 +139,13 @@ namespace boost
BOOST_ASSERT(!res || res==ETIMEDOUT);
return !res;
}
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
return &m;
}
#else
void lock()
{

View File

@@ -76,6 +76,13 @@ namespace boost
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
return &m;
}
typedef unique_lock<recursive_mutex> scoped_lock;
typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
};
@@ -171,6 +178,13 @@ namespace boost
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
return &m;
}
#else
void lock()
{

View File

@@ -222,16 +222,10 @@ namespace boost
bool interruption_requested() const;
};
inline detail::thread_move_t<thread> move(thread& x)
inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> t)
{
return x.move();
return t;
}
inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> x)
{
return x;
}
template<typename F>
struct thread::thread_data<boost::reference_wrapper<F> >:

View File

@@ -21,7 +21,10 @@ namespace boost
{
struct basic_timed_mutex
{
BOOST_STATIC_CONSTANT(long,lock_flag_value=0x80000000);
BOOST_STATIC_CONSTANT(unsigned char,lock_flag_bit=31);
BOOST_STATIC_CONSTANT(unsigned char,event_set_flag_bit=30);
BOOST_STATIC_CONSTANT(long,lock_flag_value=1<<lock_flag_bit);
BOOST_STATIC_CONSTANT(long,event_set_flag_value=1<<event_set_flag_bit);
long active_count;
void* event;
@@ -50,18 +53,7 @@ namespace boost
bool try_lock()
{
long old_count=active_count&~lock_flag_value;
do
{
long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,(old_count+1)|lock_flag_value,old_count);
if(current_count==old_count)
{
return true;
}
old_count=current_count;
}
while(!(old_count&lock_flag_value));
return false;
return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
}
void lock()
@@ -70,6 +62,10 @@ namespace boost
}
bool timed_lock(::boost::system_time const& wait_until)
{
if(!win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit))
{
return true;
}
long old_count=active_count;
#ifdef BOOST_MSVC
#pragma warning(push)
@@ -80,37 +76,39 @@ namespace boost
#pragma warning(pop)
#endif
{
long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,(old_count+1)|lock_flag_value,old_count);
if(current_count==old_count)
long const new_count=(old_count&lock_flag_value)?(old_count+1):(old_count|lock_flag_value);
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
if(current==old_count)
{
break;
}
old_count=current_count;
old_count=current;
}
if(old_count&lock_flag_value)
{
bool lock_acquired=false;
void* const sem=get_event();
++old_count; // we're waiting, too
do
{
old_count-=(lock_flag_value+1); // there will be one less active thread on this mutex when it gets unlocked
if(win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until(wait_until))!=0)
{
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
do
old_count&=~lock_flag_value;
old_count|=event_set_flag_value;
while(true)
{
long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,old_count|lock_flag_value,old_count);
if(current_count==old_count)
long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
if(current==old_count)
{
break;
}
old_count=current_count;
old_count=current;
}
while(!(old_count&lock_flag_value));
lock_acquired=!(old_count&lock_flag_value);
}
while(!lock_acquired);
@@ -131,12 +129,14 @@ namespace boost
void unlock()
{
long const offset=lock_flag_value+1;
long old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,(~offset)+1);
if(old_count>offset)
long const offset=lock_flag_value;
long const old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,lock_flag_value);
if(!(old_count&event_set_flag_value) && (old_count>offset))
{
win32::SetEvent(get_event());
if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit))
{
win32::SetEvent(get_event());
}
}
}

View File

@@ -281,14 +281,9 @@ namespace boost
bool interruption_requested() const;
};
inline detail::thread_move_t<thread> move(thread& x)
inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> t)
{
return x.move();
}
inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> x)
{
return x;
return t;
}
template<typename F>

View File

@@ -13,6 +13,7 @@
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/detail/interlocked.hpp>
#include <algorithm>
#if defined( BOOST_USE_WINDOWS_H )
@@ -277,5 +278,113 @@ namespace boost
}
}
#if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)
#if MSC_VER>=1400
extern "C" unsigned char _interlockedbittestandset(long *a,long b);
extern "C" unsigned char _interlockedbittestandreset(long *a,long b);
#pragma intrinsic(_interlockedbittestandset)
#pragma intrinsic(_interlockedbittestandreset)
namespace boost
{
namespace detail
{
namespace win32
{
inline bool interlocked_bit_test_and_set(long* x,long bit)
{
return _interlockedbittestandset(x,bit);
}
inline bool interlocked_bit_test_and_reset(long* x,long bit)
{
return _interlockedbittestandreset(x,bit);
}
}
}
}
#define BOOST_THREAD_BTS_DEFINED
#elif defined(_M_IX86)
namespace boost
{
namespace detail
{
namespace win32
{
inline bool interlocked_bit_test_and_set(long* x,long bit)
{
__asm {
mov eax,bit;
mov edx,x;
lock bts [edx],eax;
setc al;
};
}
inline bool interlocked_bit_test_and_reset(long* x,long bit)
{
__asm {
mov eax,bit;
mov edx,x;
lock btr [edx],eax;
setc al;
};
}
}
}
}
#define BOOST_THREAD_BTS_DEFINED
#endif
#endif
#ifndef BOOST_THREAD_BTS_DEFINED
namespace boost
{
namespace detail
{
namespace win32
{
inline bool interlocked_bit_test_and_set(long* x,long bit)
{
long const value=1<<bit;
long old=*x;
do
{
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old|value,old);
if(current==old)
{
break;
}
old=current;
}
while(true);
return (old&value)!=0;
}
inline bool interlocked_bit_test_and_reset(long* x,long bit)
{
long const value=1<<bit;
long old=*x;
do
{
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old&~value,old);
if(current==old)
{
break;
}
old=current;
}
while(true);
return (old&value)!=0;
}
}
}
}
#endif
#endif