Re: Using objects that manage threads via std.concurrency
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 Davis Hum, 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.
Re: Using objects that manage threads via std.concurrency
On Tuesday, 12 February 2013 at 10:08:14 UTC, FG wrote: 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(); } } 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.
Re: Using objects that manage threads via std.concurrency
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 divideconquer example receive makes sense and keeps ordering.
Using objects that manage threads via std.concurrency
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: Managers, 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?
Re: Using objects that manage threads via std.concurrency
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: Managers, 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? :)
Re: Using objects that manage threads via std.concurrency
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
Re: Using objects that manage threads via std.concurrency
On Tuesday, 12 February 2013 at 00:09:40 UTC, FG wrote: 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. 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. 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. I think there is a misunderstanding about what I meant by global mailbox. In my program, I have simple objects: Managers, 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? :)
Re: Using objects that manage threads via std.concurrency
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. 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 object 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 Davis