Threads & Message Passing - Best practices ?
I am using the recommended message passing threading model for my project, and it is not always clear how to do things in the best way; 1. receive() pattern matching -- what is common here, always send (int, someData) where int is a value you compare to. Or create dummy types that you can match on directly? receive(int cmd, int[] data) { if(cmd == SomeCommand) doStuff(data); } receive(SomeCommand, int[] data) { doStuff(data); } The latter seems nicer, but what's the best way to define those types? Or maybe it's better to be even more general? Something like; receive(void delegate(ARGS) f, ARGS a) { f(a); } 2. What is the reason you can't decide which thread(s) to receive() from and is there any way around it? Right now I need to have a static updateAll() method that is aware of all instances and call update() on them as needed. Also it's very hard to have generic modules that has their own threads because they can receive messages from other modules threads... 3. Is there a recommended way to deal with creating immutable data ? Right now I just cast to immutable before returning the data since I know I have the only reference, but it would be nice to have something like a `UniqueReference` containing a immutableMove() method...
Re: Static inline field initialization
On Tuesday, 22 August 2017 at 12:20:45 UTC, Moritz Maxeiner wrote: I agree that it can be confusing if you try to read it with C++ semantics [1]; the solution, however, imho is not to change D semantics or throw warnings [2], but to refer to the D spec [3], which states that static initialization of class members is used instead of default initialization (before any constructors are run). To me that means a statically initialized class field shall have the same value in all class instances, i.e. it's not silent sharing, you explicitly requested the sharing. If that doesn't mean the same to others, the D spec wording should be updated to be clearer on the subject. If you don't want instances to share a field value, instead of static initialization you can use constructor initialization [4]: class Test { ubyte[] buf; this() { buf = new ubyte[1000]; } } void main() { auto a = new Test(); auto b = new Test(); assert(a.buf.ptr != b.buf.ptr); } I know that it is according to the standard but since D has gone out of it's way to make sure sharing doesn't occur otherwise, by defaulting to TLS storage etc, I feel this breaks the "no surprises" rule. I took me a long time to find this out and when I mentioned it to other casual D programmers they also had no idea this was how it worked.
Static inline field initialization
Because of D's static initialization of members, this assert fails: class Test { ubyte[] buf = new ubyte[1000]; } void main() { auto a = new Test(); auto b = new Test(); assert(a.buf.ptr != b.buf.ptr); } This is bad, since; * It is not how C++ works * It introduces silent sharing of data * It's usually not what you want Shouldn't this at least generate a warning, or ideally not be allowed?