Struggling to implement parallel foreach...

Manu turkeyman at gmail.com
Fri Jun 14 09:04:42 UTC 2019


On Fri, Jun 14, 2019 at 1:30 AM Kagamin via Digitalmars-d
<digitalmars-d at puremagic.com> wrote:
>
> On Friday, 14 June 2019 at 01:40:46 UTC, Manu wrote:
> > This has cascading issues; the closure contains references to
> > outer objects, but if the delegate is `shared`, then all those
> > references transitively inherit the shared attribute too. It
> > should work exactly like I if it was writing a `shared` method
> > to some struct, and all the members are shared... so the body
> > of the foreach needs to typecheck assuming the transitive
> > application of the inferred attributes from the opApply
> > signature.
>
> Data attributes on delegates are not well supported because of
> https://issues.dlang.org/show_bug.cgi?id=1983
>
> You have to construct the delegate and call the function in the
> usual way.
>
> > As an experiment, I tried this:
> >
> > void test()
> > {
> >         int x;
> >         void fun() shared
> >         {
> >             x++; // <-- error here
> >         }
> >         fun();
> > }
> >
> > And I got this error:
> >
> > Error: `shared` function `test.fun` cannot access non-shared
> > data `x`
> >
> > That looks like a bug. `fun` is a delegate, and it's shared,
> > which means its `this` pointer is shared, which means `this.x`
> > should be shared... but that seems not to be the case.
> >
> > I think this is a bug. The compile error should have been that
> > I was
> > unable to call fun() with a non-shared delegate (since the
> > calling
> > scope is not shared).
>
> Unqualified local variable is thread local and shouldn't be
> accessed by shared closure, because then it would be implicitly
> shared between threads.

Right, exactly... the compile error should be at the assignment of the
not-shared closure to the shared delegate. The error would be
something like "can't assign `Context*` to `shared(Context)*`".
So, the function can certainly exist, but for shared, you should get
an error when you attempt to call it passing the closure to the
function.
const however would work as expected.

So why do I care about a shared local function? Because I can create
supporting machinery to assert thread-safety and call it correctly,
just like you do to use shared in any way at all. This is an
absolutely necessary step that leads to parallel-for loops... one step
at a time.


More information about the Digitalmars-d mailing list