抽象化のレベルが異なるため、チャネルとファイル記述子の両方を選択することはできません。チャネルはgoランタイムによって処理され、ファイル記述子はオペレーティングシステムによって処理されます。必要なのは、それらの間にブリッジを作成することです。これは、を使用して実行できますnet.Pipe()
。
あなたがする必要があることのほとんどは、あなたのzmqソケットと1つの「目覚め」を監視するためにepoll()
/に1つのゴルーチンを捧げることです。これはあなたの投票サーバーです。別のゴルーチンは、読み取りチャネルと書き込みチャネルをリッスンします。誰かが読み取りまたは書き込みチャネルを送信すると、2番目のゴルーチンがパイプを送信してポーリングサーバーをウェイクアップします。select()
net.Pipe()
これは、標準ライブラリのネットパッケージがどのように機能するかです。インスピレーションを得るためにそれを読むことを強くお勧めします(または盗む... BSDライセンスは非常に寛大です)。
ネット自体からのpollServerの説明は次のとおりです。これが何を言っているかを理解するためにコードを読む必要があるかもしれませんが、からのこのセクションはfd.go
探し始めるのに良い場所であるはずです。
// A pollServer helps FDs determine when to retry a non-blocking
// read or write after they get EAGAIN. When an FD needs to wait,
// send the fd on s.cr (for a read) or s.cw (for a write) to pass the
// request to the poll server. Then receive on fd.cr/fd.cw.
// When the pollServer finds that i/o on FD should be possible
// again, it will send fd on fd.cr/fd.cw to wake any waiting processes.
// This protocol is implemented as s.WaitRead() and s.WaitWrite().
//
// There is one subtlety: when sending on s.cr/s.cw, the
// poll server is probably in a system call, waiting for an fd
// to become ready. It's not looking at the request channels.
// To resolve this, the poll server waits not just on the FDs it has
// been given but also its own pipe. After sending on the
// buffered channel s.cr/s.cw, WaitRead/WaitWrite writes a
// byte to the pipe, causing the pollServer's poll system call to
// return. In response to the pipe being readable, the pollServer
// re-polls its request channels.
//
// Note that the ordering is "send request" and then "wake up server".
// If the operations were reversed, there would be a race: the poll
// server might wake up and look at the request channel, see that it
// was empty, and go back to sleep, all before the requester managed
// to send the request. Because the send must complete before the wakeup,
// the request channel must be buffered. A buffer of size 1 is sufficient
// for any request load. If many processes are trying to submit requests,
// one will succeed, the pollServer will read the request, and then the
// channel will be empty for the next process's request. A larger buffer
// might help batch requests.
//
// To avoid races in closing, all fd operations are locked and
// refcounted. when netFD.Close() is called, it calls syscall.Shutdown
// and sets a closing flag. Only when the last reference is removed
// will the fd be closed.
ネットを再実装して頑張ってください。このすべての終わりの良いニュースは、あなたのzmqソケットが外出先でスレッドセーフになるでしょう。