More synchronized ideas
Steven Schveighoffer
schveiguy at yahoo.com
Wed Jun 6 05:12:42 PDT 2012
On Mon, 04 Jun 2012 18:26:50 -0400, Michel Fortin
<michel.fortin at michelf.com> wrote:
> On 2012-06-04 18:22:22 +0000, "Steven Schveighoffer"
> <schveiguy at yahoo.com> said:
>
>> On Mon, 04 Jun 2012 07:17:45 -0400, Michel Fortin
>> <michel.fortin at michelf.com> 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
More information about the Digitalmars-d
mailing list