5 ms·
Currently there is either SEND or RECEIVE select, not a mixed one. What's the use case you have in mind for a mixed send/receive select?
by Rochus 3y ago
Currently there is either SEND or RECEIVE select, not a mixed one. What's the use case you have in mind for a mixed send/receive select?
- gpderetta 3y agoA bidirectional forwarding actor for example?
- Rochus 3y agoIs there a Go example somewhere?
- 082349872349872 3y agoNot Go, but there is example X7 on p117 of http://www.usingcsp.com/cspbook.pdf http://www.usingcsp.com/cspbook.pdf VAR_x = (left?y -> VAR_y | right!x -> VAR_x) as Hoare notes on p116: (not wrt mixed select, but the ultimate logic is the same) > To wait for the first of many possible events is the only way of achieving this: purchase of faster computers is useless. (note that Hoare78 discusses the desirability of output guards in §7.8 but there it isn't clear that they ought to occur mixed with input guards)
- Rochus 3y agoThanks. But I'm I wrong to assume that this could be worked around by two additional processes and channels?
- 082349872349872 3y agoBy what means would the two additional processes share the variable state? (I come from the pure message passing tradition and don't know much about Go so this may be a moot objection) FWIW Hoare thinks it makes for a simpler system if it is always possible to rewrite any SEQ as a PAR and vice versa.
- Rochus 3y agoMeanwhile I got a sample to which there is no adequate solution with my current proposal as long as we should not close the channel: https://news.ycombinator.com/item?id=38768025 https://news.ycombinator.com/item?id=38768025. Here are two proposals for a SELECT procedure if you want to take a look at it: https://news.ycombinator.com/item?id=38767926 https://news.ycombinator.com/item?id=38767926
- 082349872349872 3y agoMy motivating use case was a web browser: at any given point it may be browsing a number of resources, and for some of those it will be in the middle of making requests to a protocol handler (SEND) while for others it will be in the middle of reading responses from them (RECEIVE). But in general any time you might want to block until the first ready channel, it doesn't work if eg a channel becomes SEND'able but your code is currently blocked on the group RECEIVE. (this situation can be kludged with nonblocking calls, but a blocking call is friendlier to whatever else may be running in the system)
- Rochus 3y agoThanks. But wouldn't each request rather run in a separate go routine? > in general any time you might want to block until the first ready channel, it doesn't work if eg a channel becomes SEND'able but your code is currently blocked on the group RECEIVE Sure, but I think this can easily be avoided by using different go routines, i.e. not routing everything through only one. So I would be interested in examples where this is not possible or not feasible for some reason.
- dfawcus 3y agoReal world programs I've written in CSP style have made use of Alt (or select in Go) on mixed collections of receive and send channels. One simple use case is for a dynamic graph of channels, where one wishes to be able to 'cancel' a blocking send, that being done by having a 'cancel' read channel which one can select upon. Then one uses an Alt over both the send and the receive, with the expectation that usually it is the send which completes. I've used that pattern in recent Go code.
- Rochus 3y agoThanks. But do you really need another channel for "cancel", i.e. couldn't you just close the blocking channel? Of course I can add yet another built-in procedure, e.g. SELECT() which accepts both in and out channels; but since Oberon tries to be as simple as possible, I shouldn't do so as long as there are feasible work-arounds.
- dfawcus 3y agoYes one needs another channel. No, one can not just close the channel, because it is the sending end (which can close the channel) which is blocked, and the desire is to tear down the graph upon which its send is blocked. Certainly in Go, if one closes the channel upon which the sender is blocked, then it panics due to sending on a closed channel. It doesn't matter if one closes the channel before the send, or closes from another goroutine during the blocked send, the sender will still panic. So the only way to safely unblock the sender, is for its blocking send to be part of a select containing a read channel. Then when woken up, the send channel can be closed.
- Rochus 3y agoOk, I see, thanks. I will therefore add a SELECT procedure. The interface would look like in SEND and RECEIVE, but I could add an integer as the first parameter for the number of in channels, then one could first list all in and then all out channels. What do you think? Is there an added value for a non-blocking variang (i.e. like default in the Go select statement)? I could do that e.g. with a boolean parameter. EDIT: so far my SEND would not panic if the channel closes or is already closed, but just return 0; I thought that there could be yet another process instead of a cancel channel and this process could close channels even if another process is blocked on it, but maybe the SELECT solution would be more elegant (not sure though). EDIT2: or how about a SELECT procedure with just the in channels first (instead of the number), then a boolean (true..non blocking), and then the out channels?