I know I can wait on multiple channels using the select {} syntax in Go, and wait on multiple file descriptors using syscall.Select() or similar functions. But is it possible to wait on both channels at once?
For background, I want to have a goroutine that accepts for messages over a channel and forwards them over a socket connection (provided by gozmq), while simultaneously waiting for replies on the socket connection.
Due to the thread safety requirements of the underlying library, the socket can only be accessed in one thread at a time, which is why I was wondering if there is a way to handle this from a single goroutine.
Selecting on both a channel and an file descriptor is not possible because the abstractions are at different levels. Channels are handled by the go runtime and file descriptors by the operating system. What you need is to make a bridge between them and this can be done with a
net.Pipe().Pretty much what you need to do is dedicate one goroutine to
epoll()/select()to watch your zmq-sockets and a single “wake up”net.Pipe(). This is your poll server. Another goroutine listens on your read and write channels. When someone sends on the read or write channels, the second goroutine would send on the pipe to wake up the poll server.This is how the net package in the standard library works. I highly recommend reading it for inspiration (or stealing… the BSD license is very liberal).
Here is a description of pollServer from net itself. You may need to read the code to understand what this is saying, but this section from
fd.goshould be a good place to start looking.Good luck re-implementing net. The good news at the end of all this your zmq-socket will be thread safe in go.