shared - i need it to be useful

Manu turkeyman at gmail.com
Fri Oct 19 01:09:40 UTC 2018


On Thu, Oct 18, 2018 at 5:30 PM Timon Gehr via Digitalmars-d
<digitalmars-d at puremagic.com> wrote:
>
> On 18.10.18 23:34, Erik van Velzen wrote:
> > If you have an object which can be used in both a thread-safe and a
> > thread-unsafe way that's a bug or code smell.
>
> Then why do you not just make all members shared? Because with Manu's
> proposal, as soon as you have a shared method, all members effectively
> become shared.

No they don't, only facets that overlap with the shared method.
I tried to present an example before:

struct Threadsafe
{
  int x;
  Atomic!int y;
  void foo() shared { ++y; } // <- shared interaction only affects 'y'
  void bar() { ++x; ++y; } // <- not threadsafe, but does not violate
foo's commitment; only interaction with 'y' has any commitment
associated with it
  void unrelated() { ++x; } // <- no responsibilities are transposed
here, you can continue to do whatever you like throughout the class
where 'y' is not concerned
}

In practise, and in my direct experience, classes tend to have exactly
one 'y', and either zero (pure utility), or many such 'x' members.
Threadsafe API interacts with 'y', and the rest is just normal
thread-local methods which interact with all members thread-locally,
and may also interact with 'y' while not violating any threadsafety
commitments.

> It just seems pointless to type them as unshared anyway
> and then rely on convention within @safe code to prevent unsafe
> accesses. Because, why? It just makes no sense.

The pattern, is almost 100% of cses is: owner does all sorts of
stuff... threadsafe interactions with things happen in high-frequency
worker things. Parallel-for type workloads happen in bursts, the rest
of the program works like normal.
Parallel for workloads are restricted to the threadsafe API.

> With the proposal I posted in the beginning, you would then not only get
> implicit conversion of class references to shared, but also back to
> unshared.

I'm not sure how your proposal (which felt way more complicated to me)
improved on my design.
Can you clarify how my very simple design is ineffective?

> I think the conflation of shared member functions and thread safe member
> functions is confusing.

What else can it possibly mean to be a shared method? If it's not
threadsafe, it's an insta-crash...

> shared on a member function just means that the
> `this` reference is shared.

And by extension, you can only interact with other threadsafe methods.

> The only use case for this is overloading on
> shared.

No, it's for separating threadsafe methods from those that aren't.
Just like const methods separate mutating methods from those that don't.

> The D approach to multithreading is that /all/ functions should
> be thread safe, but it is easier for some of them because they don't
> even need to access any shared state. It is therefore helpful if the
> type system cleanly separates shared from unshared state.

This is patently untrue. I can't implement any interesting shared
architecture with the design as is today.
I am also completely free to violate any sense of threadsafety with no
restrictions of any kind.
Write a shared method, access any members, call it from shared
instances, watch the fire burn.

I don't understand how you can claim that D's design says that all
functions are threadsafe, it's so plainly far from the truth...?


More information about the Digitalmars-d mailing list