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

Janice Caron caron800 at googlemail.com
Thu Sep 13 11:26:45 PDT 2007


On 9/13/07, Steven Schveighoffer <schveiguy at yahoo.com> wrote:
> Without remembering which threads have read locks, you can just use a simple
> reference counter to tell if a object is read-locked.

My C++ implementation used an atomic counter for read locks, an atomic
counter for (pending) write locks, and an OS mutex.


> When "upgrading" becomes possible, then you have to know whether the thread
> you are in holds a read-lock or not.  This means you have to store (probably
> in the mutex itself) a list of all threads that hold the read-lock.  Then
> when you go to do the upgrade, it must check to see if the upgrading thread
> is in the list.  This is at least a O(lg(n)) operation, whereas a reference
> counter is a O(1).

...and it must do all that ATOMICALLY. Forget it. You'd have to mutex
lock the mutex.

Upgrading just isn't possible in any case - not even in /theory/, let
alone in a given implementation.


> BTW I think you could do reentrant read locks (just increment/decrement the
> reference counter one extra time)

Yes, read locks are inherently re-entrant.


> and write locks could be reentrant (only
> have to store one thread id, you could even use the same reference counter
> as the read locks).

My implementation wasn't re-entrant for write locks. I never found it
necessary. That said, I know that it is possible to make re-entrant
write locks, but probably not by the means that you suggest.



> So the only really "bad" situation is:
>
> readable(o);
> writable(o);

You cannot get a write lock if you already have a read lock on the
same object. It is impossible. That is a deadlock.


> This really seems awfully scary.  This really could result in an easy
> deadlock, where code that holds a read lock could call code that eventually
> grabs a write-lock.

The trick is not to lock things for longer than you actually need to
access them.

Even without fancy wrappers, that holds true. If you do mutexes
manually, you are expected to release them as soon as you've finished
with them.


> I'm thinking now that the best thing is just to use read-write locks, unless
> you really know what you are doing, and own all the code that accesses a
> shared object.

Ah, but that could lead to even more deadlocks. If a hundred threads
all want to read a resource at the same time,  and we can guarantee
that no one's writing to it at the time,
why not let them?


> I guess I'll cancel my vote for this as a language feature.  Better left as
> a library feature.  Sorry Janice :(

Hehehe.

It cannot be a library feature, because it cannot be implemented in a
library, because to implement it in a library, you'd need transitive
const, or logical const.

:-)



More information about the Digitalmars-d mailing list