On Mon, 04 Jun 2012 18:26:50 -0400, Michel Fortin
<[email protected]> wrote:
On 2012-06-04 18:22:22 +0000, "Steven Schveighoffer"
<[email protected]> said:
On Mon, 04 Jun 2012 07:17:45 -0400, Michel Fortin
<[email protected]> wrote:
After trying to make sense of the thread "synchronized
(this[.classinfo]) in druntime and phobos", I had to write my opinion
on all this somewhere that wouldn't be instantly lost in a bazilion
of posts. It turned out into something quite elaborate.
<http://michelf.com/weblog/2012/mutex-synchonization-in-d/>
I like this. But it needs a lot of work.
A few comments:
1. This does not handle shared *at all*. Presumably, there is no
reason to lock unshared data, so this has to be handled somewhere. If
you say "synchronized implies shared", well, then how do you have a
shared int inside an unshared class? My instinct is that all the
methods that need to used synchronized need to be declared shared
(meaning the whole class data is shared). But that sucks, because
what if you have a thread-local instance?
To the type system, the synchronized variable is thread-local with one
restriction: you can only access it inside a synchronized block. So
without the synchronized block you can't read or write to it, and you
can't take its address. Inside the synchronized block, any expression
making use of that variable is tainted by the current scope and must be
pure (weakly). Except if the only result of an expression contains no
indirection (is entirely copied), or is immutable or shared (no
synchronization needed), then the expression does not get tainted and
its result can be sent anywhere.
Note that this taint thing is only done locally inside the synchronized
block: called functions are simply treated as an expression with inputs
and outputs to check whether they are tainted or not.
This feels like the most significant part of this proposal, and I think is
definitely the right track.
I have an idea to solve this. Since the mutexes are implicit, we can
declare space for them, but only allocate them when the class instance
is shared (allocated on construction). Then when synchronized goes to
lock them, if they are null, do nothing.
Or they could simply work like the monitors objects currently have.
Some have stated there is a performance hit for lazy initialization of
monitors. I think we should try and fix that.
As I wrote, I think we need support for shared mutexes too (integrated
with const if you will).
I don't disagree with that approach, except the usage of shared as a
keyword to mean something completely different than it does now.
Ideally, there'd be a way to choose your own mutex implementations,
perhaps with "synchronized(Spinlock) int x".
I like this better, perhaps a synchronized(ReadWriteMutex) would suffice
instead of synchronized(shared)
But what if some data is not marked synchronized?
You might actually want to restrict synchronized variables to shared
classes and shared structs. In that case, variables not marked as
synchronized will be shared and accessible using atomic operations.
I kind of like the idea of having to implement a class/structure once, and
then being able to use it penalty-free in a thread-local context.
Perhaps that's asking too much -- a class that is meant to be shared may
have not a lot in common with one that was meant to be thread-local. It
sure feels like I should be able to (for instance) implement a container
that can be shared or unshared, and change small pieces of it, or add a
few synchronized calls and get it working.
2. As far as determining a mutex to protect multiple items of data,
what about:
synchronized(symbolname) int x, int y;
or
synchronized(symbolname)
{
int x;
int y;
}
where you cannot do synchronized(x) or synchronized(y), and cannot
read or write x or y without doing synchronized(symbolname).
Or we could be less original: use a struct. It's just a minor cosmetic
problem actually.
struct XY { int x, y; }
synchronized XY xy;
True. But sometimes the cosmetic things make all the difference! You
could implement synchronized with structs also instead of having a keyword.
One thing I don't like about this is the xy noise when referring to x and
y.
-Steve