Struggling to implement parallel foreach...
Timon Gehr
timon.gehr at gmx.ch
Mon Jun 17 01:38:57 UTC 2019
On 17.06.19 03:17, Manu wrote:
> 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.
It's not common sense, it's nonsense. It should be common sense that it
is nonsense. I don't understand how you can possibly reach that
conclusion. Closures with an immutable-qualified context can only
capture immutable variables. What is so surprising about this?
> inout is fine too, just like const.
Absolutely not. You can't implicitly promote stuff to `inout`.
> 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.
This idea is not at all contingent on the nonsensical parts of your
vision, but I don't know if there is a simple way to make this work. It
will require more care.
>>From there, parallel foreach can be implemented as a @trusted function.
>
So your evil master plan is:
1. Make qualified local functions useless.
2. Make qualified local functions more useful.
3. Profit.
Just skip phase 1, please.
More information about the Digitalmars-d
mailing list