Socket and spawn()

Jonathan M Davis newsgroup.d at jmdavisprog.com
Sat Jun 1 03:05:47 UTC 2024


On Friday, May 31, 2024 6:28:27 PM MDT Andy Valencia via Digitalmars-d-learn 
wrote:
> On Friday, 31 May 2024 at 16:59:08 UTC, Jonathan M Davis wrote:
>
> Speaking as an old kernel engineer for the Sequent multiprocessor
> product line, this is all very comfortable to me.  I'm very glad
> that D has a suitable selection of spinlocks, process semaphores,
> and memory atomic operations.  I can work with this!

The way that D handles all of this is at its core the same as C/C++. The
main difference is that the type system assumes that anything that isn't
marked as shared or immutable is thread-local and can do optimizations based
on that (though I'm not sure that that actually happens in practice right
now). And in turn, you're supposed to get errors when you do stuff with a
shared object which isn't guaranteed to be thread-safe (though not all of
those checks are enabled by default at the moment).

The result of this is supposed to be that the portions of your code which
are operating on shared data are clearly segregated, whereas in C/C++, the
type system doesn't give you any way of knowing what's actively being shared
across threads. So, in principle, you're writing essentially what you want
have written in C/C++, but the type system is helping you catch when you
screw it up.

The annoying part is that because the compiler can't know when it's actually
thread-safe to access shared data (e.g. it has no clue when the programm
associates a mutex with a set of data), you have to use explicit casts to
thread-local to then be able to operate on the data when it is thread-safe
(unless the type is designed to be used as shared, in which case, it's doing
any necessary casting internally), whereas in C/C++, since the type system
doesn't know or care about thread safety, it'll just let you access data
whether it's properly protected or not.

So, some folks get annoyed by the necessary casting, but in theory, it's the
type system helping to minimize the risk of you shooting yourself in the
foot. The idioms involved are basically the same as those used in C/C++
though, so anyone who understands those should be able to write thread-safe
code in D fairly easily once they understand how shared works.

> > In any case, you can freely cast between thread-local and
> > shared. It's just that you need to be sure that when you do
> > that, you're not violating the type system by having a
> > thread-local reference to shared data access that shared data
> > without first protecting it with a mutex.
>
> That was the trick for me; TLS implied to me that an
> implementation would be free to arrange that the address of a
> variable in one thread's TLS would not necessarily be accessible
> from another thread.  Now I'm clearer on the usage of the term
> WRT the D runtime.  All good.

If you have a module-level or static variable that isn't shared or
immutable, then each thread will get its own copy. So, those _might_ end up
in TLS (I'm not sure if they are right now or not), but if you're just
creating stuff on the fly, none of it is actually in TLS. And it's very
common when dealing with shared or immutable data to create it first as
thread-local and then cast it, since you know that it's not actually shared
across threads at that point, and it's easier to construct that way. If we
did want to start using TLS all over the place, then the casts would have to
take that into account somehow, but I don't expect that that will happen.

- Jonathan M Davis





More information about the Digitalmars-d-learn mailing list