www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Immutable Structs and std.concurrency

reply Russel Winder <russel winder.org.uk> writes:
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

The program:

        import std.concurrency ;
        import std.stdio ;
       =20
        /*immutable*/ struct X { int i ; }
       =20
        void printI ( ) {
          receive (
                   ( X x ) { writeln ( x.i ) ; }
                   ) ;
        }
       =20
        int main ( immutable string[] args ) {
          auto x =3D spawn ( & printI ) ;
          x.send ( X ( 3 ) ) ;
          return 0 ;
        }

behaves entirely as expected.  Taking the comments off the immutable
leads to:

core.exception.AssertError /home/users/russel/lib.Linux.x86_64/DMD2/bin64/.=
./../src/phobos/std/variant.d(286): X
----------------
/tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStru=
ct.d.EDDA68DBDAF917356C855298813D6CD2(_d_assert_msg+0x1f) [0x43f81f]
/tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStru=
ct.d.EDDA68DBDAF917356C855298813D6CD2(long std.variant.VariantN!(32uL).Vari=
antN.handler!(immutableStruct.X).handler(std.variant.VariantN!(32uL).Varian=
tN.OpID, ubyte[32]*, void*).bool tryPutting(immutableStruct.X*, TypeInfo, v=
oid*)+0x7a) [0x43b0fa]
/tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStru=
ct.d.EDDA68DBDAF917356C855298813D6CD2(long std.variant.VariantN!(32uL).Vari=
antN.handler!(immutableStruct.X).handler(std.variant.VariantN!(32uL).Varian=
tN.OpID, ubyte[32]*, void*)+0x103) [0x43ae03]
/tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStru=
ct.d.EDDA68DBDAF917356C855298813D6CD2( property immutableStruct.X std.varia=
nt.VariantN!(32uL).VariantN.get!(immutableStruct.X).get()+0x57) [0x434cf7]
/tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStru=
ct.d.EDDA68DBDAF917356C855298813D6CD2(void std.concurrency.Message.map!(voi=
d function(immutableStruct.X)*).map(void function(immutableStruct.X)*)+0x46=
) [0x434c96]
/tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStru=
ct.d.EDDA68DBDAF917356C855298813D6CD2(bool std.concurrency.MessageBox.get!(=
void function(immutableStruct.X)*).get(scope void function(immutableStruct.=
X)*).bool onStandardMsg(ref std.concurrency.Message)+0x2d) [0x434731]
/tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStru=
ct.d.EDDA68DBDAF917356C855298813D6CD2(bool std.concurrency.MessageBox.get!(=
void function(immutableStruct.X)*).get(scope void function(immutableStruct.=
X)*).bool scan(ref std.concurrency.List!(std.concurrency.Message).List)+0xd=
3) [0x434a47]
/tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStru=
ct.d.EDDA68DBDAF917356C855298813D6CD2(bool std.concurrency.MessageBox.get!(=
void function(immutableStruct.X)*).get(scope void function(immutableStruct.=
X)*)+0x15e) [0x434692]
/tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStru=
ct.d.EDDA68DBDAF917356C855298813D6CD2(void std.concurrency.receive!(void fu=
nction(immutableStruct.X)*).receive(void function(immutableStruct.X)*)+0x2e=
) [0x434526]
/tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStru=
ct.d.EDDA68DBDAF917356C855298813D6CD2(void immutableStruct.printI()+0x13) [=
0x433d1b]
/tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStru=
ct.d.EDDA68DBDAF917356C855298813D6CD2(_D3std11concurrency11__T6_spawnZ6_spa=
wnFbPFZvZS3std11concurrency3Tid4execMFZv+0x3d) [0x43abb5]
/tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStru=
ct.d.EDDA68DBDAF917356C855298813D6CD2(void core.thread.Thread.run()+0x2a) [=
0x449caa]
/tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStru=
ct.d.EDDA68DBDAF917356C855298813D6CD2(thread_entryPoint+0xf3) [0x449a43]
----------------

I believe this is wrong on so many levels, but is it because I don't
know D?

--=20
Russel.
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D
Dr Russel Winder      t: +44 20 7585 2200   voip: sip:russel.winder ekiga.n=
et
41 Buckmaster Road    m: +44 7770 465 077   xmpp: russel winder.org.uk
London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder
Apr 19 2012
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/19/2012 03:27 PM, Russel Winder wrote:
 The program:

          import std.concurrency ;
          import std.stdio ;

          /*immutable*/ struct X { int i ; }

          void printI ( ) {
            receive (
                     ( X x ) { writeln ( x.i ) ; }
                     ) ;
          }

          int main ( immutable string[] args ) {
            auto x = spawn (&  printI ) ;
            x.send ( X ( 3 ) ) ;
            return 0 ;
          }

 behaves entirely as expected.  Taking the comments off the immutable
 leads to:

 core.exception.AssertError /home/users/russel/lib.Linux.x86_64/DMD2/bin64/../../src/phobos
std/variant.d(286): X
 ----------------
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356C855298813D6CD2
_d_assert_msg+0x1f) [0x43f81f]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(long std.variant.VariantN!(32uL).VariantN.handler!(immutableStruct.X).handler(std.variant.VariantN!(
2uL).VariantN.OpID, ubyte[32]*, void*).bool tryPutting(immutableStruct.X*,
TypeInfo, void*)+0x7a) [0x43b0fa]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(long std.variant.VariantN!(32uL).VariantN.handler!(immutableStruct.X).handler(std.variant.VariantN!(
2uL).VariantN.OpID, ubyte[32]*, void*)+0x103) [0x43ae03]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356C8552
8813D6CD2( property immutableStruct.X
std.variant.VariantN!(32uL).VariantN.get!(immutableStruct.X).get()+0x57)
[0x434cf7]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(void std.concurrency.Message.map!(void
function(immutableStruct.X)*).map(void function(immutableStruct.X)*)+0x46)
[0x434c96]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(bool std.concurrency.MessageBox.get!(void
function(immutableStruct.X)*).get(scope void function(immutableStruct.X)*).bool
onStandardMsg(ref std.concurrency.Message)+0x2d) [0x434731]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(bool std.concurrency.MessageBox.get!(void
function(immutableStruct.X)*).get(scope void function(immutableStruct.X)*).bool
scan(ref std.concurrency.List!(std.concurrency.Message).List)+0xd3) [0x434a47]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(bool std.concurrency.MessageBox.get!(void
function(immutableStruct.X)*).get(scope void
function(immutableStruct.X)*)+0x15e) [0x434692]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(void std.concurrency.receive!(void
function(immutableStruct.X)*).receive(void function(immutableStruct.X)*)+0x2e)
[0x434526]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(void immutableStruct.printI()+0x13) [0x433d1b]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356C855298813D6CD2(_D3std11concurrency11__T6_spawnZ6_spawnFbPFZvZS3std11concurrenc
3Tid4execMFZv+0x3d) [0x43abb5]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(void core.thread.Thread.run()+0x2a) [0x449caa]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356C855298813D6CD2(thr
ad_entryPoint+0xf3) [0x449a43]
 ----------------

 I believe this is wrong on so many levels, but is it because I don't
 know D?

It certainly should work. std.concurrency does not do a good job dealing with head-immutable/head-const types currently (this includes class references). This needs to be fixed. The general problem is that it should be possible to declare a rebindable tail-immutable version of some type. std.typecons.Rebindable can be used for this, but an in-language solution would be superior.
Apr 19 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/19/2012 11:11 PM, Jakob Ovrum wrote:
 Fixing std.concurrency entails fixing std.variant which entails fixing
 std.typecons.Rebindable by moving its functionality into the language
 where it belongs.

 https://github.com/D-Programming-Language/dmd/pull/3

 This one has been lurking around forever, I wish Walter would accept
 this patch already.

Unfortunately the patch is incomplete. (template parameter matching is not implemented afaik and it does not work for structs)
Apr 19 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/19/2012 11:55 PM, Jakob Ovrum wrote:
 On Thursday, 19 April 2012 at 21:33:46 UTC, Timon Gehr wrote:
 Unfortunately the patch is incomplete. (template parameter matching is
 not implemented afaik and it does not work for structs)

Ah, didn't know about the template blocker, but how should it work for structs? Shouldn't the syntax only be allowed for implicit reference types, i.e. classes only?

std.typecons.Rebindable works for immutable structs with indirections. Reference types are just value types with indirections anyway: struct Object{ ObjectInstance* storage; alias storage this; } The language should catch this case even for user-defined types imo.
Apr 19 2012
prev sibling next sibling parent "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Thursday, 19 April 2012 at 16:26:19 UTC, Timon Gehr wrote:
 On 04/19/2012 03:27 PM, Russel Winder wrote:
 The program:

         import std.concurrency ;
         import std.stdio ;

         /*immutable*/ struct X { int i ; }

         void printI ( ) {
           receive (
                    ( X x ) { writeln ( x.i ) ; }
                    ) ;
         }

         int main ( immutable string[] args ) {
           auto x = spawn (&  printI ) ;
           x.send ( X ( 3 ) ) ;
           return 0 ;
         }

 behaves entirely as expected.  Taking the comments off the 
 immutable
 leads to:

 core.exception.AssertError /home/users/russel/lib.Linux.x86_64/DMD2/bin64/../../src/phobos
std/variant.d(286): 
 X
 ----------------
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356C855298813D6CD2
_d_assert_msg+0x1f) 
 [0x43f81f]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(long 
 std.variant.VariantN!(32uL).VariantN.handler!(immutableStruct.X).handler(std.variant.VariantN!(
2uL).VariantN.OpID, 
 ubyte[32]*, void*).bool tryPutting(immutableStruct.X*, 
 TypeInfo, void*)+0x7a) [0x43b0fa]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(long 
 std.variant.VariantN!(32uL).VariantN.handler!(immutableStruct.X).handler(std.variant.VariantN!(
2uL).VariantN.OpID, 
 ubyte[32]*, void*)+0x103) [0x43ae03]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356C8552
8813D6CD2( property 
 immutableStruct.X 
 std.variant.VariantN!(32uL).VariantN.get!(immutableStruct.X).get()+0x57) 
 [0x434cf7]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(void 
 std.concurrency.Message.map!(void 
 function(immutableStruct.X)*).map(void 
 function(immutableStruct.X)*)+0x46) [0x434c96]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(bool 
 std.concurrency.MessageBox.get!(void 
 function(immutableStruct.X)*).get(scope void 
 function(immutableStruct.X)*).bool onStandardMsg(ref 
 std.concurrency.Message)+0x2d) [0x434731]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(bool 
 std.concurrency.MessageBox.get!(void 
 function(immutableStruct.X)*).get(scope void 
 function(immutableStruct.X)*).bool scan(ref 
 std.concurrency.List!(std.concurrency.Message).List)+0xd3) 
 [0x434a47]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(bool 
 std.concurrency.MessageBox.get!(void 
 function(immutableStruct.X)*).get(scope void 
 function(immutableStruct.X)*)+0x15e) [0x434692]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(void 
 std.concurrency.receive!(void 
 function(immutableStruct.X)*).receive(void 
 function(immutableStruct.X)*)+0x2e) [0x434526]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(void 
 immutableStruct.printI()+0x13) [0x433d1b]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356C855298813D6CD2(_D3std11concurrency11__T6_spawnZ6_spawnFbPFZvZS3std11concurrenc
3Tid4execMFZv+0x3d) 
 [0x43abb5]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356
855298813D6CD2(void 
 core.thread.Thread.run()+0x2a) [0x449caa]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/immutableStruct.d.EDDA68DBDAF917356C855298813D6CD2(thr
ad_entryPoint+0xf3) 
 [0x449a43]
 ----------------

 I believe this is wrong on so many levels, but is it because I 
 don't
 know D?

It certainly should work. std.concurrency does not do a good job dealing with head-immutable/head-const types currently (this includes class references). This needs to be fixed. The general problem is that it should be possible to declare a rebindable tail-immutable version of some type. std.typecons.Rebindable can be used for this, but an in-language solution would be superior.

Fixing std.concurrency entails fixing std.variant which entails fixing std.typecons.Rebindable by moving its functionality into the language where it belongs. https://github.com/D-Programming-Language/dmd/pull/3 This one has been lurking around forever, I wish Walter would accept this patch already.
Apr 19 2012
prev sibling parent "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Thursday, 19 April 2012 at 21:33:46 UTC, Timon Gehr wrote:
 Unfortunately the patch is incomplete. (template parameter 
 matching is not implemented afaik and it does not work for 
 structs)

Ah, didn't know about the template blocker, but how should it work for structs? Shouldn't the syntax only be allowed for implicit reference types, i.e. classes only?
Apr 19 2012