March 26, 2019
On Tuesday, 26 March 2019 at 08:34:33 UTC, Kagamin wrote:
> On Monday, 25 March 2019 at 10:39:06 UTC, Stefan Koch wrote:
>> How can I distinguish in the type-system if I get a pointer which others may, write to at the same time?
>
> Qualified as shared, like anything that's not thread local.

Okay, so a shared variable may change at any time.
Is it safe to read or write it then?
March 26, 2019
On Tuesday, 26 March 2019 at 08:35:42 UTC, Kagamin wrote:
> On Monday, 25 March 2019 at 21:04:37 UTC, Rubn wrote:
>> You don't use the type system with thread local data. Using shared, actually creates global data, not thread local data.
>
> Unqualified types are specified to be thread local, so thread local data is definitely expressed in the type system.

__gshared int a;

See above, you have an unqualified type. Would you say it is thread local? Is there any way you can see that it is thread local by the type alone? Are there any guarantees that it won't be accessed by another thread? An unqualified type is bare, it does not provide any thread-safety, you can easy pass it around to another thread to be used and cause race conditions.


Anyways back to the original question you avoided:

> Its meaning is to provide guarantee that thread-local data doesn't have threading issues and I posted the proof of its usefulness.

Why do you think "shared" means thread-local data? And then you go on to say that it is unqualified types? I shall ask again, do you know what thread-local data is ?

March 27, 2019
On Tuesday, 26 March 2019 at 10:12:36 UTC, Stefan Koch wrote:
> Okay, so a shared variable may change at any time.
> Is it safe to read or write it then?

If it fits in the chosen multithreading design.
March 27, 2019
On Tuesday, 26 March 2019 at 21:09:18 UTC, Rubn wrote:
> __gshared int a;
>
> See above, you have an unqualified type. Would you say it is thread local? Is there any way you can see that it is thread local by the type alone?

It has thread local type. It's an escape provided to ease migration from other languages, when it's difficult for whatever reason to have shared data qualified as shared.

>> Its meaning is to provide guarantee that thread-local data doesn't have threading issues and I posted the proof of its usefulness.
>
> Why do you think "shared" means thread-local data? And then you go on to say that it is unqualified types?

shared is a qualifier for data that is not thread local, so that thread local data remains unqualified to reduce churn for it.
March 27, 2019
On Wednesday, 27 March 2019 at 18:25:09 UTC, Kagamin wrote:
> On Tuesday, 26 March 2019 at 21:09:18 UTC, Rubn wrote:
>> __gshared int a;
>>
>> See above, you have an unqualified type. Would you say it is thread local? Is there any way you can see that it is thread local by the type alone?
>
> It has thread local type. It's an escape provided to ease migration from other languages, when it's difficult for whatever reason to have shared data qualified as shared.

Is it thread local data? How do you identify it is not thread-local data by type only (it is unqualified)?

>>> Its meaning is to provide guarantee that thread-local data doesn't have threading issues and I posted the proof of its usefulness.
>>
>> Why do you think "shared" means thread-local data? And then you go on to say that it is unqualified types?
>
> shared is a qualifier for data that is not thread local, so that thread local data remains unqualified to reduce churn for it.

You have not answered the question.
March 31, 2019
On Wednesday, March 27, 2019 2:58:06 PM MDT Rubn via Digitalmars-d wrote:
> On Wednesday, 27 March 2019 at 18:25:09 UTC, Kagamin wrote:
> > On Tuesday, 26 March 2019 at 21:09:18 UTC, Rubn wrote:
> >> __gshared int a;
> >>
> >> See above, you have an unqualified type. Would you say it is thread local? Is there any way you can see that it is thread local by the type alone?
> >
> > It has thread local type. It's an escape provided to ease migration from other languages, when it's difficult for whatever reason to have shared data qualified as shared.
>
> Is it thread local data? How do you identify it is not thread-local data by type only (it is unqualified)?

If you use __gshared, it's up to you to ensure that thread-safety is guaranteed - just like you have to guarantee thread-safety when you cast away shared to operate on a shared object (usually after having locked a mutex to protect it). __gshared is really only intended for linking against C globals (which aren't typed as shared, because C doesn't have shared), and its use in any program should be minimal. Regardless, it's up to the programmer to use it correctly, just like it's up to the programmer to ensure that @trusted code is actually @safe, because as far as the compiler is concerned, __gshared is not part of the type. So, any code using that variable will assume that it's thread-local, leaving it up to the programmer to protect it correctly, whereas with shared, the compiler is supposed to prevent operations that aren't thread-safe (thus usually requiring shared to be cast away to operate on the variable).

- Jonathan M Davis



March 31, 2019
On Wednesday, March 20, 2019 7:25:01 AM MDT Stefan Koch via Digitalmars-d wrote:
> On Tuesday, 19 March 2019 at 21:20:58 UTC, Kagamin wrote:
> > On Tuesday, 19 March 2019 at 20:08:37 UTC, Manu wrote:
> >> Last time we talked about shared, I think we all agreed on one thing; shared should hot have read/write access to data members.
> >>
> >> Does anyone know how to implement this? I would really like to try some important experiments with shared if it worked.
> >
> > shared qualifier provides a guarantee that thread local data is thread local, it doesn't provide safety for concurrency, not supposed to, because it's not realistically feasible at such low level, and attempts to do it like yours only add noise, complicate reasoning and make errors only more likely. Normally it's unshared data that should have a qualifier, because that's actually a feature being provided, but because it would be a nuisance, the opposite was done.
>
> In it's current form the `shared` qualifier is not improving the
> thread-safety
> of D code. Manus proposal does improve thread-safety.
> I am strongly in favor for considering it seriously.
>
> Being conservative and disallowing all access is by far the most
> sensible handling
> if safety is a concern.

shared already prevents some operations that the compiler can't guarantee are thread-safe (e.g. IIRC, ++i on built-in types is disallowed). The problem is that it doesn't prevent all of them, and it can't work properly unless it does, because otherwise it can't make any guarantees about thread-safety, which is one of the main reasons that shared exists. As with @safe, the protections on shared have been added piecemeal over time rather than getting it all figured out up front like ideally would have happened.

- Jonathan M Davis



March 31, 2019
On Monday, March 25, 2019 2:37:42 AM MDT Kagamin via Digitalmars-d wrote:
> On Thursday, 21 March 2019 at 20:50:09 UTC, Manu wrote:
> > But that's now what `shared` does... it allows (guarantees
> > even) many
> > threads mutate the same data at random with no protections.
> > By inhibiting read/write access, you force the user to obtain a
> > lock
> > (or other synchronisation method) in order to access the shared
> > data.
> > Without that, the path of least resistance is to just access
> > the data,
> > and that's a race 100% of the time, by definition (because it's
> > `shared`).
>
> Some memory accesses are thread safe, then synchronization is not needed.

If the compiler can guarantee thread-safety, then there shouldn't be a problem, and nothing needs to be made illegal, but that's usually not the case. The primary exception would be stuff like atomics, and that's typed with shared, so you can pass shared variables to them. And it's not a problem, because thread-safety is guaranteed.

In the cases where synchronization _is_ needed, then those operations should be illegal, requiring the programmer to protect the object appropriately and then cast away shared to operate on it while it's protected. That way, nothing marked as shared is violating thread-safety, and the code where there is a risk of violating thread-safety is @system. So, it becomes fairly easy to grep for the portions of the code where you need to worry about threading bugs.

And of course, because shared functions can operate on shared objects, it's possible to do stuff like encapsulate a mutex inside an object so that it does all of the necessary synchronization internally, and none of the code using that object needs to do any casting or anything else that's @system to use the shared object.

- Jonathan M Davis



April 02, 2019
On Sunday, 31 March 2019 at 07:12:08 UTC, Jonathan M Davis wrote:
> If the compiler can guarantee thread-safety, then there shouldn't be a problem, and nothing needs to be made illegal, but that's usually not the case. The primary exception would be stuff like atomics, and that's typed with shared, so you can pass shared variables to them. And it's not a problem, because thread-safety is guaranteed.

False sense of thread safety already? Code is not magically thread safe because it uses atomics, they are only a tool. Thread safety is a global property and can't be easily provided on low level alone. But added churn can increase mistakes because of increased cognitive load.

> In the cases where synchronization _is_ needed, then those operations should be illegal, requiring the programmer to protect the object appropriately and then cast away shared to operate on it while it's protected. That way, nothing marked as shared is violating thread-safety, and the code where there is a risk of violating thread-safety is @system. So, it becomes fairly easy to grep for the portions of the code where you need to worry about threading bugs.

@safe code might be disallowed to access shared data, that's understandable, but like for @system, it's difficult to provide protection for shared code that can pull its weight.

Also greppability implies that casting away shared is not really inevitable, it's needed if you want to apply algorithm that was written for thread local data, but keeping data and methods as shared will help communicate that it's not an ordinary thing happening here (a use case for private shared methods).
April 03, 2019
On Tue, Apr 2, 2019 at 4:40 AM Kagamin via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On Sunday, 31 March 2019 at 07:12:08 UTC, Jonathan M Davis wrote:
> > If the compiler can guarantee thread-safety, then there shouldn't be a problem, and nothing needs to be made illegal, but that's usually not the case. The primary exception would be stuff like atomics, and that's typed with shared, so you can pass shared variables to them. And it's not a problem, because thread-safety is guaranteed.
>
> False sense of thread safety already? Code is not magically thread safe because it uses atomics, they are only a tool. Thread safety is a global property and can't be easily provided on low level alone. But added churn can increase mistakes because of increased cognitive load.
>
> > In the cases where synchronization _is_ needed, then those operations should be illegal, requiring the programmer to protect the object appropriately and then cast away shared to operate on it while it's protected. That way, nothing marked as shared is violating thread-safety, and the code where there is a risk of violating thread-safety is @system. So, it becomes fairly easy to grep for the portions of the code where you need to worry about threading bugs.
>
> @safe code might be disallowed to access shared data, that's understandable, but like for @system, it's difficult to provide protection for shared code that can pull its weight.
>
> Also greppability implies that casting away shared is not really inevitable, it's needed if you want to apply algorithm that was written for thread local data, but keeping data and methods as shared will help communicate that it's not an ordinary thing happening here (a use case for private shared methods).

I think a lot of people just don't quite visualise what shared means right.

I think it's a fact that `shared` data can not be read/written,
period... not under any circumstance.
If you want to touch it, it's only reasonable to access shared data if
you have confidence that you're the only one accessing it at that
moment. In that sense, it's a reasonable description to say that you
are creating (or asserting) a thread-local context with respect to
that data, and we express that by casting away shared.
It's on you to assure that the thread-local environment you are
assuming is true. The compiler can't help with this.
Taking a mutex is one such form of creating that thread-local context;
if you lock others off from accessing this data, then it is
effectively thread-local to you for that period, so you may cast away
shared and access it during that window.

This code can never be @safe. But it may be tested and @trusted.

Nothing means anything though if you can read/write to shared data as you can right now. If that's possible, shared has no meaning at all, and no value that I can figure.