www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Problem with receiveOnly and classes

reply Ghislain <no_spam no_spam.com> writes:
Hello,

I need to pass objects of a hierarchy between threads and I have some 
troubles.

The sample code below displays:
Unknown
B.fun()

I do not understand why an object of type A is fetched as a Variant, while 
a object of type B is received correctly.

Instead of 
	(A a){a.fun();}
I also tried 
	(immutable(A) a){a.fun();}
which resulted in 
core.exception.AssertError /usr/include/d/dmd/phobos/std/variant.d(286): 
immutable(A)

Any idea?
I am using dmd 2.057 with linux.

Thanks

import std.stdio;
import std.concurrency;

class A{
	public:
		void fun()const{
			writeln("A.fun()");
		}
};
class B : A{
	public:
		override void fun()const{
			writeln("B.fun()");
		}
};

void producer(Tid t){	
	auto a = new immutable(A);
	auto b = new immutable(B);
	t.send(a);
	t.send(b);
}

void main(){
	auto t = spawn(&producer, thisTid);
	while(1){
		receive( 
			(A a){a.fun();},
			(Variant v){writeln("Unknown");}
			);
	}
}
Mar 25 2012
parent reply kraybourne <stdin kraybourne.com> writes:
On 3/25/12 19:33 , Ghislain wrote:
 Hello,

 [...]
 I do not understand why an object of type A is fetched as a Variant, while
 a object of type B is received correctly.

 [...]
 Any idea?

Hi! I get the same on Mac DMD 2.058. I have no idea. Looks like a bug to me, although I can't say which part is wrong/right. The chapter on concurrency in TDPL ( http://www.informit.com/articles/article.aspx?p=1609144&seqNum=6 ) only ever uses values and arrays as examples, and ddocs sort of strategically says nothing, so I guess it's not really clear if passing objects should be possible at all? Either way, I once tried to pass over "ownership" of trees of objects to other threads but gave up on that. I don't think std.concurrency and D really can work like that. (?) Concurrency seems to work much better when you pass messages and data, structs are fine, and then build object trees from that on the other side etc. Sorry I can't help more.
Mar 27 2012
parent Ghislain <no_spam no_spam.com> writes:
 Either way, I once tried to pass over "ownership" of trees of objects to
 other threads but gave up on that. I don't think std.concurrency and D
 really can work like that. (?) Concurrency seems to work much better
 when you pass messages and data, structs are fine, and then build object
 trees from that on the other side etc. Sorry I can't help more.

I finally found a solution, thanks to your post: make a struct holding the object (and alias it so I can use it "nearly" transparently). I do not really like it, but it solves my problem. Would it be possible to integrate this into std.concurrency? I am newbie in D (my background is C++) Here is sample code: import std.stdio; import std.concurrency; class A{ public: void fun()const{ writeln("A.fun()");} } class B : A{ public: override void fun()const{ writeln("B.fun()");} } immutable struct P(T){ public: immutable(T) t; alias t this; this(immutable(T) _t)immutable{ t = _t; } } void producer(Tid t){ auto a = new immutable(A); auto b = new immutable(B); auto p1 = new P!A(a); auto p2 = new P!A(b); t.send(p1); t.send(p2); } void main(){ auto t = spawn(&producer, thisTid); while(1){ receive( (P!A* a){ writeln("matched P!A*"); a.fun(); }, (Variant v){ writeln("Unknown"); } ); } }
Apr 01 2012