www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Best choice for messages (std.concurrency)

reply nsf <no.smile.face gmail.com> writes:
Hi. I'm trying to replicate in D my Go demo app which basically
draws mandelbrot fractal using multiple goroutines. In Go it's
fairly easy to communicate between threads, because the memory model
is C like. D 2.0 on the other hand has this thing "TLS by default".
And I saw simple examples of std.concurrency usage in Andrei's book,
but what about more complex ones.

I have a need to pass some kind of a message to a worker thread.
Let's call it Request. It should contain request data, flag that is
used to interrupt thread if the response isn't needed anymore and
obviously the sender ID. What's the best way to do that?

Something like:
shared struct Request {
    bool discard;
immutable:
    byte[] request_data;
    Tid sender;
}

? Or maybe I don't understand something. How this struct should be
allocated in order to be able to pass it between threads? Or should
I use class instead? I think it's very confusing. Any suggestions?
Aug 18 2010
next sibling parent Jonathan M Davis <jmdavisprog gmail.com> writes:
On Wednesday, August 18, 2010 13:48:08 nsf wrote:
 Hi. I'm trying to replicate in D my Go demo app which basically
 draws mandelbrot fractal using multiple goroutines. In Go it's
 fairly easy to communicate between threads, because the memory model
 is C like. D 2.0 on the other hand has this thing "TLS by default".
 And I saw simple examples of std.concurrency usage in Andrei's book,
 but what about more complex ones.
 
 I have a need to pass some kind of a message to a worker thread.
 Let's call it Request. It should contain request data, flag that is
 used to interrupt thread if the response isn't needed anymore and
 obviously the sender ID. What's the best way to do that?
 
 Something like:
 shared struct Request {
     bool discard;
 immutable:
     byte[] request_data;
     Tid sender;
 }
 
 ? Or maybe I don't understand something. How this struct should be
 allocated in order to be able to pass it between threads? Or should
 I use class instead? I think it's very confusing. Any suggestions?

Well, if you have the book, I would have thought that it explained it well enough. You use send() and receive() in std.concurrency to send messages back and forth. All communication is done through them. The data passed across is either a value type which is copied, or it's immutable. There is no sharing across threads. If it's a struct, you should be able to just pass it across. Now, the fact that you're trying to pass a _shared_ struct is just weird. So maybe that's your problem. That isn't going to work. Something which is shared is no longer thread local, at which point you need to worry about synchronization and all that. You pass normal structs across. They data is copied. If you want to send a message back, then send a message back using send(). Trying to use a shared flag in something that you pass across just doesn't make sense. If you really need to, you can use shared data, and you can have both shared data and message passing in the same program, but the ideal is to just use message passing, and with a flag, that should be quite straightforward. You just send a message indicating whatever the flag is meant to indicate or just straight up send the flag across. Now, that may mean altering how your program works, but the idea is to constrain all communication between threads to the data sent via send() and have no data sharing beyond that. I'd really suggest reading the concurrency section of the book again. I had thought that it was quite clear on the matter. - Jonathan M Davis
Aug 18 2010
prev sibling parent Russel Winder <russel russel.org.uk> writes:
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Wed, 2010-08-18 at 20:48 +0000, nsf wrote:
 Hi. I'm trying to replicate in D my Go demo app which basically
 draws mandelbrot fractal using multiple goroutines. In Go it's
 fairly easy to communicate between threads, because the memory model
 is C like. D 2.0 on the other hand has this thing "TLS by default".
 And I saw simple examples of std.concurrency usage in Andrei's book,
 but what about more complex ones.

For the little experiments I am doing in D and Go, I am finding that the solution architectures are surprisingly similar. Goroutines, channels and message passing in Go compare to spawning and message passing in D. Yes the underlying semantics are very different in many ways, but it is process and message passing as an architectural direction. In neither case do I actually care about threads and thread pools, etc. The whole point is to get away from shared-memory multithreading as a programming model and treat it as an enabling model. Processors, cores and threads are like memory, heaps and stacks, programmers know they are there, but they let the runtime system deal with them. Of course having a sensible parallel algorithm compared to a sequential algorithm matters, but I am assuming you already have that covered. --=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 russel.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Aug 18 2010