Update of /cvsroot/boost/boost/boost/thread/win32
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv30554
Modified Files:
Tag: thread_rewrite
read_write_mutex.hpp
Log Message:
Updated read-write mutex implementation to support upgradeable locks too
Index: read_write_mutex.hpp
===================================================================
RCS file: /cvsroot/boost/boost/boost/thread/win32/Attic/read_write_mutex.hpp,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -u -d -r1.1.2.5 -r1.1.2.6
--- read_write_mutex.hpp 5 Oct 2006 09:38:13 -0000 1.1.2.5
+++ read_write_mutex.hpp 5 Oct 2006 14:42:01 -0000 1.1.2.6
@@ -13,18 +13,18 @@
private:
long state;
void* shared_event;
- void* writer_sem;
- void* upgrader_sem;
+ void* exclusive_event;
+ void* upgradeable_event;
- BOOST_STATIC_CONSTANT(long,shared_count_shift=0);
- BOOST_STATIC_CONSTANT(long,shared_count_mask=0x3ff);
- BOOST_STATIC_CONSTANT(long,exclusive_count_shift=10);
- BOOST_STATIC_CONSTANT(long,exclusive_count_mask=0xffc00);
- BOOST_STATIC_CONSTANT(long,shared_mask=0x20000000);
- BOOST_STATIC_CONSTANT(long,upgrading_mask=0x40000000);
- BOOST_STATIC_CONSTANT(long,exclusive_mask=0x80000000);
+ BOOST_STATIC_CONSTANT(long,shared_count_increment=1);
+ BOOST_STATIC_CONSTANT(long,shared_count_mask=0x1fff);
+ BOOST_STATIC_CONSTANT(long,exclusive_count_mask=0x1ffe00);
+ BOOST_STATIC_CONSTANT(long,exclusive_count_increment=0x2000);
+ BOOST_STATIC_CONSTANT(long,shared=0x20000000);
+ BOOST_STATIC_CONSTANT(long,upgradeable=0x40000000);
+ BOOST_STATIC_CONSTANT(long,exclusive=0x80000000);
- template<long lock_mask,long count_mask,long count_increment,long
loop_mask,bool test_first>
+ template<long lock_flags,long unlock_flags,long count_mask,long
count_increment,long loop_mask,bool test_first>
long update_state(long old_state)
{
if(test_first && (old_state&loop_mask))
@@ -33,9 +33,10 @@
}
do
{
- long const new_count=((old_state&count_mask)+count_increment);
+ long const masked_state=old_state&~unlock_flags;
+ long const
new_count=((masked_state&count_mask)+count_increment);
BOOST_ASSERT(new_count<=count_mask);
- long const
new_state=(old_state&~count_mask)|new_count|lock_mask;
+ long const
new_state=(masked_state&~count_mask)|new_count|lock_flags;
long const
current_state=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&state,new_state,old_state);
if(current_state==old_state)
{
@@ -51,36 +52,37 @@
read_write_mutex():
state(0),
shared_event(::boost::detail::CreateEventA(NULL,true,false,NULL)),
- writer_sem(::boost::detail::CreateSemaphoreA(NULL,0,1,NULL)),
- upgrader_sem(::boost::detail::CreateSemaphoreA(NULL,0,1,NULL))
+
exclusive_event(::boost::detail::CreateEventA(NULL,false,false,NULL)),
+
upgradeable_event(::boost::detail::CreateEventA(NULL,false,true,NULL))
{}
~read_write_mutex()
{
::boost::detail::CloseHandle(shared_event);
- ::boost::detail::CloseHandle(writer_sem);
- ::boost::detail::CloseHandle(upgrader_sem);
+ ::boost::detail::CloseHandle(exclusive_event);
+ ::boost::detail::CloseHandle(upgradeable_event);
}
void lock_shareable()
{
// try and add ourselves to the current readers
- long
old_state=update_state<shared_mask,shared_count_mask,1,exclusive_mask,false>(0);
+ long
old_state=update_state<shared,0,shared_count_mask,shared_count_increment,exclusive,false>(0);
- if(!(old_state&shared_mask))
+ if(old_state&exclusive)
{
// someone else has exclusive access
// mark that we're interested
-
old_state=update_state<0,shared_count_mask,1,0,false>(old_state);
+
old_state=update_state<0,0,shared_count_mask,shared_count_increment,0,false>(old_state);
// now we're marked as waiting, if the exclusive lock is now
free, try and claim
// loop until we can claim shared lock
while(true)
{
-
old_state=update_state<shared_mask,0,0,exclusive_mask|shared_mask,true>(old_state);
- if(old_state&shared_mask)
+
old_state=update_state<shared,0,0,0,exclusive|shared,true>(old_state);
+ if(old_state&shared)
{
break;
}
+ old_state&=~(exclusive|shared);
bool const
success=::boost::detail::WaitForSingleObject(shared_event,BOOST_INFINITE)==0;
BOOST_ASSERT(success);
@@ -90,13 +92,14 @@
void unlock_shareable()
{
- long
old_state=update_state<0,shared_count_mask,-1,0,false>(old_state); // decrement
shared count
- if((old_state&shared_count_mask)==1) // if it was just us sharing
+ long
old_state=update_state<0,0,shared_count_mask,-shared_count_increment,0,false>(shared|shared_count_increment);
// decrement shared count
+ if((old_state&shared_count_mask)==shared_count_increment) // if it
was just us sharing
{
-
old_state=update_state<0,shared_mask,-shared_mask,0,false>(old_state);
- if(old_state&exclusive_count_mask)
+ old_state-=shared_count_increment;
+
old_state=update_state<0,shared,0,0,shared_count_mask,true>(old_state);
+ if((old_state&exclusive_count_mask) &&
!(old_state&shared_count_mask))
{
- bool const
res=::boost::detail::ReleaseSemaphore(writer_sem)!=0;
+ bool const
res=::boost::detail::SetEvent(exclusive_event)!=0;
BOOST_ASSERT(res);
}
}
@@ -105,23 +108,24 @@
void lock()
{
// try and acquire an exclusive lock
- long
old_state=update_state<exclusive_mask,exclusive_count_mask,1<<exclusive_count_shift,exclusive_mask|shared_mask>(old_state);
- if(old_state&(exclusive_mask|shared_mask))
+ long
old_state=update_state<exclusive,0,exclusive_count_mask,exclusive_count_increment,exclusive|shared|upgradeable,false>(0);
+ if(old_state&(exclusive|shared|upgradeable))
{
// someone else has the lock
// mark that we're interested
-
old_state=update_state<0,exclusive_count_mask,1,0,false>(old_state);
+
old_state=update_state<0,0,exclusive_count_mask,exclusive_count_increment,0,false>(old_state);
// now we're marked as waiting, if the lock is now free, try
and claim
// loop until we can claim exclusive lock
while(true)
{
-
old_state=update_state<exclusive_mask,0,0,exclusive_mask|shared_mask,true>(old_state);
- if(!(old_state&(shared_mask|exclusive_mask)))
+
old_state=update_state<exclusive,0,0,0,exclusive|shared|upgradeable,true>(old_state);
+ if(!(old_state&(shared|exclusive)))
{
break;
}
+ old_state&=~(exclusive|shared|upgradeable);
- bool const
success=::boost::detail::WaitForSingleObject(writer_sem,BOOST_INFINITE)==0;
+ bool const
success=::boost::detail::WaitForSingleObject(exclusive_event,BOOST_INFINITE)==0;
BOOST_ASSERT(success);
}
}
@@ -131,7 +135,7 @@
void unlock()
{
- long
old_state=update_state<0,exclusive_mask|exclusive_count_mask,-(exclusive_mask |
(1<<exclusive_count_shift)),0,false>(old_state);
+ long
old_state=update_state<0,exclusive,exclusive_count_mask,-exclusive_count_increment,0,false>(exclusive|exclusive_count_increment);
if(old_state&shared_count_mask)
{
bool const success=::boost::detail::SetEvent(shared_event)!=0;
@@ -140,13 +144,132 @@
if(old_state&exclusive_count_mask)
{
- bool const
success=::boost::detail::ReleaseSemaphore(writer_sem)!=0;
+ bool const
success=::boost::detail::SetEvent(exclusive_event)!=0;
BOOST_ASSERT(success);
}
}
+
+ void lock_upgradeable()
+ {
+ // try and acquire an upgrading lock
+ long
old_state=update_state<upgradeable|shared,0,shared_count_mask,shared_count_increment,exclusive|upgradeable,false>(0);
+ if(old_state&(exclusive|upgradeable))
+ {
+ // someone else has the lock
+ // mark that we're interested
+
old_state=update_state<0,0,shared_count_mask,shared_count_increment,0,false>(old_state);
+ // now we're marked as waiting, if the lock is now free, try
and claim
+ // loop until we can claim lock
+
+ void* const handles[2]={upgradeable_event,shared_event};
+
+ while(true)
+ {
+
old_state=update_state<upgradeable|shared,0,0,0,exclusive|upgradeable,true>(old_state);
+ if(!(old_state&(upgradeable|exclusive)))
+ {
+ break;
+ }
+ if(old_state&exclusive) // someone has exclusive lock
+ {
+ // so we can take lock when they release it
+ bool const
success=::boost::detail::SetEvent(upgradeable_event)!=0;
+ BOOST_ASSERT(success);
+ }
+ old_state&=~(exclusive|upgradeable);
+
+ bool const
success=::boost::detail::WaitForMultipleObjects(2,handles,true,BOOST_INFINITE)<2;
+ BOOST_ASSERT(success);
+ }
+ }
+ bool const success=::boost::detail::ResetEvent(shared_event);
+ BOOST_ASSERT(success);
+ }
+
+ void unlock_upgradeable()
+ {
+
update_state<0,upgradeable,0,0,0,false>(upgradeable|shared|shared_count_increment);
// we're not upgrading
+ unlock_shareable(); // and we're not sharing either
+ bool const success=::boost::detail::SetEvent(upgradeable_event)!=0;
+ BOOST_ASSERT(success);
+ }
+
+ void unlock_upgradeable_and_lock()
+ {
+ // try and just change "1 upgrading, shared lock" to "1 exclusive
lock"
+ // we can't do it if there's more than 1 shared lock
+ long old_state=update_state<exclusive,
+ upgradeable|shared,
+ shared_count_mask|exclusive_count_mask,
+ exclusive_count_increment-shared_count_increment,
+ shared_count_mask-shared_count_increment,
+ true>(upgradeable|shared|shared_count_increment);
+ if((old_state&shared_count_mask)!=shared_count_increment)
+ {
+ // We can't upgrade, because there's another shared lock
+ // we're not a shared lock any more, but an
exclusive-lock-to-be
+
old_state=update_state<0,0,exclusive_count_mask|shared_count_mask,exclusive_count_increment-shared_count_increment,0,false>(old_state);
+ old_state+=exclusive_count_increment-shared_count_increment;
+ // if there now aren't any more shared locks, take off the mask
+
old_state=update_state<0,shared,0,0,shared_count_mask,true>(old_state);
+ if(!(old_state&shared_count_mask))
+ {
+ old_state&=~shared;
+ }
+ // now we're marked as waiting, if the lock is now free, try
and claim
+ // loop until we can claim exclusive lock
+ while(true)
+ {
+
old_state=update_state<exclusive,upgradeable,0,0,shared,true>(old_state);
+ if(!(old_state&(shared)))
+ {
+ break;
+ }
+ old_state&=~shared;
+
+ bool const
success=::boost::detail::WaitForSingleObject(exclusive_event,BOOST_INFINITE)==0;
+ BOOST_ASSERT(success);
+ }
+ }
+ bool const success=::boost::detail::ResetEvent(shared_event);
+ BOOST_ASSERT(success);
+ }
+ void unlock_and_lock_upgradeable()
+ {
+ long old_state=update_state<upgradeable|shared,exclusive,
+
shared_count_mask|exclusive_count_mask,shared_count_increment-exclusive_count_increment,
+ 0,false>(exclusive|exclusive_count_increment);
+ if(old_state&shared_count_mask)
+ {
+ bool const success=::boost::detail::SetEvent(shared_event)!=0;
+ BOOST_ASSERT(success);
+ }
+ }
-
+ void unlock_and_lock_shareable()
+ {
+ long old_state=update_state<shared,exclusive,
+
shared_count_mask|exclusive_count_mask,shared_count_increment-exclusive_count_increment,
+ 0,false>(exclusive|exclusive_count_increment);
+ if(old_state&shared_count_mask)
+ {
+ bool const success=::boost::detail::SetEvent(shared_event)!=0;
+ BOOST_ASSERT(success);
+ }
+ }
+
+ void unlock_upgradeable_and_lock_shareable()
+ {
+ long
old_state=update_state<0,upgradeable,0,0,0,false>(upgradeable|shared|shared_count_increment);
+ if((old_state&shared_count_mask)!=shared_count_increment)
+ {
+ bool const success=::boost::detail::SetEvent(shared_event)!=0;
+ BOOST_ASSERT(success);
+ }
+ bool const success=::boost::detail::SetEvent(upgradeable_event)!=0;
+ BOOST_ASSERT(success);
+ }
class scoped_read_lock
{
@@ -166,22 +289,71 @@
class scoped_write_lock
{
read_write_mutex& m;
- boost::mutex::scoped_lock lock;
+ bool locked;
public:
scoped_write_lock(read_write_mutex& m_):
- m(m_),
- lock(m.guard)
+ m(m_),locked(false)
+ {
+ lock();
+ }
+ void lock()
{
m.lock();
+ locked=true;
}
+
void unlock()
{
m.unlock();
+ locked=false;
}
~scoped_write_lock()
{
- if(lock.locked())
+ if(locked)
+ {
+ unlock();
+ }
+ }
+ };
+
+ class scoped_upgradeable_lock
+ {
+ read_write_mutex& m;
+ bool locked;
+ bool upgraded;
+
+ public:
+ scoped_upgradeable_lock(read_write_mutex& m_):
+ m(m_),
+ locked(false),upgraded(false)
+ {
+ lock();
+ }
+ void lock()
+ {
+ m.lock_upgradeable();
+ locked=true;
+ }
+ void upgrade()
+ {
+ m.unlock_upgradeable_and_lock();
+ upgraded=true;
+ }
+ void unlock()
+ {
+ if(upgraded)
+ {
+ m.unlock();
+ }
+ else
+ {
+ m.unlock_upgradeable();
+ }
+ }
+ ~scoped_upgradeable_lock()
+ {
+ if(locked)
{
unlock();
}
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Boost-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/boost-cvs