shared - i need it to be useful
Steven Schveighoffer
schveiguy at gmail.com
Thu Oct 18 14:19:41 UTC 2018
On 10/18/18 10:11 AM, Simen Kjærås wrote:
> On Thursday, 18 October 2018 at 13:35:22 UTC, Steven Schveighoffer wrote:
>> struct ThreadSafe
>> {
>> private int x;
>> void increment()
>> {
>> ++x; // I know this is not shared, so no reason to use atomics
>> }
>> void increment() shared
>> {
>> atomicIncrement(&x); // use atomics, to avoid races
>> }
>> }
>
> But this isn't thread-safe, for the exact reasons described elsewhere in
> this thread (and in fact, incorrectly leveled at Manu's proposal).
> Someone could write this code:
>
> void foo() {
> ThreadSafe* a = new ThreadSafe();
> shareAllOver(a);
Error: cannot call function shareAllOver(shared(ThreadSafe) *) with type
ThreadSafe *
> a.increment(); // unsafe, non-shared method call
> }
>
> When a.increment() is being called, you have no idea if anyone else is
> using the shared interface.
I do, because unless you have cast the type to shared, I'm certain there
is only thread-local aliasing to it.
> This is one of the issues that MP (Manu's Proposal) tries to deal with.
> Under MP, your code would *not* be considered thread-safe, because the
> non-shared portion may interfere with the shared portion. You'd need to
> write two types:
>
> struct ThreadSafe {
> private int x;
> void increment() shared {
> atomicIncrement(&x);
> }
> }
>
> struct NotThreadSafe {
> private int x;
> void increment() {
> ++x;
> }
> }
>
> These two are different types with different semantics, and forcing them
> both into the same struct is an abomination.
Why? What if I wanted to have an object that is local for a while, but
then I want it to be shared (and I ensure carefully when I cast to
shared that there are no other aliases to that)?
> In your case, the user of your type will need to ensure thread-safety.
No, the contract the type provides is: if you DON'T cast unshared to
shared or vice versa, the type is thread-safe.
If you DO cast unshared to shared, then the type is thread-safe as long
as you no longer use the unshared reference.
This is EXACTLY how immutable works.
> You may not have any control over how he's doing things, while you *do*
> control the code in your own type (and module, since that also affects
> things). Under MP, the type is what needs to be thread-safe, and once it
> is, the chance of a user mucking things up is much lower.
Under MP, the type is DEFENSIVELY thread-safe, locking or using atomics
unnecessarily when it's thread-local.
-Steve
More information about the Digitalmars-d
mailing list