Struggling to implement parallel foreach...

Manu turkeyman at gmail.com
Mon Jun 17 01:17:43 UTC 2019


On Sun, Jun 16, 2019 at 6:00 PM Kagamin via Digitalmars-d
<digitalmars-d at puremagic.com> wrote:
>
> On Saturday, 15 June 2019 at 06:13:09 UTC, Manu wrote:
> > struct S
> > {
> >   void method() shared;
> > }
> >
> > void test()
> > {
> >   S s;
> >   void localFun() shared
> >   {
> >     s.method(); // <- s must transitively receive const from the
> > context pointer, otherwise this doesn't work
> >   }
> > }
> >
> > Current semantics would reject this, because s is not shared,
> > and
> > therefore not accessible by localFun.
> > The unnecessary complexity inhibits the only useful thing that a
> > shared function can do.
>
> Declare `s` as shared and it will work. It would receive
> qualifier from context, but unshared variables can't be captured
> by shared closure to begin with because unshared data can't part
> of shared context, because that would break the guarantee that
> unshared data shouldn't be shared. Currently compiler implements
> check which variables can be captured and which can't.

I don't think the capture should be shared, only the function argument
has the shared attribute applied, ie:
Capture cap;
void localFun(shared(Capture)* ctx);
localFun(cap); // <- error: can't pass `Context*` to
`shared(Context)*`... form there, we can begin to do something
interesting.

In you consider the const case, this will work perfectly fine, and
everything will be as expected with absolutely no magic of any kind.
immutable local functions can not be called under any circumstances;
this seems like common sense to me.
inout is fine too, just like const.
shared is the interesting one; we shouldn't be able to pass the
capture to the function because Context* -> shared(Context)*, but we
can start to talk about ways this can work.
One way is that the promotion is actally perfectly valid! Because you
are calling a local function from the local thread; so the shared
function will have a shared reference to the local context only for
the life of the function call, and when it returns, the shared
reference must end with the function. We can do this by declaring the
local function: `void localFun(scope shared(Context)* ctx);`
A shared local function is valid so long as that function does NOT
escape any of those shared references. It might want to attribute
`return` too.
>From there, parallel foreach can be implemented as a @trusted function.


More information about the Digitalmars-d mailing list