Thread overview | |||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 12, 2010 [dmd-concurrency] Sending mesages to non-listening threads | ||||
---|---|---|---|---|
| ||||
It's nice that you can now send messages to any thread like this:
tid.send(i);
But... what if you're sending a message to the wrong thread, to a thread that isn't listening for messages? Do the messages accumulate in memory until no memory is left? If that's the case, sending messages to the wrong thread would become a memory leak. Any solution?
--
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/
|
January 12, 2010 [dmd-concurrency] Sending mesages to non-listening threads | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michel Fortin | On Jan 12, 2010, at 11:58 AM, Michel Fortin wrote:
> It's nice that you can now send messages to any thread like this:
>
> tid.send(i);
>
> But... what if you're sending a message to the wrong thread, to a thread that isn't listening for messages? Do the messages accumulate in memory until no memory is left? If that's the case, sending messages to the wrong thread would become a memory leak. Any solution?
Every thread created with spawn() will have a message queue, so in effect they're all listening. If the user is sending messages to a thread and never processing them then it's a flaw in the program design. About the only thing we could do about it is set a (possibly optional) max queue size and start returning "failure" messages once this limit is reached. The drawback being that sending such automatic messages could screw up any protocol the user has in place. I'd personally prefer to just leave this as-is, since the API is behaving in a logical and consistent manner.
There are a bunch of things still missing from the current API that will need to be addressed at some point though, like linking threads (so one will be notified if the other exits), a Tid registery, and probably a bunch of other things I'm forgetting offhand. These aren't necessary for a first cut, but they'll have to be added soon after.
|
January 12, 2010 [dmd-concurrency] Sending mesages to non-listening threads | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michel Fortin | ----- Original Message ----
> From: Michel Fortin <michel.fortin at michelf.com>
>
> It's nice that you can now send messages to any thread like this:
>
> tid.send(i);
>
> But... what if you're sending a message to the wrong thread, to a thread that isn't listening for messages? Do the messages accumulate in memory until no memory is left? If that's the case, sending messages to the wrong thread would become a memory leak. Any solution?
Maybe a thread who doesn't want messages can close his incoming message handle? Similar to a disconnected socket, the sender will get an exception or something (and trying to receive a message in such a thread would get an exception).
The other possibility is to only allow so many messages to be queued before the queue is "full". Unsure what you want to do at that point though, either block or return an EAGAIN type error (maybe you can do both depending on how you want to send the message). This solution is at least more likely to show logic errors, since with the first solution you may forget to close the handle. But it also could cause deadlocks or force you to write handling code for full queue conditions.
How does erlang handle this?
-Steve
|
January 12, 2010 [dmd-concurrency] Sending mesages to non-listening threads | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steve Schveighoffer | On Jan 12, 2010, at 12:12 PM, Steve Schveighoffer wrote: > ----- Original Message ---- > >> From: Michel Fortin <michel.fortin at michelf.com> >> >> It's nice that you can now send messages to any thread like this: >> >> tid.send(i); >> >> But... what if you're sending a message to the wrong thread, to a thread that isn't listening for messages? Do the messages accumulate in memory until no memory is left? If that's the case, sending messages to the wrong thread would become a memory leak. Any solution? > > Maybe a thread who doesn't want messages can close his incoming message handle? Similar to a disconnected socket, the sender will get an exception or something (and trying to receive a message in such a thread would get an exception). I don't think someone will often send a message to the wrong thread. The only default way to get a Tid is to be the one who spawned it (since spawn() returns a Tid) or to have looked it up in a registry by name. I suspect they'll be passed around in messages as well, but it doesn't seem likely that an app will be lost in a sea of Tids. I don't know that we want to try and guarantee any response for a failed send. Remember, this same API has to have identical behavior for threads living somewhere across the network as locally. It's feasible to provide a means of being notified when a thread dies (or becomes unreachable), but if the sender wants a return receipt for messages I think he should build that into his protocol. Firewall issues may prevent this from always working anyway, and that's something only the user would be aware of. As for closing the message handle, that should be trivial if people really want it. Message queues are turned off but left for the GC to clean up when a thread dies anyway, so this would simply be a matter of exposing the "disable my queue" function to the user. In a disabled queue, any messages received are simply dropped on the floor. > The other possibility is to only allow so many messages to be queued before the queue is "full". Unsure what you want to do at that point though, either block or return an EAGAIN type error (maybe you can do both depending on how you want to send the message). This solution is at least more likely to show logic errors, since with the first solution you may forget to close the handle. But it also could cause deadlocks or force you to write handling code for full queue conditions. > > How does erlang handle this? The way I described above. What I'm shooting for with this API is to provide a basic set of operations on top of which more complex designs could be built if desired. If you want CSP-like channels you can build that on top of send/receive, if you want a synchronous protocol you can do that as well, etc. The last thing we want is for no one to use our messaging system because it makes assumptions that don't match some common use case we didn't think of. |
January 12, 2010 [dmd-concurrency] Sending mesages to non-listening threads | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michel Fortin | Michel Fortin wrote:
> It's nice that you can now send messages to any thread like this:
>
> tid.send(i);
>
> But... what if you're sending a message to the wrong thread, to a thread that isn't listening for messages? Do the messages accumulate in memory until no memory is left? If that's the case, sending messages to the wrong thread would become a memory leak. Any solution?
I think mailbox crowding is a liability of message-passing systems in general. We can mitigate that in a number of ways, including an API for threads to set a ceiling for their mailbox:
enum OnCrowding { wait, throwException }
setMaxMailboxSize(size_t messages, OnCrowding doThis);
Andrei
|
January 12, 2010 [dmd-concurrency] Sending mesages to non-listening threads | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | Sean Kelly wrote:
> There are a bunch of things still missing from the current API that will need to be addressed at some point though, like linking threads (so one will be notified if the other exits), a Tid registery, and probably a bunch of other things I'm forgetting offhand. These aren't necessary for a first cut, but they'll have to be added soon after.
Yah, please do mention everything you remember. I want to describe a reasonably complete API.
Andrei
|
January 12, 2010 [dmd-concurrency] Sending mesages to non-listening threads | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steve Schveighoffer | Steve Schveighoffer wrote: > ----- Original Message ---- > >> From: Michel Fortin <michel.fortin at michelf.com> >> >> It's nice that you can now send messages to any thread like this: >> >> tid.send(i); >> >> But... what if you're sending a message to the wrong thread, to a thread that isn't listening for messages? Do the messages accumulate in memory until no memory is left? If that's the case, sending messages to the wrong thread would become a memory leak. Any solution? > > Maybe a thread who doesn't want messages can close his incoming message handle? Similar to a disconnected socket, the sender will get an exception or something (and trying to receive a message in such a thread would get an exception). With my suggested API, a thread can close its mailbox with: setMaxMailboxSize(0, OnCrowding.throwException); > The other possibility is to only allow so many messages to be queued before the queue is "full". Unsure what you want to do at that point though, either block or return an EAGAIN type error (maybe you can do both depending on how you want to send the message). This solution is at least more likely to show logic errors, since with the first solution you may forget to close the handle. But it also could cause deadlocks or force you to write handling code for full queue conditions. > > How does erlang handle this? I haven't found a mechanism described in the Erlang book. I think good Erlang style is to call receive with an "everything" handler at least in a while. Andrei |
January 12, 2010 [dmd-concurrency] Sending mesages to non-listening threads | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | Le 2010-01-12 ? 17:26, Andrei Alexandrescu a ?crit : > Michel Fortin wrote: >> It's nice that you can now send messages to any thread like this: >> tid.send(i); >> But... what if you're sending a message to the wrong thread, to a thread that isn't listening for messages? Do the messages accumulate in memory until no memory is left? If that's the case, sending messages to the wrong thread would become a memory leak. Any solution? > > I think mailbox crowding is a liability of message-passing systems in general. We can mitigate that in a number of ways, including an API for threads to set a ceiling for their mailbox: > > enum OnCrowding { wait, throwException } > setMaxMailboxSize(size_t messages, OnCrowding doThis); Looks like a fine solution, but I'm wary of the crowding policies you propose because it forces message passing to be somewhat synchronous: if you're on a network you must wait for the reply in case you need to throw an exception. It's very appropriate for thread-to-thread though, so I'm not sure what to propose. -- Michel Fortin michel.fortin at michelf.com http://michelf.com/ |
January 12, 2010 [dmd-concurrency] Sending mesages to non-listening threads | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Jan 12, 2010, at 2:29 PM, Andrei Alexandrescu wrote:
> Steve Schveighoffer wrote:
>
>> The other possibility is to only allow so many messages to be queued before the queue is "full". Unsure what you want to do at that point though, either block or return an EAGAIN type error (maybe you can do both depending on how you want to send the message). This solution is at least more likely to show logic errors, since with the first solution you may forget to close the handle. But it also could cause deadlocks or force you to write handling code for full queue conditions.
>> How does erlang handle this?
>
> I haven't found a mechanism described in the Erlang book. I think good Erlang style is to call receive with an "everything" handler at least in a while.
In Erlang, receiveAny() is just a side effect of the pattern matching:
receive
Any ->
io:format( "got something: ~p", Any );
end.
I suppose the closest fit in D would be to accept a Variant :-)
|
January 12, 2010 [dmd-concurrency] Sending mesages to non-listening threads | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Tue, 12 Jan 2010 17:27:09 -0500, Andrei Alexandrescu <andrei at erdani.com> wrote:
> Sean Kelly wrote:
>> There are a bunch of things still missing from the current API that will need to be addressed at some point though, like linking threads (so one will be notified if the other exits), a Tid registery, and probably a bunch of other things I'm forgetting offhand. These aren't necessary for a first cut, but they'll have to be added soon after.
>
> Yah, please do mention everything you remember. I want to describe a reasonably complete API.
>
> Andrei
> _______________________________________________
> dmd-concurrency mailing list
> dmd-concurrency at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/dmd-concurrency
On that note, will we be able to create message boxes/queues that are separate from threads?
|
Copyright © 1999-2021 by the D Language Foundation