|
Boost-Commit : |
From: anthony_at_[hidden]
Date: 2008-05-04 18:39:52
Author: anthonyw
Date: 2008-05-04 18:39:52 EDT (Sun, 04 May 2008)
New Revision: 45119
URL: http://svn.boost.org/trac/boost/changeset/45119
Log:
new BTS-based mutex implementation on win32
Text files modified:
trunk/boost/thread/win32/basic_timed_mutex.hpp | 56 ++++++++++----------
trunk/boost/thread/win32/thread_primitives.hpp | 109 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 137 insertions(+), 28 deletions(-)
Modified: trunk/boost/thread/win32/basic_timed_mutex.hpp
==============================================================================
--- trunk/boost/thread/win32/basic_timed_mutex.hpp (original)
+++ trunk/boost/thread/win32/basic_timed_mutex.hpp 2008-05-04 18:39:52 EDT (Sun, 04 May 2008)
@@ -21,7 +21,10 @@
{
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 @@
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 @@
}
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 @@
#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 @@
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());
+ }
}
}
Modified: trunk/boost/thread/win32/thread_primitives.hpp
==============================================================================
--- trunk/boost/thread/win32/thread_primitives.hpp (original)
+++ trunk/boost/thread/win32/thread_primitives.hpp 2008-05-04 18:39:52 EDT (Sun, 04 May 2008)
@@ -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 @@
}
}
+#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
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk