[dmd-concurrency] Shutdown protocol
Robert Jacques
sandford at jhu.edu
Wed Jan 20 07:45:20 PST 2010
On Wed, 20 Jan 2010 08:21:28 -0500, Michel Fortin
<michel.fortin at michelf.com> wrote:
> I know this has been discussed at length while I was sleeping, but I
> also see two problems with the shutdown protocol currently in the draft.
>
> First, it's a nice concept that the main thread waits for other threads
> to shutdown before exiting. It's a simple concept which allows other
> threads to finish their work before exiting. Except for this: any thread
> that requires communication to finish its work cannot exit properly.
> Another problem is that threads waiting a shutdown signal might not end
> until the very termination of the application.
>
> For instance, here is a modified version of Andrei's copy example which
> copies two files in parallel by putting each copy operation in a
> separate thread:
>
> import std.algorithm, std.concurrency, std.stdio;
>
> void main() {
> spawn(©("in1", "out1"));
> spawn(©("in2", "out2"));
> }
>
> void copy(string input, string output) {
> File source = File(input, "r");
>
> enum bufferSize = 1024 * 100;
> auto tid = spawn(&writer, outputPath); // Read loop
> foreach (immutable(ubyte)[] buffer; stdin.byChunk(bufferSize)) {
> send(tid, buffer);
> }
> }
> void writer(string output) {
> File target = File(output, "w");
>
> // Write loop
> for (;;) {
> auto buffer = receiveOnly!(immutable(ubyte)[])();
> target.rawWrite(buffer);
> }
> }
>
> Given the current shutdown protocol, this wouldn't work at all. The
> shutdown state would make writer() exit before copy has a chance to read
> most of the input. True, you could just a 'join()' to make the main
> thread explicitly wait for the two copy threads it spawned, but this
> would leave a writer thread inactive in the background while the other
> copy finishes. Add more files to copy and you'll get a lot of waisted
> writer threads doing nothing until the program terminates.
>
> So I'd propose a simple change to the shutdown protocol to make it scale
> better: when any thread finishes, it puts all the threads it spawned in
> shutdown state and exits (except for the main thread witch must wait
> before exiting to keep the other threads running).
>
> This somehow creates a ownership hierarchy between threads:
>
> main --> file copy thread 1 -> writer thread 1
> \-> file copy thread 2 -> writer thread 2
>
> What happens in the above example is this: main puts the two file copy
> threads in shutdown mode. When a file copy thread finishes reading, it
> puts its writer thread in shutdown mode, which then exits.
>
> I think this scales better.
>
> (Note: it should be possible to change the owner thread for cases where
> this hierarchy isn't appropriate.)
>
This seems like a bad idea. A lot of CSP examples I've seen have a
processes being spawned and then passed off to other processes. I think
this would complicate things and result in unexpected behavior. Really,
you wouldn't do something like that: you'd add some kind of
closed/last/poison sentinel to the message protocol so the writer knows
when to stop. A note to this effect should go into TDPL regarding standard
producer/consumer design.
More information about the dmd-concurrency
mailing list