Walter is right about transitive readonly - here's the alternative
Sean Kelly
sean at f4.ca
Thu Sep 13 09:05:03 PDT 2007
Janice Caron wrote:
>
> To recap...
>
> It is a compile-time error to refer to the member variables of
> b.a_shared directly. Instead, you must obtain a second reference to
> b.a_shared, using either readable(b) or writable(b), and you can
> access the member variables /only/ through those. The locks are scoped
> so that the mutexes always get released.
What if I only plan to use the class within a single thread and don't
want to pay for the cost of a lock? Also, how would this apply to a
linked-list container? Would each node have to be shared and thus have
its own lock, or would the outermost one suffice?
> And you have to be aware that other threads may modify shared things
> when they're not locked. For example, my lookup-from-file class
> becomes
>
> class Lookup
> {
> shared int[int] map_s;
>
> int readonly lookup(int key)
> {
> {
> auto map = readable(map_s);
> if (key in map) return map[key];
> }
> {
> auto map = writable(map_s);
> if (key in map) return map[key]; /* pay attention */
>
> /* read stuff from file and store it in map */
>
> return map[key];
> }
> }
> }
>
> See how I had to check the cache twice? Once while readable, then
> again while writable? That's because, between the unlocking of the
> read lock and the locking of the write lock, another thread could have
> got in and updated the map.
I'll admit I do really like the idea that the programmer's intention is
made explicit using this approach. Logical const basically provides
blanket protection and then gives the programmer a pair of scissors
which can be used to cut holes in the blanket. This requires the
programmer to state explicitly "I plan to read this value" or "I plan to
write this value" in a way that the compiler can check. Also, I don't
know why, but it seems like this may integrate well with transactional
memory somehow.
Sean
More information about the Digitalmars-d
mailing list