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 { /** The cell id# of the sender of the message. */ immutable uint64_t from; /** The cell id# of the recipient of the message. */ 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) { /** Unprocessed message queue, indexed by cell id#. */ 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); } }