Walter is right about transitive readonly - here's the alternative

Sean Kelly sean at f4.ca
Thu Sep 13 13:53:27 PDT 2007


Janice Caron wrote:
> On 9/13/07, Steven Schveighoffer <schveiguy at yahoo.com> wrote:
>>> My C++ implementation used an atomic counter for read locks, an atomic
>>> counter for (pending) write locks, and an OS mutex.
>> Using atomic counters, how do you read the write counter, then increment the
>> read counter atomically without using the mutex?
> 
> You don't have to make the entire process atomic, just the increments
> and decrements.
> 
> getWriteLock()
> {
>     atomicIncrement(wcount);
>     obtainMutex();
> }
> 
> releaseWriteLock()
> {
>     releaseMutex();
>     atomicDecrement(wcount);
> }
> 
> getReadLock()
> {
>     while (wcount != 0)
>     {
>         obtainMutex();
>         releaseMutex();
>     }
>     if (atomicIncrement(rcount) == 1)
>     {
>         obtainMutex();
>     }
> }
> 
> releaseReadLock()
> {
>     if (atomicDecrement(rcount) == 0)
>     {
>         releaseMutex();
>     }
> }
> 
> I think that's right. That's from memory. If it's wrong, I can't check
> until tomorrow. It looks right to me though.

To pick a nit, I think the above code may have some problems.

Scenario 1:

* Thread A acquires a write lock, mutates the protected data, and
   releases the lock.
* Thread B acquires a read lock and stalls.
* Thread C acquires a read lock.

   Here, because wcount is 0, thread C will never call obtainMutex and 
therefore may view bad data.

Scenario 2:

* Thread A acquires a read lock and stalls.
* Thread B attempts to acquire a write lock, increments wcount, and
   blocks on obtainMutex.
* Thread C attempts to acquire a read lock, sees wcount is nonzero and
   blocks on obtainMutex.

   Here, thread C should be allowed to proceed and read the protected 
data but blocks instead.

There may be others as well, but I think the above is sufficient to 
illustrate that multithreaded programming at the typical level (manual 
locking, etc) is really quite difficult and therefore probably not an 
ideal goal for future language development.  I'll admit I do like the 
idea of a programmer declaring intent to read/write data, but I do 
wonder if additional integrated locking is the best way to go about 
solving this particular issue.  Perhaps the basic concept could be 
applied another way?


Sean



More information about the Digitalmars-d mailing list