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