On Sat, Jul 5, 2014 at 8:07 AM, Nat Pryce <nat.pr...@gmail.com> wrote:
> 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. > > What API should I use to wait for multiple I/O objects within a task? Is > there a runtime-independent API for this? > Sounds like you might want something like a Java NIO Selector. These Selectors bake in a pipe as a wakeup mechanism as well: http://docs.oracle.com/javase/7/docs/api/java/nio/channels/Selector.html 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? ---------- Forwarded message ---------- From: Tony Arcieri <basc...@gmail.com> Date: Wed, Jan 29, 2014 at 1:40 AM Subject: Multiplexing I/O the Erlang way: an "ioserver" To: "rust-dev@mozilla.org" <rust-dev@mozilla.org> 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. 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) 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. 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" 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? 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: - 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 - 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 (Note: libuv is an I/O completions library and not a selector library so the proposed solution is admittedly a bit handwavey) 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. -- Tony Arcieri
_______________________________________________ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev