std.concurrency and immutable

Shammah Chancellor anonymous at coward.com
Mon Nov 25 03:48:06 PST 2013


On 2013-11-25 06:03:27 +0000, Antoche said:

> The following code compiles but doesn't work as expected:
> 
>       import std.stdio;
>       import std.concurrency;
> 
>       class A
>       {
>           this() immutable {}
>       }
> 
>       void main()
>       {
>           auto tid = spawn( &fooBar, thisTid );
>           while(true)
>           {
>               receive(
>                   (Variant any) {
>                       writeln( "Received a variant" );
>                       writeln( "Received ", any );
>                   }
>               );
>           }
>       }
> 
>       void fooBar( Tid masterTid )
>       {
>           scope(failure) writeln( "fooBar failed" );
>           scope(success) writeln( "fooBar succeeded" );
>           scope(exit) writeln( "fooBar exiting" );
>           try
>           {
>               immutable A b = new immutable A();
>               masterTid.send( 42 ); // This works
>               masterTid.send( b );  // This doesn't
>           }
>           catch( Exception e )
>           {
>               writeln( "Exception received" );
>           }
>       }
> 
> 
> I see this in the console:
> 
>       fooBar exiting
>       fooBar failed
>       Received a variant
>       Received 42
> 
> (then it just hangs)
> 
> I'm especially puzzled by:
>    * Sending an int as a message works but not an immutable object.
> Wasn't this  (safely sharing objects across threads) one of the
> basic use cases for the immutable type qualifier?
>    * scope(failure) failed but my exception handler didn't catch
> anything. How is this possible? What could cause that?
> Assertions/abort?
> 
> There seemed to be a 3-year-old ticket on this issue
> (http://d.puremagic.com/issues/show_bug.cgi?id=5538) with very
> little activity, which is a bit surprising given how much
> emphasis is given to this feature (the D homepage mentions "D
> offers an innovative approach to concurrency, featuring true
> immutable data, message passing, no sharing by default, and
> controlled mutable sharing across threads", and TDPL devotes a
> whole chapter on it). This thread
> (http://forum.dlang.org/thread/kgk8hc$12fa$1@digitalmars.com)
> also says std.concurrency is "very buggy".
> 
> If I can't use std.concurrency, is there any other safe
> alternative for multithreaded programming with D?
> 
> Thanks,
> A.


There is a bug with the internals of send/receive.   It has to be able 
to copy the reference to a another place while sending --  and it seems 
it can't do that because it's immutable.     I don't think many people 
are using it.    I personally did not realize the bug was from 2011.  I 
think DMD has been fixed enough to make a patch to phobos now.  I'm 
going to ping this bug report.

However,  even CONSTRUCTING immutable objects right now is very 
difficult.   It's arguably "correct" but, seems impossible to actually 
be able to make something of use without many many idups.  It's kind of 
in the same boat as shared.

What I am currently doing, is casting to shared, and then back.  I 
tried making my classes shared, and also immutable as you have.   
Nothing else seems to work:

> class A
>       {
>           this() {}
>       }
> 
>       void main()
>       {
>           auto tid = spawn( &fooBar, thisTid );
>           while(true)
>           {
>               receive(
		   (shared A _m)
	     	   {
			auto m = cast(A)_m;
			//Do stuff.
		   },
>                   (Variant any) {
>                       writeln( "Received a variant" );
>                       writeln( "Received ", any );
>                   }
>               );
>           }
>       }
> 
>       void fooBar( Tid masterTid )
>       {
>           scope(failure) writeln( "fooBar failed" );
>           scope(success) writeln( "fooBar succeeded" );
>           scope(exit) writeln( "fooBar exiting" );
>           try
>           {
>               immutable A b = new A();
>               masterTid.send( 42 ); // This works
>               masterTid.send( cast(shared) b );  // Should work
>           }
>           catch( Exception e )
>           {
>               writeln( "Exception received" );
>           }
>       }

-Shammah






More information about the Digitalmars-d-learn mailing list