www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - shared - no read/write access

reply Manu <turkeyman gmail.com> writes:
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.
Mar 19 2019
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2019-03-19 21:08, 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.
Not exactly sure of what you're looking for but write access is already disable [1].
 Does anyone know how to implement this? I would really like to try
 some important experiments with shared if it worked.
If it's only the read access that is left to disable I recommend looking at how the write access is disable and try to do the same for read. I suggest to do a project wide search for the error message for write operations, seems pretty unique. Then go from there. [1] https://run.dlang.io/is/ZJ5maE -- /Jacob Carlborg
Mar 19 2019
next sibling parent Rubn <where is.this> writes:
On Tuesday, 19 March 2019 at 20:16:03 UTC, Jacob Carlborg wrote:
 On 2019-03-19 21:08, 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.
Not exactly sure of what you're looking for but write access is already disable [1].
 Does anyone know how to implement this? I would really like to 
 try
 some important experiments with shared if it worked.
If it's only the read access that is left to disable I recommend looking at how the write access is disable and try to do the same for read. I suggest to do a project wide search for the error message for write operations, seems pretty unique. Then go from there. [1] https://run.dlang.io/is/ZJ5maE
Only read-write-modify are disabled, you can still write as long as you don't read from it at the same time. shared int global; shared class Foo { int a; } void main() { auto foo = new shared Foo; foo.a = 1; }
Mar 19 2019
prev sibling next sibling parent Rubn <where is.this> writes:
On Tuesday, 19 March 2019 at 20:16:03 UTC, Jacob Carlborg wrote:
 On 2019-03-19 21:08, 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.
Not exactly sure of what you're looking for but write access is already disable [1].
 Does anyone know how to implement this? I would really like to 
 try
 some important experiments with shared if it worked.
If it's only the read access that is left to disable I recommend looking at how the write access is disable and try to do the same for read. I suggest to do a project wide search for the error message for write operations, seems pretty unique. Then go from there. [1] https://run.dlang.io/is/ZJ5maE
A more obvious example of it being misused: shared int global; shared class Foo { int a; } void main() { auto foo = new shared Foo; foo.a = foo.a + 1; }
Mar 19 2019
prev sibling parent Manu <turkeyman gmail.com> writes:
On Tue, Mar 19, 2019 at 1:20 PM Jacob Carlborg via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 2019-03-19 21:08, 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.
Not exactly sure of what you're looking for but write access is already disable [1].
 Does anyone know how to implement this? I would really like to try
 some important experiments with shared if it worked.
If it's only the read access that is left to disable I recommend looking at how the write access is disable and try to do the same for read. I suggest to do a project wide search for the error message for write operations, seems pretty unique. Then go from there. [1] https://run.dlang.io/is/ZJ5maE -- /Jacob Carlborg
Erm, change `++` to `= 10`. Read/write from a shared thing should be a compile error in every circumstance.
Mar 19 2019
prev sibling next sibling parent jmh530 <john.michael.hall gmail.com> writes:
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.
This looks like a good place to start: https://github.com/dlang/dmd/commit/7535f3dc86e9e88c4ee609dd98b5305224c3b88a
Mar 19 2019
prev sibling parent reply Kagamin <spam here.lot> writes:
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.
Mar 19 2019
next sibling parent Manu <turkeyman gmail.com> writes:
On Tue, Mar 19, 2019 at 2:25 PM Kagamin via Digitalmars-d
<digitalmars-d puremagic.com> 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.
I have literally no idea what you're talking about.
Mar 19 2019
prev sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
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.
Mar 20 2019
next sibling parent reply Kagamin <spam here.lot> writes:
On Wednesday, 20 March 2019 at 13:25:01 UTC, Stefan Koch wrote:
 In it's current form the `shared` qualifier is not improving 
 the thread-safety
 of D code.
It does, proof: https://issues.dlang.org/show_bug.cgi?id=6585
 Being conservative and disallowing all access is by far the 
 most sensible handling
 if safety is a concern.
Added noise and cognitive load on programmer causes more bugs, not more safety. shared is already restrictive enough to handle, making it more restrictive will only make people give up on it more often.
Mar 20 2019
parent reply Manu <turkeyman gmail.com> writes:
On Wed, Mar 20, 2019 at 11:20 AM Kagamin via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Wednesday, 20 March 2019 at 13:25:01 UTC, Stefan Koch wrote:
 In it's current form the `shared` qualifier is not improving
 the thread-safety
 of D code.
It does, proof: https://issues.dlang.org/show_bug.cgi?id=6585
That is most certainly not a bug, that's absolutely 100% correct behaviour. It's absolutely not okay to pass a pointer to shared data to memcpy! It needs some external synchronisation, and then cast shared away when you know you have a thread-local lock on it.
 Being conservative and disallowing all access is by far the
 most sensible handling
 if safety is a concern.
Added noise and cognitive load on programmer causes more bugs, not more safety. shared is already restrictive enough to handle, making it more restrictive will only make people give up on it more often.
So, just to be clear, you favour shared being broken and meaningless to actually meaning something and being useful? I don't have the energy to repeat the last uber-thread on the issue; you'll find the full discussion in the forum history.
Mar 20 2019
parent reply Kagamin <spam here.lot> writes:
On Wednesday, 20 March 2019 at 20:15:23 UTC, Manu wrote:
 So, just to be clear, you favour shared being broken and 
 meaningless
 to actually meaning something and being useful?
Its meaning is to provide guarantee that thread-local data doesn't have threading issues and I posted the proof of its usefulness.
Mar 21 2019
next sibling parent reply Rubn <where is.this> writes:
On Thursday, 21 March 2019 at 19:03:23 UTC, Kagamin wrote:
 On Wednesday, 20 March 2019 at 20:15:23 UTC, Manu wrote:
 So, just to be clear, you favour shared being broken and 
 meaningless
 to actually meaning something and being useful?
Its meaning is to provide guarantee that thread-local data doesn't have threading issues and I posted the proof of its usefulness.
If the data is thread local, then it is already guaranteed to have no conflict with other threads. Hence it being "thread local", only the local thread can access the data. There's no need for a "shared" qualifier in this regard.
Mar 21 2019
parent reply Kagamin <spam here.lot> writes:
On Thursday, 21 March 2019 at 19:50:31 UTC, Rubn wrote:
 If the data is thread local, then it is already guaranteed to 
 have no conflict with other threads. Hence it being "thread 
 local", only the local thread can access the data. There's no 
 need for a "shared" qualifier in this regard.
In case of D the claim doesn't hang in a vacuum, but is supported by the type system.
Mar 25 2019
parent reply Rubn <where is.this> writes:
On Monday, 25 March 2019 at 08:36:42 UTC, Kagamin wrote:
 On Thursday, 21 March 2019 at 19:50:31 UTC, Rubn wrote:
 If the data is thread local, then it is already guaranteed to 
 have no conflict with other threads. Hence it being "thread 
 local", only the local thread can access the data. There's no 
 need for a "shared" qualifier in this regard.
In case of D the claim doesn't hang in a vacuum, but is supported by the type system.
You don't use the type system with thread local data. Using shared, actually creates global data, not thread local data. I'll ask this now since it seems you are talking mostly gibberish. Do you even know what thread local data is ?
Mar 25 2019
parent reply Kagamin <spam here.lot> writes:
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.
Mar 26 2019
parent reply Rubn <where is.this> writes:
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 ?
Mar 26 2019
parent reply Kagamin <spam here.lot> writes:
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.
Mar 27 2019
parent reply Rubn <where is.this> writes:
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.
Mar 27 2019
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
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
Mar 31 2019
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On Thu, Mar 21, 2019 at 12:05 PM Kagamin via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Wednesday, 20 March 2019 at 20:15:23 UTC, Manu wrote:
 So, just to be clear, you favour shared being broken and
 meaningless
 to actually meaning something and being useful?
Its meaning is to provide guarantee that thread-local data doesn't have threading issues and I posted the proof of its usefulness.
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`).
Mar 21 2019
parent reply Kagamin <spam here.lot> writes:
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.
Mar 25 2019
next sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Monday, 25 March 2019 at 08:37:42 UTC, Kagamin 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.
So what you are saying is that shared can thread-safe; For access where synchronization is not needed. In those cases it technically does not matter if the data is shared or not. Let's talk about the case now where data is actually shared between threads, How can I distinguish in the type-system if I get a pointer which others may, write to at the same time? Cheers, Stefan
Mar 25 2019
parent reply Kagamin <spam here.lot> writes:
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.
Mar 26 2019
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
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?
Mar 26 2019
parent Kagamin <spam here.lot> writes:
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.
Mar 27 2019
prev sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
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
Mar 31 2019
parent reply Kagamin <spam here.lot> writes:
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).
Apr 02 2019
next sibling parent Manu <turkeyman gmail.com> writes:
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.
Apr 03 2019
prev sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Tuesday, April 2, 2019 5:37:20 AM MDT Kagamin via Digitalmars-d 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.
Atomics guarantee that the read/write operations are thread-safe, but no they obviously can't guarantee things like that a set of interrelated variables whose values should be kept in sync are actually protected against multiple threads mucking with them at once. So, maybe a better way to put it is that the compiler won't allow operations that it can't guarantee are atomic (or which are marked shared).
 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).
Greppability just means that you can easily find the code in question, and between the keywords shared, cast, trusted, and system, it should be easy to quickly narrow down the code that involves casting away shared and thus find the code that has to be closely examined for threading issues. And code involving atomics is easily greppable - and thus easily findable - for the same reason. And no, it shouldn't be the case that everything using a shared variable has to constantly cast away shared to do anything with it, because those operations can be encapsulated in functions - a prime example of that being an object that has its own mutex to protect its data. Nothing using the object would need to cast away shared, but internally, that's exactly what the object would need to do in order to actually mutate the data. That's already true to an extent, because some read/write operations are illegal on shared objects and have been for some time. The problem is that they aren't all illegal. So, instead of the whole thing being set up so that you clearly have to cast away shared to mutate data, you end up only having to cast it away some of the time, just increasing the annoyance factor. Either we need to go all the way and make all non-atomic read/write operations illegal on shared data or just give up on shared providing any protections at all beyond ensuring that code not involving casts can't make the type system treat shared data as thread-local or vice versa. - Jonathan M Davis
Apr 03 2019
prev sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
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
Mar 31 2019