Boost logo

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