www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Worker is not finished while sending message to intermediate worker

reply "xtreak" <tir.karthi gmail.com> writes:
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-
ntermediate-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.
Feb 09 2015
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Feb 09 2015
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 02/09/2015 11:46 AM, Ali Çehreli wrote:

 threads normally start one [or] more worker threads and
 send tasks to those threads
Accordingly, the following program uses just three threads: import std.stdio; import std.concurrency; import std.conv; import core.thread; struct Terminate {} void main() { auto square_tid = spawn(&square); foreach (int num; 1..100) { square_tid.send(num); auto square = receiveOnly!string(); writeln(square); } square_tid.send(Terminate()); } void square() { auto i = 0; bool done = false; auto stringWorker = spawn(&stringConverter, ownerTid); while (!done) { receive ( (Terminate message) { stringWorker.send(message); done = true; }, (int num) { auto square = num * num; writeln("sqaure : Comes in with " , num , " for " , ++i , " time"); stringWorker.send(square); }); } } void stringConverter(Tid destination) { auto i = 0; bool done = false; while (!done) { receive ( (Terminate message) { done = true; }, (int num) { auto stringified = num.to!string; writeln("string : Comes in with ", num, " for " , ++i , " time"); destination.send(stringified); }); } } Ali
Feb 09 2015
parent reply "xtreak" <tir.karthi gmail.com> writes:
On Monday, 9 February 2015 at 20:11:09 UTC, Ali Çehreli wrote:
 On 02/09/2015 11:46 AM, Ali Çehreli wrote:

 threads normally start one [or] more worker threads and
 send tasks to those threads
Accordingly, the following program uses just three threads: import std.stdio; import std.concurrency; import std.conv; import core.thread; struct Terminate {} void main() { auto square_tid = spawn(&square); foreach (int num; 1..100) { square_tid.send(num); auto square = receiveOnly!string(); writeln(square); } square_tid.send(Terminate()); } void square() { auto i = 0; bool done = false; auto stringWorker = spawn(&stringConverter, ownerTid); while (!done) { receive ( (Terminate message) { stringWorker.send(message); done = true; }, (int num) { auto square = num * num; writeln("sqaure : Comes in with " , num , " for " , ++i , " time"); stringWorker.send(square); }); } } void stringConverter(Tid destination) { auto i = 0; bool done = false; while (!done) { receive ( (Terminate message) { done = true; }, (int num) { auto stringified = num.to!string; writeln("string : Comes in with ", num, " for " , ++i , " time"); destination.send(stringified); }); } } Ali
Hi Ali, Thanks for your book :) I am using it for learning D. I want the stringConverter to send a message to square which in turn messages the main function with string "hello". So are you saying that message is not delivered to square from stringWorker. How does embedding the receive call inside the int in stackoverflow answer receives the message? It seems silly but how can I keep my threads alive to receive messages? Thanks a lot again. Please correct me if I am wrong anywhere.
Feb 09 2015
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 02/09/2015 12:34 PM, xtreak wrote:

 I want the stringConverter to send a message to square which in
 turn messages the main function with string "hello".
Your code did almost that but there was a bug (which I've pointed out).
 So are you saying that message is not delivered to square from
 stringWorker.
Not in your code due to that bug but the program that I've shown does exactly what you want.
 How does embedding the receive call inside the int in
 stackoverflow answer receives the message?
Once one receive() is executed, the program flow continues with further expressions. The suggestion that you received was making square() wait a second message. It need not be "embedded" at all. All it is needed was a second receive() call. That's all... However, that is not what you intended anyway. You wanted stringConverter() to send a message to main(). So, just forget about that embeded receive and either do what my program did or fix the bug. :) (See my earlier message.)
 It seems silly but how can I keep my threads alive to receive
 messages?
By having an infinite loop like 'while (!done)'. (Please see my program.) Ali
Feb 09 2015