DLF September 2023 Monthly Meeting Summary

matheus matheus at gmail.com
Mon Nov 13 04:47:42 UTC 2023


On Monday, 13 November 2023 at 04:46:44 UTC, matheus wrote:
> ...

Part 3:

Átila

Átila said he'd asked Roy after DConf if he wanted to write a 
spec for the new shared semantics but hadn't yet received a 
reply. He thought we could go ahead with it anyway, as it's 
probably going to be obvious in all the cases what we should do.

He'd also been thinking about Robert's suggestions regarding safe 
code, and the more he'd done so, the more they made sense. He 
didn't think we needed to wait for editions, because then we 
could solve all the problems we've had with DIP 1000, possibly in 
one fell swoop. The whole issue was we were making people have to 
add scope everywhere because they use @safe, even if the 
functions weren't doing anything "unscopey". They wouldn't have 
to anymore because it would only apply to @trusted. He thought we 
should go ahead with that, too.

Another thing: he'd been trying to play around with Timon's idea 
of pointers that have a compile-time enum saying if they're 
isolated or not. He wanted to do a proof of concept with a vector 
type and some allocators to see what that looks like. That might 
inform some decisions on how to add isolated to the language.

He'd also been thinking about how we could do editions.

I brought up an email Átila had sent recently about what features 
should go in the next edition. I suggested that's not what we 
need to be thinking about right now. We should first define 
exactly how editions were going to be implemented. For example, 
Walter had suggested the approach of attaching editions to module 
declarations. There are other possibilities. So we need to define 
what that looks like first. We should also be thinking about 
which features we need to have stabilized in the current 
language, which is going to be the default edition. What's broken 
now that we're not going to fix now, but want to defer until the 
first new edition?

Átila agreed. He said he'd wanted to know what we could maybe do 
with the new edition so that it could inform what potential 
issues could arise rather than dealing with it in the abstract. 
It's more because of that. Not even, "that's what we're going to 
do", but "what would we do if we could do anything" so that we 
could think of what could go wrong.

I thought this should be a high priority for us. I proposed that 
we put it on the agenda of our next planning session. Everyone 
agreed.

(SPOILER: I'll post the September planning update a day or so 
after this summary, but in that session, we agreed that Átila 
would write up the proposal for editions by November 1st. We've 
since extended that to December.)

Before yielding his time, Átila said he'd like to write a program 
that fetches all of the dub packages and checks which ones still 
built so he could get a list of stuff we need to test the kinds 
of modifications like the shared and safe stuff, along with as 
many future dub packages as possible, instead of the 
hand-selected, curated list we have now.

Dennis thought even Phobos would break. He said that DIP 1000 was 
not a breaking change. The breaking change was fixing the accepts 
invalid bug that, so far, slicing a local static array has been 
allowed. Robert's proposal was strictly more breakage than DIP 
1000.

Átila said he understood that, but that code was obviously wrong 
anyway. The code was broken. It's just that the compiler didn't 
tell people. And the issue with DIP 1000 was adoption. The issue 
with that was having to add scope everywhere.

I said that's the kind of thing I was talking about earlier. If 
fixing shared or scope or anything was going to break a lot of 
code, shouldn't we defer fixing them to a new edition and not do 
it in the default language? Walter said DIP 1000 clearly had to 
be in an edition.

Átila said, "Okay." But the shared thing is a no-brainer. The 
code is completely wrong and we're not going to break anything by 
lowering it to atomics. Walter agreed.

Timon asked if the idea is to do operations on shared variables 
atomically. Walter said yes, for the ones where the CPU supports 
an atomic operation. If the CPU doesn't support an atomic 
operation on a variable, then it will not be allowed. It varies 
by target.

Timon said yes, but an atomic operation is not the only way to 
synchronize something. Átila said that's true, but the thing is, 
there's always an opt-out by casting away shared yourself. If 
you're going to do something to shared directly, you should 
either pass it to a function that takes shared, or cast it away 
and lock a mutex, or whatever you want.

Timon brought up Manu's push to just reject all of those 
operations. Átila said that doesn't work. He'd been trying to fix 
it this year and it's been one bug after another. Timon asked 
what the issue with that was. Átila said there were many, but 
gave one example: synchronized(mutex) doesn't compile with 
-preview=nosharedaccess because you're accessing the mutex. The 
runtime doesn't build with it and Phobos won't either. He'd been 
trying to plug the holes and he realized at DConf that it's 
better not to try to do that at all. Instead, just lower it to an 
atomic in every one of those cases. If it doesn't compile, then 
it doesn't compile. What are you trying to do with it anyway?

Walter told Timon that the problem was you couldn't pass a shared 
value as an argument. If you've created a shared pointer to 
something, you can't do anything with it because it's shared. If 
you want to access the shared pointer, you have to pass it by 
reference to std.atomic. However, there are instructions on the 
CPU to atomically load a pointer type and other basic types. Why 
not take advantage of that and allow shared operations when the 
target CPU can support them directly?

Timon said it seems that we'll always synchronize. Átila said 
that's better than the world right now. And again, if that's the 
case and your profile shows that's your problem, cast shared away.

Walter said it's also less efficient to always be calling the 
std.atomic functions when you can just use the CPU instructions 
if it has them. Timon said it seems the solution to that should 
be intrinsics. The proposal seems like intrinsics but with nicer 
syntax. He thought there were some decisions about how to do the 
synchronization exactly that you're kind of locking this default 
syntax into when you do this.

Átila said the default is to do something sensible. If you want 
to do something else, you can. Timon said what is sensible 
semantics for your atomic load and store may depend on the 
context. Átila agreed, but for most cases, it's going to be 
sequential consistency. Again, if you want something else, then 
you use something else. If you explicitly say, "atomic load with 
something else", then that's fine. That's what happens. You 
should still be able to write code that does explicit atomic 
load, store, fetch, add, whatever, and it should just work. It 
won't add to that, because then we would have failed.

Timon said it could just contribute to the confusion because the 
code will do some synchronization stuff implicitly, but you have 
to think about it from, like, both threads if they're 
participating in it. If it's implicit, you kind of don't see it 
in code anymore. To him, that's a less good solution than having 
it fail compilation if you don't do it right.

Walter said it's the same issue we have with vector instructions. 
If the instruction exists for the operation you requested in the 
code, the compiler will generate the vector instruction for you. 
If the instruction doesn't exist on the target CPU, the compiler 
will fail to compile and you get to decide what alternate path 
you want to take. So what it means is that if it compiles, it 
will work. If it fails to compile on your target machine, you're 
going to have to figure out a workaround for it.

Walter continued, saying that if the CPU has instructions to do 
an atomic load of an integer, the compiler will support that and 
it will give you atomic loads. If you're compiling for a CPU that 
does not support atomic loads of an integer, it will fail to 
compile. This is exactly the way vector instructions work. He 
thought we'd been successful with that. He's happy with it.

He said that means that when you move to different platforms, 
maybe your shared code will break, and maybe not. But that's kind 
of how it should be, because shared is implicitly wrapped up with 
how the CPU is constructed. So that's what he thought we should 
do.

Timon asked what happens if you're in a heterogeneous system that 
has different kinds of hardware operating on the same memory, 
with different coherency guarantees and features. How does the 
compiler know about this?

Walter and Átila both said that it doesn't. Átila said you cast 
away shared and you do your weird stuff yourself because he 
didn't know how we could support that. Walter agreed. Timon said 
that was the point of saying that if it's shared, you have to do 
something sensible on your own, the compiler will not assume that 
doing certain things is sensible. Walter said the compiler 
assumes what's sensible based on the CPU it's targeting.

Timon said yes, but in concurrent program, the compiler knows 
what it's generating the code for now, but it doesn't know what 
other devices are on the same system and accessing this memory. 
Walter said Timon was suggesting that the lock instruction on a 
CPU was completely useless. Timon said he wasn't saying that. You 
should probably specify what you want. Átila said you can. Timon 
said that definitely you can, it's just that to him, the 
reasoning made sense that there is no sensible default. But of 
course, they could disagree with that and say the sensible 
default is sequential consistency, assuming that all the threads 
are running on this CPU that you're compiling for. It's just a 
different trade-off.

Walter said he's going to assume that the CPU maker hasn't 
screwed up with the implementation of shared loads. Timon 
emphasized he was just saying there is not a single way to 
synchronize access. Átila reiterated that you can do your own 
synchronization instead. And if you're somebody who cares about 
this, that's what you're going to be doing anyway.

Given that we'd already gone over two hours and a few 
participants had dropped out, Walter suggested we cut this 
particular discussion here and consider putting a cap on long 
discussions in the future.
Walter

Walter said he'd been able to fix a bunch of things that had come 
up at DConf. He was very disappointed that he'd been forced to 
adopt Microsoft assembly syntax for ImportC because they offered 
no path through their header files that didn't end up using their 
version of inline assembler. We'll see how that works out.

He'd spent a lot of time converting his DConf presentation into 
an article.

He'd also been working on 'The Didacticus' for D, a set of 
general design principles that would be congruent with our vision 
of changing the way programmers think. We'd never really sat down 
and made a list of the general principles that make D a unique 
and useful language. He thought it was long past time. He'd 
written up a draft form that he'd sent to a couple of people. He 
hoped everyone was happy with that.

(UPDATE: Right now, Walter is currently working on what I think 
is the fourth, or maybe fifth, draft of the principles. He 
started with a list of the principles themselves and then refined 
that list, and has since been expanding on defining and 
describing them. Once he's finished, we'll publish this on the 
website alongside the DLF's vision statement and that of each DLF 
associate.)

Conclusion
This meeting was followed by a planning session on the 23rd. We 
then had a quarterly meeting with industry reps on October 6th. 
Our next monthly was on October 13th.

That's it!

Matheus.


More information about the Digitalmars-d-announce mailing list