On Wednesday, 8 July 2015 at 14:00:43 UTC, Jonathan M Davis wrote:
On Wednesday, 8 July 2015 at 13:26:53 UTC, Shachar Shemesh
wrote:
On 08/07/15 15:08, Jonathan M Davis wrote:
I know that there are a number of people who get frustrated
with shared
and using __gshared instead, but unless you fully understand
what you're
doing and how the language works, and you're _really_
careful, you're
going to shoot yourself in the foot it subtle ways if you do
that.
I guess my main issue with this statement is that I don't see
how that is not the case when using shared.
Because unless you cast away shared, you're prevented from
doing much of anything to the object, and the compiler clearly
indicates which objects are shared, so the code that has to
worry about getting locks right and dealing with casting away
shared correctly is clearly marked and segregated from the rest
of the program, unlike with a language like C++ or Java where
_everything_ is shared, and you have no idea which objects are
actually shared across threads and which are thread-local.
What we have is uglier than we'd like, but that ugliness
highlights the small portion of code where you actually have to
deal with synchronization and threading issues so that if you
do have a problem with it, you have a very small amount of code
to dig through to figure out how you screwed it up.
- Jonathan M Davis
I think a good way to avoid this extra annoyance would be to have
shared be implicitly convertible to non-shared, or actually,
shared should just be ignored inside synchronized blocks,
essentially the net result is that the cast is done implicitly at
the beginning of the block.
To solve the wrong mutex problem that Dmitry mentioned, perhaps a
declarative approach could be used? I wouldn't mind the extra
syntax, as it also provides documentation by giving clarity into
which mutexes guard what data. With the implicit
stripping/ignoring of shared it would become very succinct as
well.
```
Mutex moomtx;
Mytex cheesemtx;
shared(moomtx) int[] moo;
shared(cheesemtx) float cheese;
or perhaps with UDA:
@lock(globalmtx, moomtx) shared int moo; // either globalmtx or
moomtx must be locked
synchronized(moomtx) {
moomtx = []; // ok
cheese = 1.61803f; // error: mutex moomtx is not locked, even
though we are inside a synchronized block
moo.sort(); // shared automatically ignored
}
// ...
moo.sort(); // error: mutex moomtx is not locked
```