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

Arek via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Aug 14 15:22:58 PDT 2017


On Monday, 14 August 2017 at 21:27:48 UTC, Jonathan M Davis 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. You can send and receive mutable data 
> with no indirections, and AFAIK, you can send immutable data 
> (though the OP is apparently having problems with that, so I 
> guess that that doesn't work completely, though I definitely 
> recall doing so previously), but you get compilation errors if 
> you try to send shared data. For instance, this code
>
> import std.concurrency;
>
> void main()
> {
>     static void func(Tid parent)
>     {
>         auto received = receiveOnly!(shared int[string]);
>     }
>
>     shared int[string] aa;
>
>     auto tid = spawn(&func, thisTid);
>     send(tid, aa);
> }
>

I've found some simple workaround for this problem:

import std.stdio;
import std.concurrency;

struct Envelope(T) if (is(T == class)) // for simplicity of this 
example, only classes
{
	shared(T)[] obj;

	this(shared T o)
	{
		this.obj = [o];
	}

	T get() @property nothrow @nogc
	{
		return cast() obj[0];
	}
}

class A
{

}

void consumer()
{
	auto r = receiveOnly!(Envelope!(A))();
	writeln("Got: ", typeof(r).stringof);
}

void main()
{
	auto cons = spawn(&consumer);
	auto o = Envelope!A(new A());
	send(cons, o);
}

Shared object can be encapsulated in the array. In case of other 
(non-class) types the pointer can be used, and get() should 
return ref to the pointed object (after stripping off the shared 
qualifier).

send() could encapsulate itself shared objectes.

Arek


More information about the Digitalmars-d-learn mailing list