Walter is right about transitive readonly - here's the alternative
Regan Heath
regan at netmail.co.nz
Thu Sep 13 03:22:44 PDT 2007
I'm still taking this is, on the surface (my first impression) is that
it sounds like a good idea. I do have a couple of comments...
Janice Caron wrote:
> There is no magic bullet to thread-safety. This mechanism does ensure
> that multiple threads won't try to access the same variable at the
> same time, but what it /won't/ do is prevent deadlocks.
What sort of deadlocks, this sort...
[thread1]
scope a = readable(x);
--context switch here--
scope b = readable(y);
[thread2]
scope b = readable(y);
--or context switch here--
scope a = readable(x);
(caused by a timing issue)
or, this sort:
[thread1]
scope a = readable(x);
scope b = readable(x); //deadlocks unless locks are re-entrant
(this one occurs in a number of forms, but the basic problem is the same)
Currently "synchronized" in D is reentrant :)
> It's also
> still possible to screw up. For instance - you cannot get a write lock
> if you already hold a lock...
>
> scope a = readable(x);
> scope b = writable(x); /* Error - b is already locked by this thread */
You mean "x is already locked.." :)
> That error is not always detectable by the compiler.
Does it 'break' the system to allow a thread with a read lock to aquire
a write lock (assuming we block until no other thread has a read lock)?
If one of the goals of this system is to prevent aliasing style
problems, eg.
int a;
foo(&a,&a);
void foo(int *a, int *b)
{
if (b == 5) return ;
*a = 5;
//oops b == 5 now
}
?
If not then we may be able to handle this case with some clever locking
routines.
One observation; as these variables are scoped you know that if you
already have a read lock then the write lock lifetime is equal to or
less than the read lock lifetime.
And vice-versa. So, how about the opposite case:
scope b = writable(x);
scope a = readable(x);
Allowed? Error? Can we also handle this case?
I suspect it might be possible to handle it but I am not sure.
> And you have to be aware that other threads may modify shared things
> when they're not locked.
At first this comment seemed contrary to the whole purpose of your idea,
that is until I realised you meant "you have to be aware that other
threads may modify shared things when /you haven't got them locked
yourself/"
So, just to clarify under your system the only time a shared object may
change is when it's locked by the thread making the change, correct?
> 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.
It would therefore be quite beneficial to allow overlapping/simultaneous
read/write locks (in a single thread), if at all possible.
It seems like it may be possible to code this idea up as a library
solution, hmmm...
Regan
More information about the Digitalmars-d
mailing list