<div class="gmail_quote">On Wed, Jan 20, 2010 at 9:23 AM, Kevin Bealer <span dir="ltr">&lt;<a href="mailto:kevinbealer@gmail.com">kevinbealer@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; BORDER-LEFT: #ccc 1px solid">There is a type of locking pattern that solves this issue.  It involves locks that can be in &quot;read&quot;, &quot;write&quot; or &quot;shared&quot; mode.  The concept is that you get a shared lock when you might want to upgrade to a write lock.<br>
<br>Shared mode can coexist with other threads that are in &quot;read&quot; mode, but is not compatible with other threads that are in write or shared mode.  You can upgrade a shared mode lock to a write lock without deadlocking -- it waits for other threads to finish reading.<br>
<br>The normal usage pattern is that you get a shared mode when you might want to modify something.  Let&#39;s say that a user wants to write a line to a logfile.  You get a shared mode lock on the directory, then check if the file exists.  If it already exists, you downgrade the shared lock to a read lock, then get a write mode lock on the file.  If the file does not exist, you instead upgrade the shared lock to a write lock, then create the file (which is why you needed write permissions), then get a write lock on the new file and downgrade or release the directory lock.<br>
<br>This model of locking cannot deadlock on itself because there is only one &quot;shared&quot; process at a time -- when getting a shared lock, you need to wait for all existing writers to exit, and for any existing shared lock holders to exit or downgrade.  It works best for cases where a processes often thinks it *might* need to do a write operation but usually doesn&#39;t, in which case it reduces lock contention for reader threads.  The most common situation is where you don&#39;t know if you need to do the write until you&#39;ve done some reads to asses the current situation.<br>
<br>I know we used locks like this when I was at IBM.  I wish I could find out who invented this so I know whether it is patented.  (IBM loves patents -- I suspect it isn&#39;t patented but I haven&#39;t found a good writeup of it online yet.)<br>
<font color="#888888"><br>Kevin</font> 
<div>
<div></div>
<div class="h5"> </div></div></blockquote>
<div> </div>
<div>Never mind that last bit, I just noticed that read/write/shared locks as I describe here are available in boost.  The patent I remember had something to do with specifics of how it was implemented.</div>
<div> </div>
<div>Kevin<br></div>
<blockquote class="gmail_quote" style="PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; BORDER-LEFT: #ccc 1px solid">
<div>
<div class="h5">
<div class="gmail_quote">On Wed, Jan 20, 2010 at 7:28 AM, Michel Fortin <span dir="ltr">&lt;<a href="mailto:michel.fortin@michelf.com" target="_blank">michel.fortin@michelf.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="PADDING-LEFT: 1ex; MARGIN: 0pt 0pt 0pt 0.8ex; BORDER-LEFT: rgb(204,204,204) 1px solid">Le 2010-01-20 à 2:07, Sean Kelly a écrit :<br>
<div><br>&gt; Is what you want in core.sync.rwmutex?  You can use it as:<br>&gt;<br>&gt; synchronized( mut.reader ) {}<br>&gt; synchronized( mut.writer ) {}<br>&gt;<br>&gt; It doesn&#39;t currently allow upgrading read locks to write locks, though I think this wouldn&#39;t be difficult to add.  More importantly I suppose is that acquiring a concurrent read lock may be more expensive than you&#39;d expect, so you really only want to use a ReadWriteMutex if the read operations take a reasonable amount of time to complete.<br>
<br></div>What happens if you call test() here?<br><br>       void test() {<br>               synchronized (mut.reader) {<br>                       // read A<br>                       testWrite();<br>                       // read B<br>
               }<br>       }<br><br>       void testWrite() {<br>               syncrhonized (mut.writer) {<br>                       // write C<br>               }<br>       }<br><br>I guess that if you haven&#39;t implemented upgrades this will deadlock.<br>
<br>I&#39;d like to note that even upgrading the lock to a write lock might be a problem: as I said in my other message, making this an automatic upgrade might force the release the reader lock until the writer lock is acquired, which would be unexpected from test()&#39;s point of view.<br>
<br>This could work well as a transaction, where a failure to upgrade the lock would throw an exception, &quot;read A&quot; would be rollbacked, and the synchronized part would be attempted again. But without proper logic to deal with the unfortunate case of a failed upgrade you have either a race or a deadlock here.<br>

<div><br>--<br>Michel Fortin<br><a href="mailto:michel.fortin@michelf.com" target="_blank">michel.fortin@michelf.com</a><br><a href="http://michelf.com/" target="_blank">http://michelf.com/</a><br><br><br><br>_______________________________________________<br>
</div>
<div>
<div></div>
<div>dmd-concurrency mailing list<br><a href="mailto:dmd-concurrency@puremagic.com" target="_blank">dmd-concurrency@puremagic.com</a><br><a href="http://lists.puremagic.com/mailman/listinfo/dmd-concurrency" target="_blank">http://lists.puremagic.com/mailman/listinfo/dmd-concurrency</a><br>
</div></div></blockquote></div><br></div></div></blockquote></div><br>