On 15 November 2012 15:00, Jonathan M Davis <span dir="ltr"><<a href="mailto:jmdavisProg@gmx.com" target="_blank">jmdavisProg@gmx.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div class="im">On Thursday, November 15, 2012 14:32:47 Manu wrote:<br>
> On 15 November 2012 13:38, Jonathan M Davis <<a href="mailto:jmdavisProg@gmx.com">jmdavisProg@gmx.com</a>> wrote:<br>
<br>
</div><div class="im">> I don't really see the difference, other than, as you say, the cast is<br>
> explicit.<br>
> Obviously the possibility for the situation you describe exists, it's<br>
> equally possible with the cast, except this way, the usage pattern is made<br>
> more convenient, the user has a convenient way to control the locks and<br>
> most importantly, it would work with templates.<br>
> That said, this sounds like another perfect application of 'scope'. Perhaps<br>
> only scope parameters can receive a locked, shared thing... that would<br>
> mechanically protect you against escape.<br>
<br>
</div>You could make casting away const implicit too, which would make some code<br>
easier, but it would be a disaster, because the programer wouldn't have a clue<br>
that it's happening in many cases, and the code would end up being very, very<br>
wrong. Implicitly casting away shared would put you in the same boat.</blockquote><div><br></div><div>... no, they're not even the same thing. const things can not be changed.</div><div>Shared things are still mutable things, and perfectly compatible with other non-shared mutable things, they just have some access control requirements.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> _Maybe_ you could get away with it in very restricted circumstances where both pure<br>

and scope are being used, but then it becomes so restrictive that it's nearly<br>
useless anyway. And again, it would be hidden from the programmer, when this<br>
is something that _needs_ to be explicit. Having implicit locks happen on you<br>
could really screw with any code trying to do explicit locks, as would be<br>
needed anyway in all but the most basic cases.<br></blockquote><div><br></div><div>I think you must have misunderstood my suggestion, I certainly didn't suggest locking would be implicit.</div><div>All locks would be explicit, all I suggested is that shared things would gain an associated mutex, and an implicit assert that said mutex is locked whenever it is accessed, rather than deny assignment between shared/unshared things.</div>
<div><br></div><div>You could use lock methods, or a nice alternative would be to submit them to some sort of synchronised scope like luka illustrates.</div><div><br></div><div>I'm of the opinion that for the time being, explicit lock control is mandatory (anything else is a distant dream), and atomic primitives may not be relied upon.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="im">
> 2. It's often the case that you need to lock/unlock groups of stuff together<br>
> > such that locking specific variables is of often of limited use and would<br>
> > just<br>
> > introduce pointless extra locks when dealing with multiple variables. It<br>
> > would<br>
> > also increase the risk of deadlocks, because you wouldn't have much - if<br>
> > any -<br>
> > control over what order locks were acquired in when dealing with multiple<br>
> > shared variables.<br>
><br>
> Your fear is precisely the state we're in now, except it puts all the work<br>
> on the user to create and use the synchronisation objects, and also to<br>
> assert that things are locked when they are accessed.<br>
> I'm just suggesting some reasonably simple change that would make the<br>
> situation more usable and safer immediately, short of waiting for all these<br>
> fantastic designs being discussed having time to simmer and manifest.<br>
<br>
</div>Except that with your suggestion, you're introducing potential deadlocks which<br>
are outside of the programmer's control, and you're introducing extra overhead<br>
with those locks (both in terms of memory and in terms of the runtime costs).<br>
Not to mention, it would probably cause all kinds of issues for something like<br>
shared int* to have a mutex with it, because then its size is completely<br>
different from int*. It also would cause even worse problems when that shared<br>
int* was cast to int* (aside from the size issues), because all of the locking<br>
that was happening for the shared int* was invisible. If you want automatic<br>
locks, then use synchronized classes. That's what they're for.<br>
<br>
Honestly, I really don't buy into the idea that it makes sense for shared to<br>
magically make multi-threaded code work without the programmer worrying about<br>
locks. Making it so that it's well-defined as to what's atomic is great for<br>
code that has any chance of being lock-free, but it's still up to the<br>
programmer to understand when locks are and aren't needed and how to use them<br>
correctly. I don't think that it can possibly work for it to be automatic.<br>
It's far to easy to introduce deadlocks, and it would only work in the<br>
simplest of cases anyway, meaning that the programmer needs to understand and<br>
properly solve the issues anyway. And if the programmer has to understand it<br>
all to get it right, why bother adding the extra overhead and deadlock<br>
potential caused by automatically locking anything? D provides some great<br>
synchronization primitives. People should use them.<br></blockquote><div><br></div><div>To all above:</div><div>You've completely misunderstood my suggestion. It's basically the same as luka.</div><div>It's not that hard, shared just assists the user do what they do anyway by associating a lock primitive, and implicitly assert it is locked when accessed.</div>
<div>No magic should be performed on the users behalf.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
I think that the only things that share really needs to be solving are:<br>
<br>
1. Indicating to the compiler via the type system that the object is not<br>
thread-local. This properly segregates shared and unshared code and allows the<br>
compiler to take advantage of thread locality for optimizations and avoid<br>
optimizations with shared code that screw up threading (e.g. double-checked<br>
locking won't work if the compiler does certain optimizations).<br>
<br>
2. Making it explicit and well-defined as part of the language which operations<br>
can assumed to be atomic (even if it that set of operations is very small,<br>
having it be well-defined is valuable).<br>
<br>
3. Ensuring sequential consistency so that it's possible to do lock-free code<br>
when atomic operations permit it and so that there are fewer weird issues due<br>
to undefined behavior.<br>
<span class=""><font color="#888888"><br>
- Jonathan M Davis<br>
</font></span></blockquote></div><br></div>