Yes, I do want something like an nio Selector. <div><br></div><div>I'm trying to write it myself using epoll and eventfd on Linux. Binding to the syscall is straightforward. However I can't work out how to get the fds of IO objects (File struct, for example) so am stuck again.</div>
<div><div><br></div><div>The ioserver approach sounds promising as long as it can be easily extended with new I/O mechanisms. One thing to keep in mind is that not all I/O can be made non-blocking. Eg I2C and SPI communication on Linux is performed by ioctls that<span></span> block the calling thread and so would block an event loop that relies on nonblocking IO.</div>
<div><br></div><div>--Nat<br><br>On Sunday, July 6, 2014, Tony Arcieri <<a href="mailto:bascule@gmail.com">bascule@gmail.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sat, Jul 5, 2014 at 8:07 AM, Nat Pryce <span dir="ltr"><<a href="javascript:_e(%7B%7D,'cvml','nat.pryce@gmail.com');" target="_blank">nat.pryce@gmail.com</a>></span> wrote:<br>



<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div>I've been trying to write tasks that wait for both I/O and channel communication. I've been told that, to maximise communication performance, channels do not support selecting of both channels and I/O objects.  Therefore a program should signal to a task that is waiting for I/O over another I/O object, such as a pipe, not by sending a message over a channel.  Fair enough.<div>





<br></div><div>What API should I use to wait for multiple I/O objects within a task?  Is there a runtime-independent API for this?</div></div></div></blockquote><div><br></div><div>Sounds like you might want something like a Java NIO Selector. These Selectors bake in a pipe as a wakeup mechanism as well:</div>



<div><br></div><div><a href="http://docs.oracle.com/javase/7/docs/api/java/nio/channels/Selector.html" target="_blank">http://docs.oracle.com/javase/7/docs/api/java/nio/channels/Selector.html</a><br></div><div><br></div>


<div>However, there is more than one way to do it ;) Earlier I sent this message out about providing I/O "as a service" by having a dedicated task (or pool of tasks) that performs I/O operations for you, sending completions back as messages over the normal std::comm message protocol, ala Erlang's ioserver. Perhaps it's relevant to bring up again?</div>


<div><br><div class="gmail_quote">---------- Forwarded message ----------<br>From: <b class="gmail_sendername">Tony Arcieri</b> <span dir="ltr"><<a href="javascript:_e(%7B%7D,'cvml','bascule@gmail.com');" target="_blank">bascule@gmail.com</a>></span><br>
Date: Wed, Jan 29, 2014 at 1:40 AM<br>

Subject: Multiplexing I/O the Erlang way: an "ioserver"<br>To: "<a href="javascript:_e(%7B%7D,'cvml','rust-dev@mozilla.org');" target="_blank">rust-dev@mozilla.org</a>" <<a href="javascript:_e(%7B%7D,'cvml','rust-dev@mozilla.org');" target="_blank">rust-dev@mozilla.org</a>><br>


<br><br><div dir="ltr">libnative (fast, low-latency native I/O) and libgreen (libuv backed and great for large numbers of infrequent/idle messengers) are both awesome and provide some great options for network server I/O, particularly since you can mix-and-match them.<div>


<br></div><div>However there's a seemingly unsolved problem in Rust: multiplexing I/O operations with channels. I think this can be fixed in a purely additive manner (i.e everything else that exists today is great!) with a new feature borrowed from Erlang: the ioserver (noting that Erlang also implements libgreen-style synchronous I/O in addition to ioserver)</div>


<div><br></div><div>Ignoring Erlang for a second, the naive solution to the I/O + channel multiplexing is magic select API that can handle both. In my experience (i.e. I wrote and support this approach in a system some people actually use) the backend implementation, especially across POSIX and Windows, ends up quite ugly.</div>


<div><br></div><div>There's a better option though... if you want to multiplex IO with channel messages, turn everything into channel messages in one place: the "ioserver"</div><div><br></div><div>Solution: Centralize I/O event loops into a separate thread (pool if necessary, probably not). Erlang and 0MQ work this way. Erlang implements an API called a "port" to talk to the ioserver. In Rust perhaps you could have a type that implements the same trait as channels?</div>


<div><br></div><div>The ioserver becomes the central place to optimize the nitty gritty of taking I/O requests from the rest of the program and multiplexing them with other (i.e channel) events in the system. The basic formula is:</div>


<div><br></div><div>- Have the ioserver block for events using libuv or what have you, and have an OS-specific I/O handle (i.e. a pipe) to unblock the selector in the event of in-process communication</div><div>- Use lock-free mechanisms so if the selector isn't stuck in a system call we can use more efficient coordination of registering and unregistering I/O op interests</div>


<div><br></div><div>(Note: libuv is an I/O completions library and not a selector library so the proposed solution is admittedly a bit handwavey)</div><div><br></div><div>Mixing a pipe-based wakeup mechanism with lock-free operations to eliminate unnecessary system calls has been used somewhat successfully in the Netty I/O library for the JVM.</div>


<span><font color="#888888"><div><br></div>-- <br>Tony Arcieri</font></span></div></div></div></div>
</div></div>
</blockquote></div></div><br><br>-- <br><a href="http://www.natpryce.com">http://www.natpryce.com</a><br>