Thread overview
std.concurrent Tid vector initialization problem
Jun 28, 2015
Charles Hixson
Jun 28, 2015
Ali Çehreli
Jun 28, 2015
Marc Schütz
Jun 30, 2015
Charles Hixson
Jul 01, 2015
Marc Schütz
June 28, 2015
I'm planning an application where a series of threads each need to be aware of the Tids of all the others.  The number won't be known at compile time, but that doesn't seem to change the design.

All I've been able to come up with is a pair of loops, one to spawn the threads, and collect their Tids, and a second for each one to send its Tid to all the others.  receive doesn't seem to want to work with shared Tids.  My original design was to have a file level shared array of Tids, but receive (or possibly send) objected to attempts to use them.  They aren't known until they've been spawned, so I can't pass them as spawn parameters.  Etc.

This seems like a very clumsy initialization design.  Does anyone have a better idea?

(The rough estimate of the number of Tids is six, but that's likely to change from run to run.)
June 28, 2015
On 06/27/2015 06:00 PM, Charles Hixson via Digitalmars-d-learn wrote:
> I'm planning an application where a series of threads each need to be
> aware of the Tids of all the others.  The number won't be known at
> compile time, but that doesn't seem to change the design.
>
> All I've been able to come up with is a pair of loops, one to spawn the
> threads, and collect their Tids, and a second for each one to send its
> Tid to all the others.  receive doesn't seem to want to work with shared
> Tids.  My original design was to have a file level shared array of Tids,
> but receive (or possibly send) objected to attempts to use them.  They
> aren't known until they've been spawned, so I can't pass them as spawn
> parameters.  Etc.
>
> This seems like a very clumsy initialization design.  Does anyone have a
> better idea?
>
> (The rough estimate of the number of Tids is six, but that's likely to
> change from run to run.)

register(), unregister(), and locate() may be useful:

  http://dlang.org/phobos/std_concurrency.html#.register

I have a short example in the "Thread names" section here:

  http://ddili.org/ders/d.en/concurrency.html

Ali

June 28, 2015
On Sunday, 28 June 2015 at 01:02:02 UTC, Charles Hixson wrote:
> I'm planning an application where a series of threads each need to be aware of the Tids of all the others.  The number won't be known at compile time, but that doesn't seem to change the design.
>
> All I've been able to come up with is a pair of loops, one to spawn the threads, and collect their Tids, and a second for each one to send its Tid to all the others.  receive doesn't seem to want to work with shared Tids.  My original design was to have a file level shared array of Tids, but receive (or possibly send) objected to attempts to use them.  They aren't known until they've been spawned, so I can't pass them as spawn parameters.  Etc.
>
> This seems like a very clumsy initialization design.  Does anyone have a better idea?
>
> (The rough estimate of the number of Tids is six, but that's likely to change from run to run.)

The most elegant solution I can think of is this:

struct Go { }

__gshared const Tid[] allTids;

void myfunc(...) {
    receiveOnly!Go();
    // do the work
}

shared static this() {
    Tid[] tids;
    foreach(thread; threads)
        tids ~= spawn(&myfunc, ...);
    *cast(const(int)[]*) &allTids = tids;
    foreach(tid; allTids)
        tid.send(Go());
}

I believe the cast is not even undefined behaviour, because it's not immutable, but I'm not sure. But the const-ness guards against accidental modification of `allTids` by a thread.

Alternatively, you could make `allTids` private, provide a public getter, and implement the threads in another module.

Or you could simply leave the global array mutable and be careful not to modify it.
June 30, 2015
On Sunday, 28 June 2015 at 09:59:29 UTC, Marc Schütz wrote:
> On Sunday, 28 June 2015 at 01:02:02 UTC, Charles Hixson wrote:
>> I'm planning an application where a series of threads each ...gn.  Does anyone have a better idea?
>>
>> (The rough estimate of the number of Tids is six, but that's likely to change from run to run.)
>
> The most elegant solution I can think of is this:
>
> struct Go { }
>
> __gshared const Tid[] allTids;
>
> void myfunc(...) {
>     receiveOnly!Go();
>     // do the work
> }
>
> shared static this() {
>     Tid[] tids;
>     foreach(thread; threads)
>         tids ~= spawn(&myfunc, ...);
>     *cast(const(int)[]*) &allTids = tids;
>     foreach(tid; allTids)
>         tid.send(Go());
> }
>
> I believe the cast is not even undefined behaviour, because it's not immutable, but I'm not sure. But the const-ness guards against accidental modification of `allTids` by a thread.
>
> Alternatively, you could make `allTids` private, provide a public getter, and implement the threads in another module.
>
> Or you could simply leave the global array mutable and be careful not to modify it.

Thanks.  That sounds similar to the approach that I had though of, except that you're doing it in a static this().

(I'd have answered sooner, but my D email seems to have died.  Only the D groups are currently dead now, though my entire account was dead for a couple of weeks.  [AT&T])

July 01, 2015
On Tuesday, 30 June 2015 at 19:19:43 UTC, Charles Hixson wrote:
> On Sunday, 28 June 2015 at 09:59:29 UTC, Marc Schütz wrote:
>> On Sunday, 28 June 2015 at 01:02:02 UTC, Charles Hixson wrote:
>>> I'm planning an application where a series of threads each ...gn.  Does anyone have a better idea?
>>>
>>> (The rough estimate of the number of Tids is six, but that's likely to change from run to run.)
>>
>> The most elegant solution I can think of is this:
>>
>> struct Go { }
>>
>> __gshared const Tid[] allTids;
>>
>> void myfunc(...) {
>>     receiveOnly!Go();
>>     // do the work
>> }
>>
>> shared static this() {
>>     Tid[] tids;
>>     foreach(thread; threads)
>>         tids ~= spawn(&myfunc, ...);
>>     *cast(const(int)[]*) &allTids = tids;
>>     foreach(tid; allTids)
>>         tid.send(Go());
>> }
>>
>> I believe the cast is not even undefined behaviour, because it's not immutable, but I'm not sure. But the const-ness guards against accidental modification of `allTids` by a thread.
>>
>> Alternatively, you could make `allTids` private, provide a public getter, and implement the threads in another module.
>>
>> Or you could simply leave the global array mutable and be careful not to modify it.
>
> Thanks.  That sounds similar to the approach that I had though of, except that you're doing it in a static this().
>
> (I'd have answered sooner, but my D email seems to have died.  Only the D groups are currently dead now, though my entire account was dead for a couple of weeks.  [AT&T])

That `shared static this` isn't really necessary here. I originally had an immutable `allTids`, for which it was necessary.