On 02/09/2015 08:00 AM, xtreak wrote:
I am using "programming in D" to learn about D language. I wrote a
simple program that spawns a worker and sends it a number to receive its
square as a string. The worker 1 gets the number squares it and sends to
worker 2 (a different function) to get casted as string which is
returned to the worker 1 and thus it returns it to the main function
call. I can write the whole thing in a single thread. I wrote it to
understand about workers better. I used receive to get the worker 1 act
as per the input. The program is as follows
import std.stdio;
import std.concurrency;
import std.conv;
import core.thread;
void main() {
foreach (int num; 1..100) {
auto square_tid = spawn(&square);
square_tid.send(num);
auto square = receiveOnly!string();
writeln(square);
}
}
void square() {
static i = 0;
receive (
(int num) {
auto square = num * num;
writeln("sqaure : Comes in with " , num , " for " , ++i , "
time");
auto stringWorker = spawn(&stringConverter);
stringWorker.send(thisTid, square, ownerTid);
},
(Tid tid, string str) {
writeln("comes in string");
send(tid, "hello");
});
}
void stringConverter() {
static i = 0;
auto params = receiveOnly!(Tid, int, Tid)();
auto stringified = to!string(params[1]); // Stringify the square
writeln("string : Comes in with " , params[1], " for " , ++i , " time");
params[0].send(params[2], stringified); // params[0] - square
function tid, // params[2] - main function tid
}
I got the answer from stackoverflow @
https://stackoverflow.com/questions/28128383/worker-is-not-finished-while-sending-message-to-intermediate-worker.
But the person who answered my question asked me to post back to dlang
learn to learn more about it. As I spawn the function and a send a
message to stringConverter as it sends a message to the square function
why do I need to embed another receive call inside the int case as
indicated in the answer. How can I avoid embedding the receive call and
why does the person in the second answer used while(1) to receive the
message.
Let me answer your question about 'value' first. You said on StackOverflow:
> Why does it have the value >= 0 as its obvious in the code.
I decided to use the value received to keep the example as simple as
possible. Note that later examples use a special type Terminate to
request termination:
int value = 0;
while (value >= 0) { // <-- Yes, obvious at first
value = receiveOnly!int(); // <-- But may change here
// ...
}
In message passing, threads normally start one more worker threads and
send tasks to those threads. In your example, your thread threads that
live for a very short time. In the case of square(), it creates a thread
for every request that it receives.
There is technically nothing wrong with that. However, it will be a good
idea to ensure that threads are alive when messages are sent to them.
This is not the case in your code.
For example, square() starts a thread, sends a message to it, and leaves
the receive() call. When stringConverter() sends the message, that
message will go to the main() thread. square() has executed its
receive() call and about to exit. In other words, the message "comes in
string" will never be printed.
Again, nothing wrong with it; just stating the obvious... :)
If you want main() to receive stringConverter()'s message, then there is
a bug in stringConverter() because it sends the message to square()
which will never receive it:
params[0].send(/* ... */);
should be
params[2].send(/* ... */);
And then main() complains because it should receive just a string:
Unexpected message type: expected 'string', got
'std.typecons.Tuple!(Tid, string).Tuple'
so the call should actually be
params[2].send(stringified);
Now it works. :)
Ali