www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - std.concurrency bug?

reply Charles Hixson via Digitalmars-d-learn writes:
Is it a bug that an immutable struct cannot be sent to a thread?  (It compiles 
without problem if I make all elements mutable.)
May 20 2014
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 05/20/2014 11:38 AM, Charles Hixson via Digitalmars-d-learn wrote:
 Is it a bug that an immutable struct cannot be sent to a thread?  (It compiles
 without problem if I make all elements mutable.)
Does the struct have any mutable indirection? Then it is illegal. Otherwise, can you demonstrate with minimal code please? Ali
May 20 2014
next sibling parent Charles Hixson via Digitalmars-d-learn writes:
On Tuesday, May 20, 2014 11:42:48 AM Ali Çehreli via Digitalmars-d-learn 
wrote:
 On 05/20/2014 11:38 AM, Charles Hixson via Digitalmars-d-learn wrote:
 Is it a bug that an immutable struct cannot be sent to a thread?  (It
 compiles without problem if I make all elements mutable.)
Does the struct have any mutable indirection? Then it is illegal. Otherwise, can you demonstrate with minimal code please? Ali
Nope. Here it is (with the immutable tags removed): /** This is the only message that one cell sends to another. */ struct Msg uint64_t from; uint64_t to; /** The kind of action the message is impelling. */ Act act; /** The tick on which the message was accepted for transmission. * This is set by std.datetime.Clock.currStdTime() */ long tick; /** Distance between cells. Not currently well defined except in * the case of two words, in which case it is the number of words of * separation, where adjacent is 1. */ float dist; /** Not currently well defined. */ int value; this (uint64_t from, uint64_t to, Act act, float dist, int value) { this.from = from; this.to = to; this.act = act; this.tick = Clock.currStdTime; this.dist = dist; this.value = value; } }
May 20 2014
prev sibling parent reply Charles Hixson via Digitalmars-d-learn writes:
On Tuesday, May 20, 2014 11:42:48 AM Ali Çehreli via Digitalmars-d-learn 
wrote:
 On 05/20/2014 11:38 AM, Charles Hixson via Digitalmars-d-learn wrote:
 Is it a bug that an immutable struct cannot be sent to a thread?  (It
 compiles without problem if I make all elements mutable.)
Does the struct have any mutable indirection? Then it is illegal. Otherwise, can you demonstrate with minimal code please? Ali
Nearly a minimal example. If "void sendMsg (Msg m){...}" is removed there's not compilation error. import std.array; import std.concurrency; import std.datetime; import std.format; import std.stdio; import std.stdint; import std.string; import std.variant; enum numCThreads = 4; class UnexpectedMessage : Exception { this (string s) { super (s); } } enum Act {create, activate, deactivate, wait, read, reset, save, done} string toString(E)(E value) if (is(E == enum)) { foreach (s; __traits(allMembers, E)) { if (value == mixin("E." ~ s) ) return s; } return null; } // string toString (... for enum /** This is the only message that one cell sends to another. */ struct Msg immutable uint64_t from; immutable uint64_t to; /** The kind of action the message is impelling. */ immutable Act act; /** The tick on which the message was accepted for transmission. * This is set by std.datetime.Clock.currStdTime() */ immutable long tick; /** Distance between cells. Not currently well defined except in * the case of two words, in which case it is the number of words of * separation, where adjacent is 1. */ immutable float dist; /** Not currently well defined. */ immutable int value; this (uint64_t from, uint64_t to, Act act, float dist, int value) { this.from = from; this.to = to; this.act = act; this.tick = Clock.currStdTime; this.dist = dist; this.value = value; } } void cellThread(size_t ndx, shared(Tid)[] cThreads) Msg msgs[uint64_t][]; bool done = false; //TODO load the cells into the thread /** Receive all messages in the mailbox. Wait 2 ns for response. */ while (!done && receiveTimeout (0.seconds, (Msg m) { if (m.to in msgs) { msgs[m.to] ~= m; } else { msgs[m.to] = [m]; } }, (Act act) { switch (act) { case Act.done: // end cell processing done = true; break; default: auto s = format ( "Error in thread %s: received message Act.%s", ndx, act); writefln (s); throw new UnexpectedMessage(s); } // switch (act) } //(Act act) ) ) { } // while (!done && receiveTimeout void sendMsg (Msg m) { assert (m.to > 0); assert (m.to < lastId); int ndx = m.to % numCThreads; Tid ct = cast(Tid)cThreads[ndx]; ct.send(m); } } // void cellThread() void main() { auto cellTids = new shared(Tid)[numCThreads]; foreach (id; 0 .. numCThreads) { auto cThread = spawn(&cellThread, id, cellTids); cellTids[id] = cast(shared(Tid))cThread; } foreach (cThread; cellTids) { Tid ct = cast(Tid)cThread; ct.send(Act.done); } }
May 20 2014
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 05/20/2014 05:24 PM, Charles Hixson via Digitalmars-d-learn wrote:

 On Tuesday, May 20, 2014 11:42:48 AM Ali Çehreli via Digitalmars-d-learn
 wrote:
 On 05/20/2014 11:38 AM, Charles Hixson via Digitalmars-d-learn wrote:
 Is it a bug that an immutable struct cannot be sent to a thread?  (It
 compiles without problem if I make all elements mutable.)
Further reduced: import std.concurrency; struct S { immutable int i; } void foo() {} void main() { auto f = spawn(&foo); auto s = S(); f.send(s); } I think this is a known issue with immutable and Variant, which std.concurrency uses for unknown messages. This looks related: https://issues.dlang.org/show_bug.cgi?id=5538 Ali
May 21 2014
next sibling parent Charles Hixson via Digitalmars-d-learn writes:
On Wednesday, May 21, 2014 01:19:32 PM Ali Çehreli via Digitalmars-d-learn 
wrote:
 On 05/20/2014 05:24 PM, Charles Hixson via Digitalmars-d-learn wrote:
  > On Tuesday, May 20, 2014 11:42:48 AM Ali Çehreli via Digitalmars-d-learn
  > 
  > wrote:
  >> On 05/20/2014 11:38 AM, Charles Hixson via Digitalmars-d-learn wrote:
  >>> Is it a bug that an immutable struct cannot be sent to a thread?  (It
  >>> compiles without problem if I make all elements mutable.)
 
 Further reduced:
 
 import std.concurrency;
 
 struct S
 {
      immutable int i;
 }
 
 void foo()
 {}
 
 void main()
 {
      auto f = spawn(&foo);
 
      auto s = S();
      f.send(s);
 }
 
 I think this is a known issue with immutable and Variant, which
 std.concurrency uses for unknown messages. This looks related:
 
    https://issues.dlang.org/show_bug.cgi?id=5538
 
 Ali
Thanks. Fortunately, I don't really need for messages to be immutable, I just thought it would be safer (as in avoiding the possibility of making a mistake). They're stucts, and I never pass a pointer, just the struct. Being immutable would allow me to guarantee that certain logic errors couldn't be committed is all.
May 21 2014
prev sibling parent "Sean Kelly" <sean invisibleduck.org> writes:
On Wednesday, 21 May 2014 at 20:19:32 UTC, Ali Çehreli wrote:
 I think this is a known issue with immutable and Variant, which 
 std.concurrency uses for unknown messages. This looks related:

   https://issues.dlang.org/show_bug.cgi?id=5538
std.concurrency actually uses Variant as the transport mechanism for all messages, and this is most likely the cause of your problem. If this is just to make a class pass type checking for transport, casting to shared is probably a better bet. The real solution is to make std.concurrency effectively allow uniquely referenced classes to be transferred, but that's a bit farther out.
May 22 2014