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:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{}
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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> >:
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user