| |
 | Posted by Jonathan M Davis in reply to Guillaume Piolat | Permalink Reply |
|
Jonathan M Davis 
Posted in reply to Guillaume Piolat
| On Saturday, April 19, 2025 6:47:31 AM MDT Guillaume Piolat via dip.ideas wrote:
> On Wednesday, 16 April 2025 at 22:46:32 UTC, Dave P. wrote:
> > A long time ago, global variables and static variables in D were changed to be thread local by default. I think this has proven to mostly be a bad idea, for a few reasons:
> >
> > - Violates the “looks like C principle”: Code that looks like C
> > should either behave the same as C or not compile.
> > - Unexpected: No other language defaults to TLS.
> > - Unwanted: Most of the time you don’t actually want thread
> > local variables. If you want global state you either want
> > immutability or synchronized access (mutexes) through something
> > like shared. TLS is the exception.
> > - Not as safe as it looks: thread local variables still have
> > many of the problems of global variables, such as having to
> > worry about function re-entrancy.
> >
> > So I propose to make it an error to have it be unspecified if a static variable is shared, __gshared, immutable or thread local. Additionally, add a thread_local storage class so you can explicitly opt into TLS for when you actually want that.
> >
> > Changing this might require a new edition, but who knows.
>
> +1
> It really brings zero benefit to have it implicit (when did you
> really want that). We should finally admit to that being a
> mistake.
>
> If the goal was "no sharing by default", then explicit TLS keeps that goal.
Not really. If anything, it gets rid of the default and then forces you to add extra attributes to types all over the place in order to be explicit.
The current situation largely works extremely well, because having variables not be shared across threads is almost always what you want, and it's required for memory safety, because you can't access variables which are shared across threads in thread-safe manner without extra machinery to ensure that those reads and writes are thread-safe.
I can understand there being some frustration when porting code, because the type systems of other languages like C do not encode whether something is shared across threads or not, but the fact that D has that distinction helps localize threading issues and is required for the memory safety guarantees that the language is supposed to be providing. And because very little code in general is sharing anything across threads, the amount of code that needs to encode that distinction in the types is small. So, the number of explicit attributes required is small. But if we got rid of the default and required that it be explict, then that would literally mean adding an additional attribute onto almost every time everywhere, which would be incredibly verbose.
And if the argument is that static variables or module-level variables should be treated differently and require an explicit attribute which is the opposite of shared, then that would create a pretty massive inconsistency in how types are dealt with for this one corner case that's really only an issue when porting code. And in my experience, static and module-level variables are almost always thread-local just like the rest of the objects in the program. It's just specific sections of multi-threaded code that needs to worry about shared, and __gshared is really only supposed to be used when binding to C globals anyway - and the fact that __gshared is shared but typed as thread-local is actually a hole in @safe, though now that we have @system variables, we could fix it so that all __gshared variables are @system, which would fix that problem.
- Jonathan M Davis
|