July 15, 2021

On Thursday, 15 July 2021 at 13:12:34 UTC, Paul Backus wrote:

>

@safe code can't access __gshared data.

We're talking about @system code and whether it can be @trusted.

July 15, 2021

On Thursday, 15 July 2021 at 13:16:01 UTC, Sebastiaan Koppe wrote:

>

Yes that is the sensible thing to do. But I am not sure that is the right thing. I am afraid that it will lead to the conclusion that everything needs to be shared, because who is going to stop someone from taking your struct/class/function, moving it over to another thread and then complain it corrupts memory while it was advertised as having a @safe interface?

If you share an object between threads, it must be typed as shared. Then someone can only call those methods that are also marked shared. Those methods are thread-safe. If someone casts shared away, it's on them to ensure thread-safety.

July 15, 2021

On Thursday, 15 July 2021 at 13:16:01 UTC, Sebastiaan Koppe wrote:

>

On Thursday, 15 July 2021 at 12:35:29 UTC, Petar Kirov [ZombineDev] wrote:

>

On Wednesday, 14 July 2021 at 19:10:55 UTC, Sebastiaan Koppe

>

Because member functions are harder to call from multiple threads than static functions are. For one, you will have to get the object on two threads first. Most functions that do that require a shared object, which requires a diligent programmer to do the casting.

The problem with std.stdio : std{in,out,err} is they ought to be defined (conceptually) as shared Atomic!File, where File is essentially a wrapper around SharedPtr!FileState (and SharedPtr does atomic ref-counting, if it's shared) and until then, they shouldn't be @trusted, unless the program is single-threaded.

Yes that is the sensible thing to do. But I am not sure that is the right thing. I am afraid that it will lead to the conclusion that everything needs to be shared, because who is going to stop someone from taking your struct/class/function, moving it over to another thread and then complain it corrupts memory while it was advertised as having a @safe interface?

Not quite. If an aggregate has no methods marked as shared, it means that in essence it's not designed to be shared across threads (i.e it's not thread-safe). Just like const methods define the API of const object instances, shared methods define the API of shared objects. While it can be useful to overload methods based on the this type qualifier (e.g. I added shared overloads to the lock, unlock and tryLock methods of core.sync.mutex : Mutex (*)), it's not strictly necessary. It's perfectly possible to have a class which has one set of functions of single-thread use and a complete separate set of thread-safe functions. As an example, a simple non-thread-safe queue class can have front, push, pop and empty methods, while a thread-safe variant will instead have tryGetFront, tryPush, tryPop (and no empty) methods.

>

I am afraid that it will lead to the conclusion that everything needs to be shared

This is the sort thinking common in languages like C# and Java (at least, in my experience), where you don't know whether your class may be shared across threads, so you either find out eventually the hard way (via bug reports), or (e.g. if requested by code reviewers) you go in and preemptively add locks all over the code (usually not tested well, since you your initial use-case didn't involve sharing the object across threads).

This is not the case in D. If your aggregate doesn't have shared methods it means that it must not be shared, plain and simple.

That's why __gshared should be avoided - it shares both thread-safe and non-thread-safe objects across threads. A __gshared Mutex will work just fine (as the underlying Posix/Win32 primitives are obviously designed support it), but other types, like D's associative arrays would certainly go kaboom, if access to them is not synchronized externally (**).

In case of Phobos, std.stdio : std{in,out,err} should really be made thread-safe (you can find issues in bugzilla), as the whole idea of making them global mutable properties is to allow any thread to redirect them at any point of time. Whether that's a good idea is a separate topic, but it was certainly an intended case.

(*) core.sync.mutex : Mutex.{lock, unlock, tryLock} really should have been shared @safe nothrow @nogc from the beginning, but hey better late, then never :)
I considered removing the non-shared overloads, but I decided against, as that would have been a breaking change. That said, once we have enough high-quality APIs in Phobos to allow ergonomic use of shared (i.e. not requiring people to cast-away shared all over the place), we should consider deprecating them (the non-shared overloads of lock/unlock/tryLock).

(**) Another way to discuss shared is to think in terms of internal and external synchronization. If a method is shared, it follows that access to the underlying object is internally synchronized, i.e. you don't need an external mutex to guard it. And vice versa - if the methods are not shared, it means that you need to use external synchronization, and only then (assuming you have implemented it correctly), you can cast away shared and freely call the non-shared methods inside the scope of the lock. See Rust's Mutex and more specifically the MutexGuard types for a good example of this technique. Given a type like Rust's MutexGuard, casting-away shared should really not be done in user-code - the idea is that the MutexGuard will give you a safe scope-ed access to a head-un-shared type (given shared(SomeType**) it will give you scope shared(SomeType*)*).

P.S. I use the term "method" when I mean non-static member function, and "aggregate" when I mean struct, class, or interface type.

July 15, 2021

On Thursday, 15 July 2021 at 13:10:44 UTC, Sebastiaan Koppe wrote:

>

But does that all imply that we have to make all non-threadsafe functions @system? How can we every be @safe?

TL;DR of my previous post is "no" as the answer to your question. It's perfectly fine to develop/use @safe non-shared code. That should actually be the default for most projects. You should mark code as @system only if it implicitly uses shared data (no matter if it is actually marked as shared) without internal synchronization. In the case of trustedStdout it really should be @system as from the outside (it's signature) it looks like it gives access to a thread-local object, but it's actually returning an implicitly-shared one (meaning it has shared global mutable state, even though it's not marked as shared).

Another TL;DR:

  • @safe shared -> thread-safe
  • @safe and not shared -> safe in single-threaded code; unusable if shared, unless externally synchronized correctly
  • @system and not shared -> beware! Tricky to use safely even with external synchronization, as there could be other code that uses this without any synchronization outside of your control
July 15, 2021

On Thursday, 15 July 2021 at 17:17:53 UTC, Petar Kirov [ZombineDev] wrote:

>

[..] You should mark code as @system only if it implicitly uses shared data [..]

I mean "only" in the context of multi-threading, other memory/type safety issues not withstanding.

July 16, 2021

On Sunday, 4 July 2021 at 15:31:31 UTC, Bastiaan Veelo wrote:

>

I don't know when the episode on D will be made, and it might be interesting if multiple solutions using different styles are available. Anyway, tweaks will be accepted until a final comparison in the last episode.

-- Bastiaan.

Why not ldc2 instead of gdc?

July 16, 2021

On Friday, 16 July 2021 at 08:07:27 UTC, Andrea Fontana wrote:

>

Why not ldc2 instead of gdc?

Solution2 uses ldc2.

— Bastiaan.

July 29, 2021

On Tuesday, 13 July 2021 at 23:23:56 UTC, SealabJaster wrote:

>

On Tuesday, 13 July 2021 at 22:11:34 UTC, SealabJaster wrote:

>

...

https://github.com/PlummersSoftwareLLC/Primes/pull/407

@_@ Finally decided to run the full benchmark.

On my weak linux machine, it comes out at 68(CT) 76(RT) out of 191 for the single threaded version.

For the multithreaded we're at 39(CT) and 43(RT) out of 52.

I've also managed to get WSL to run it now, so I'll report back on the results from my main machine.

July 29, 2021

On Thursday, 29 July 2021 at 07:16:41 UTC, SealabJaster wrote:

>

...

Scratch WSL, it's super weird and kind of awful.

Anyway, another PR: https://github.com/PlummersSoftwareLLC/Primes/pull/541

1 2 3
Next ›   Last »