On 01/26/2013 04:07 AM, Michael Neumann wrote:
Am 26.01.2013 13:01, schrieb Michael Neumann:
Am 26.01.2013 12:28, schrieb Michael Neumann:
Another question: When a task sends a message to another task, and this task is waiting exactly for this event, will it directly switch to that task, or will it buffer the message? Sometimes this could be quite handy and efficient. I rember this was done in the L4 microkernel (www.l4ka.org), which only allowed synchronous IPC. It could make sense to provide a send_and_receive directive, which sends to the channel and lets the scheduler know that it is now waiting for a message to receive from another port. So send_and_receive could directly switch to the other task, and when this does a send back to the calling task, it will switch back to it. If you don't have send_and_receive as atomic operation, there is no way to switch back to the other task, as it might still be running.

"as it might still be running" is here of course wrong (as we switched to another thread). What I wanted to say is, that it is not waiting for any event, so it is not in a blocking state, so that
we cannot directly switch back (matching the recv() and the send()).

Ideally the task that wants to read would do the non-blocking I/O itself, and the scheduler would just notify when it can "read". But I think this is not possible with libuv as you have no control over when to read (except using uv_read_start() / _stop). I think this would be much more efficient and even more powerful (one can read directly into a buffer... there is no need to allocate a new buffer for each read as done by libuv). So what I would suggest is the following:

  // task
  blocking_read(socket, buffer, ...)
// this will register socket with the schedulers event queue (if not yet done) and block. // once the scheduler will receive an "data is available" event from the kernel
    // it will unblock the task.
    // then the task will do an non-blocking read() on it's own.

I'm not that familiar with the uv API. Is there a distinct 'data available' event that happens before we start reading? I've been assuming that, as you say, we have to control over when the read events happen, so we would need to check whether the task initiating this read was currently waiting for data, and either buffer it or context switch to the task depending on its state.


Basically it's the same what libuv does internally on it's own, just that the responsibility for doing the read's for example is moved into the task itself, so there is no longer a need for an I/O task and we gain full control of the asynchronous reads.

The advantage is:

  * we no longer need messages for I/O.
  * more flexibility
  * much better memory usage (no need to copy anymore)

Agree on these points.

  * the design is much easier and better to understand,
     libraries become so much easier

I do not think the design that integrates the scheduler with the I/O loop will be easier to understand. I expect the interactions will be complicated.


* and message passing could be done synchronous, i.e. very fast :)

In many cases this should be true, if the task initiating the I/O is still waiting on it. It could go off and execute other code and block on other things though, in which case the data needs to be buffered until the task can be scheduled.

_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to