awaitchannel icon indicating copy to clipboard operation
awaitchannel copied to clipboard

Is there a way to have select do one and only one action ?

Open edouardklein opened this issue 7 years ago • 8 comments

I've been banging my head on this problem for some time, and someone showed this library (which looks quite nice, congrats:) to me, but is is unclear to me if the semantics of select are the same as in Go:

Sometimes, in Go, my code relies on the fact that only one of the channel read or write passed to select actually happened.

If I send one value in channel c1 and another value in channel c2, and then select them both, and e.g. c1's read is chosen by the select and I discard its third return value, is there a guarantee that's c2's value is still available, or is there a possibility that it is lost ?

My problem here is that c2 may have been given to another goroutine, which does not have any access to the context where the third return value of the select call exists, and I may need this coroutine to have access to c2's value.

I hope my question is clear, if not, I'll try my best to clarify.

edouardklein avatar Jul 24 '17 15:07 edouardklein

Hi, after (id_, r), cases = await select(cases) it's possible that others have completed and their values are saved into the cases.completed list – if you don't do a select(cases) again or retrieve them manually from the cases.completed list they are gone.

pothos avatar Jul 24 '17 15:07 pothos

It's based on https://docs.python.org/3/library/asyncio-task.html#asyncio.wait and FIRST_COMPLETED – but if you can find out whether .completed is always empty then it could even be removed ;)

pothos avatar Jul 24 '17 15:07 pothos

Nope, it's really needed and can contain values. So you have to process them (maybe forward/put back in your case?).

pothos avatar Jul 24 '17 15:07 pothos

Thank you very much for your answers :)

Putting them back is a good idea, but I'm not familiar with asyncio enough to know whether this can be done with a guarantee that no other goroutine is putting something before the value we just read.

Maybe putting the asyncio.wait and the putting back of extraneous values in a critical section ?

I'll work on it. Would you consider a pull request in that sense, maybe with a keyword argument to select so that existing code gets the expected behavior, but go-style select is possible ?

If so, I'll propose the matter to one of my interns.

Cheers,

edouardklein avatar Jul 24 '17 20:07 edouardklein

This was just an educational project for me, I'm happy if it has a use and promotes async Python ;) and there is much room for improvements here, please provide PR's or maintain a fork of this project. The default event loop is slow and it would be interesting to run it on another one - but even then Python has its limits ;) Best regards

pothos avatar Jul 24 '17 21:07 pothos

For the reference: in my experience getting select semantics right is the key when implementing go-like channels. Some time ago I had to port my code from Go to Python and for that implemented pygolang which provides working select including working synchronous select - select sends.

navytux avatar Dec 03 '19 10:12 navytux

Thanks @navytux - I was looking for a working select and pygolang seems to cut it!

dumblob avatar May 28 '21 13:05 dumblob

You are welcome, @dumblob; thanks for feedback.

navytux avatar May 31 '21 18:05 navytux