Does anyone understand how to use "shared" types with concurrency send/receive functions?

Steven Schveighoffer via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Aug 15 06:53:05 PDT 2017


On 8/14/17 5:27 PM, Jonathan M Davis via Digitalmars-d-learn wrote:
> On Monday, August 14, 2017 15:22:23 Steven Schveighoffer via Digitalmars-d-
> learn wrote:
>> On 8/13/17 11:40 PM, Jonathan M Davis via Digitalmars-d-learn wrote:
>>> On Saturday, August 12, 2017 18:57:44 Arek via Digitalmars-d-learn
> wrote:
>>>> I have the folowing problem:
>>>> I like to envelope the class object in struct to control the
>>>> destruction moment and then send this object to another
>>>> thread/fiber (or task, cause I use vibe-d).
>>>>
>>>> I can't find any method to make it working. Any ideas?
>>>
>>> Unfortunately, send and receive do not currently work with shared
>>> because of issues with Variant, which they use internally.
>>
>> This can't be a correct statement. This is the whole point of shared.
> 
> What's incorrect about it? It's a longstanding issue that because Variant
> can't contain shared data, send and receive do not work with shared.

The implementation details aren't important. From the documentation (and 
no, this documentation is not wrong):

 From spawn:
args must not have unshared aliasing. In other words, all arguments to 
fn must either be shared or immutable or have no pointer indirection. 
This is necessary for enforcing isolation among threads.

 From send:
As with std.concurrency.spawn, T must not have unshared aliasing.

So clearly passing shared pointers or things containing shared pointers 
should work fine.

As I was building code to test, I found that it does actually work for 
shared int pointers:

import std.concurrency;
import std.typecons;
import std.stdio;
import core.thread;

void threadfunc()
{
     bool done = false;
     while(!done)
     {  receive(
                   (shared(int)*foo) {*foo = 5; done = true;},
                   (Variant v) {}
                   );
     }
}

shared int f;

void main()
{
     auto tid = spawn(&threadfunc);
     tid.send(&f);
     Thread.sleep(1.seconds);
     writeln(f);
}


No error, completes as expected, and outputs 5.

So it looks like this is really a straight up bug and has nothing to do 
with the shared type qualifier. It is documented as working, and does 
work in some cases.

I think if the shared item is not a reference, it is doing something 
different, and this is incompatible with something in the 
implementation. Indeed, if you attempt to send unshared references, you 
get an assert. However, if you send a shared int (not a pointer), you 
get a bunch of compiler errors. Clearly the implementation expects it to 
work, as it doesn't fail the logical checks.

-Steve


More information about the Digitalmars-d-learn mailing list