digitalmars.D.learn - Using objects that manage threads via std.concurrency
- monarch_dodra (25/25) Feb 11 2013 I've been trying out std.concurrency, and it's MPI, and found it
- FG (6/16) Feb 11 2013 Caller locks the callee mailbox for a moment to put a message. Doesn't l...
- monarch_dodra (6/32) Feb 11 2013 Yes, but there is only one global mailbox per thread. If I have
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (12/15) Feb 11 2013 Threads receive their own messages. If there is a specific receiver of a...
- monarch_dodra (39/54) Feb 11 2013 I think I didn't explain myself very well. I have my single
- Jonathan M Davis (9/18) Feb 11 2013 By making it so that their receiving functions take unique types. If nee...
- monarch_dodra (10/18) Feb 12 2013 Hum, I just realized that "receive" works out of order on the
- FG (22/25) Feb 12 2013 OK, I finally get what you are saying.
- monarch_dodra (27/55) Feb 12 2013 Hum, I'll have to try to play around with that. For one thing,
- FG (8/11) Feb 12 2013 Unnecessarily hidden, because, from what I can see from a fast look at t...
- monarch_dodra (2/2) Feb 12 2013 THREAD HAS BEEN MOVED TO:
I've been trying out std.concurrency, and it's MPI, and found it very easy to use. It has been working well in most of my toy programs so far, but I see a HUGE glaring flaw with it. I mean: SHOWSTOPPER. Basically, I can't help but feel the thing has an hopelessly thread-global "mailbox" approach to the problem. This is all fine and dandy if there is only a single "canal" of communication between the master and the child/children. But what happens if you have 2 objects at once that want to communicate with their children? They have to share the global mailbox, making things very complex. In my program, I have simple objects: "Manager"s, that spawn a child thread to do work. This works fine if I have a single Manager, but how do I manage having 2 Managers at once? What should a manager do if it calls "receive", and notices the message wasn't meant for him? I can write an internal service that can manage the mailbox for all my managers, but that is a *very* closed approach. In particular, I'm planning to distribute a module with integrated multithreading. What if my clients also want to do MPI on their end? How does that work? ------------ Is there any way for an object to create its own personal MailBox? How would you tackle the problem? Does any one have any (simple) literature on the subject?
Feb 11 2013
On 2013-02-11 22:37, monarch_dodra wrote:Basically, I can't help but feel the thing has an hopelessly thread-global "mailbox" approach to the problem. This is all fine and dandy if there is only a single "canal" of communication between the master and the child/children.What thread-global? Every mbox is in thread-local storage.But what happens if you have 2 objects at once that want to communicate with their children? They have to share the global mailbox, making things very complex.Caller locks the callee mailbox for a moment to put a message. Doesn't lock any other thread, so you can have N/2 threads writing to other N/2 at the same time.In my program, I have simple objects: "Manager"s, that spawn a child thread to do work. This works fine if I have a single Manager, but how do I manage having 2 Managers at once?It's generally a very bad idea to have more than 1 manager over one's head. :)What should a manager do if it calls "receive", and notices the message wasn't meant for him?Don't know. Kill the messenger perhaps? :)
Feb 11 2013
On Tuesday, 12 February 2013 at 00:09:40 UTC, FG wrote:On 2013-02-11 22:37, monarch_dodra wrote:Yes, but there is only one global mailbox per thread. If I have more than one class instance inside a thread trying to communicate with other threads, they have to share the box.Basically, I can't help but feel the thing has an hopelessly thread-global "mailbox" approach to the problem. This is all fine and dandy if there is only a single "canal" of communication between the master and the child/children.What thread-global? Every mbox is in thread-local storage.I think there is a misunderstanding about what I meant by "global mailbox".But what happens if you have 2 objects at once that want to communicate with their children? They have to share the global mailbox, making things very complex.Caller locks the callee mailbox for a moment to put a message. Doesn't lock any other thread, so you can have N/2 threads writing to other N/2 at the same time.In my program, I have simple objects: "Manager"s, that spawn a child thread to do work. This works fine if I have a single Manager, but how do I manage having 2 Managers at once?It's generally a very bad idea to have more than 1 manager over one's head. :)What should a manager do if it calls "receive", and notices the message wasn't meant for him?Don't know. Kill the messenger perhaps? :)
Feb 11 2013
On 02/11/2013 01:37 PM, monarch_dodra wrote:What should a manager do if it calls "receive", and notices the message wasn't meant for him?Threads receive their own messages. If there is a specific receiver of a message, then the child sends it to that receiver. As FG said, every thread has a separate mailbox. It is possible to introduce threads to each other by their thread ids, which can be mapped to arbitrary names. (See register, locate, and unregister in std.concurrency.)Does any one have any (simple) literature on the subject?My experiments have been documented in the following chapter: http://ddili.org/ders/d.en/concurrency.html The "Thread names" section in there has a simple example that involves a third party introducing two threads to each other. Ali
Feb 11 2013
On Tuesday, 12 February 2013 at 06:29:22 UTC, Ali Çehreli wrote:On 02/11/2013 01:37 PM, monarch_dodra wrote:I think I didn't explain myself very well. I have my single "master" thread which has a "thread-global" mailbox, but I have 3 different objects that are sharing that mailbox. Code example: //---- import std.stdio, std.concurrency; struct Manager { this(string s) { spawn(&worker, s, thisTid); } string get() { return receiveOnly!string(); } } void worker(string s, Tid owner) { owner.send(s); } void main() { auto ma = Manager("a"); auto mb = Manager("b"); auto mc = Manager("c"); writeln(ma.get()); writeln(mb.get()); writeln(mb.get()); } //---- How can I get my 3 managers to co-exist, when they are all sharing the same box? How can I make sure the workers are sending their messages to the correct manager?What should a manager do if it calls "receive", and notices the message wasn't meant for him?Threads receive their own messages. If there is a specific receiver of a message, then the child sends it to that receiver. As FG said, every thread has a separate mailbox.It is possible to introduce threads to each other by their thread ids, which can be mapped to arbitrary names. (See register, locate, and unregister in std.concurrency.)Yes, but in this case, the problem is not thread to thread communication, but rather thread to objectI have already fully read that tutorial, which was very helpful. Thank you.Does any one have any (simple) literature on the subject?My experiments have been documented in the following chapter: http://ddili.org/ders/d.en/concurrency.html The "Thread names" section in there has a simple example that involves a third party introducing two threads to each other. Ali
Feb 11 2013
On Tuesday, February 12, 2013 07:58:04 monarch_dodra wrote:How can I get my 3 managers to co-exist, when they are all sharing the same box? How can I make sure the workers are sending their messages to the correct manager?By making it so that their receiving functions take unique types. If need be, you can declare types specific to the channel of communication that you're trying to create. Then only functions which match will receive those messages.Which I don't think was ever really intended. That doesn't mean that it's unreasonable, but I think that it was always the idea that a particular thread had a particular job, in which case, you wouldn't generally be trying to send messages to different parts of the thread. - Jonathan M DavisIt is possible to introduce threads to each other by their thread ids, which can be mapped to arbitrary names. (See register, locate, and unregister in std.concurrency.)Yes, but in this case, the problem is not thread to thread communication, but rather thread to object
Feb 11 2013
On Tuesday, 12 February 2013 at 07:07:21 UTC, Jonathan M Davis wrote:Which I don't think was ever really intended. That doesn't mean that it's unreasonable, but I think that it was always the idea that a particular thread had a particular job, in which case, you wouldn't generally be trying to send messages to different parts of the thread. - Jonathan M DavisHum, I just realized that "receive" works out of order on the types requested. I thought it *had* to receive THE first message in the queue, and throw if the type is not supported. I guess then that by specifying my specific type, and having a dedicated dispatcher, I can make my program work, without clashing with anybody else who is also threading. Now, I've just got to figure out how to manage my master's mailbox sizes, if a worker is faster than the rest.
Feb 12 2013
On 2013-02-12 07:58, monarch_dodra wrote:I think I didn't explain myself very well. I have my single "master" thread which has a "thread-global" mailbox, but I have 3 different objects that are sharing that mailbox.OK, I finally get what you are saying. You need to create a mailbox and a unique tid for every Manager (and probably would have to change Manager into a class). Unfortunately this won't work out of the box, as for example receiveOnly and friends use only the default mailbox of the current thread. struct Manager { Tid tid; MessageBox mbox; this(string s) { this.mbox = new MessageBox tid = Tid(new Mailbox); spawn(&worker, s, tid); } string get() { // you'd have to rewrite receive to use custom mbox return tid.myReceiveOnly!string(); } }
Feb 12 2013
On Tuesday, 12 February 2013 at 10:08:14 UTC, FG wrote:On 2013-02-12 07:58, monarch_dodra wrote:Hum, I'll have to try to play around with that. For one thing, "MessageBox" is private. Good news is my manager is already a class. As for the re-implement of receive to work on a custom Tid, maybe it might be better to forget about the tid, and implement it on directly on the mailbox? Something like this: //---- struct Manager { MessageBox mbox; this(string s) { this.mbox = new MessageBox Tid managerTid = Tid(new Mailbox); spawn(&worker, s, managerTid); } string get() { // you'd have to rewrite receive to use custom mbox return mbox.receiveOnly!string(); //Or just straight up: mbox.get(); } } //---- I don't know, I'll try and see how it goes.I think I didn't explain myself very well. I have my single "master" thread which has a "thread-global" mailbox, but I have 3 different objects that are sharing that mailbox.OK, I finally get what you are saying. You need to create a mailbox and a unique tid for every Manager (and probably would have to change Manager into a class). Unfortunately this won't work out of the box, as for example receiveOnly and friends use only the default mailbox of the current thread. struct Manager { Tid tid; MessageBox mbox; this(string s) { this.mbox = new MessageBox tid = Tid(new Mailbox); spawn(&worker, s, tid); } string get() { // you'd have to rewrite receive to use custom mbox return tid.myReceiveOnly!string(); } }
Feb 12 2013
On 2013-02-12 12:14, monarch_dodra wrote:For one thing, "MessageBox" is private.Unnecessarily hidden, because, from what I can see from a fast look at the sources, there is no implicit requirement for there to be only one MessageBox per thread. Maybe we're getting somewhere and this will be changed.As for the re-implement of receive to work on a custom Tid, maybe it might be better to forget about the tid, and implement it on directly on the mailbox?Well, yes. It's more natural to work on mbox than some artificial struct. Now, as for the usefulness of having many mailboxes. I'd rather have one mailbox than go into a loop with receiveTimeout called for each Manager, but in your divide&conquer example receive makes sense and keeps ordering.
Feb 12 2013
THREAD HAS BEEN MOVED TO: http://forum.dlang.org/thread/hatfmxuccjwraqwrzshq forum.dlang.org
Feb 12 2013