►
From YouTube: An I/O System for Rust
Description
Eric Reed from the Research team presents "An I/O System for Rust"
Help us caption & translate this video!
http://amara.org/v/2FhW/
A
A
I
am
the
scheduler
before
it
runs
a
task
checks
with
the
lib
EV
event
loop
to
see
if
there's
anything
that
it
needs
to
do
like,
say,
process,
a
completed,
read
or
an
incoming
connection
attempt,
and
if
you
want
more
details,
I
was
just
going
to
look
at
Aaron
Todd's,
a
work,
stealing
runtime
for
rust
presentation
a
couple
weeks
ago.
It
should
be
on
air
Mozilla,
so
we
have
cross-platform
and
non
blocking
from
lib
TV,
but
it's
asynchronous
and
we
run
synchronous.
So
how
are
we
going
to
handle
that
it's
actually
pretty
simple
conceptually?
A
It
gets
a
little
tricky
when
you
actually
try
to
implement
it
and
it's
a
little
easy
to
mess
up,
but
the
basic
idea
is
when
a
task
starts
to
do.
I
owe
it
calls
read,
for
example,
and
the
first
thing
Reed:
does
it
made
you
some
preparatory
stuff
of
allocating
buffers,
but
basically
the
first
thing
that
it
does.
A
Is
it
yields
itself
to
the
scheduler
and
it
blocks
itself
basically,
and
it
gives
the
scheduler
this
cleanup
job
that
it
needs
to
run
before
it
goes
and
fix
some
other
task
to
do,
and
in
this
way
of
job
we
actually
call
into
Libya
V
and
call
Liv
Evie's
read
function
which
takes
some
call
back,
but
it
starts
a
request
and
it
takes
a
call
back
to
run
when
their
question,
please.
We
actually
take
the
task
and
we
wrap
it
inside
this
callback
and
this
we
give
it
to
libya
v
and
then
that's
not
blocking.
A
So
that
call
finishes
and
the
scheduler
goes
and
finds
some
other
work
to
do
somewhere
else
and
then
sometime
later
it
could
be
almost
instantly
it
could
be.
You
know
who
knows
long,
who
knows
how
long
the
I/o
request
finishes:
lube
EV
registers
this
event
in
the
event
loop
q.
Eventually
it
gets
the
top
and
the
scheduler
sees
this
event
happens
and
it
runs
the
callback
and
this
callback
gets
the
output
from
the
event
either
like.
A
So,
if
it's
a
read,
it'll
get
like
a
buffett,
that's
filled
with
data
or
it'll
get
like
a
an
error
that
something
went
wrong.
You
tried
to
read
from
a
socket
that
has
been
closed
on
the
other
end
or
something,
and
it
also
has
that
task
that
we
bought
so
process
is
the
output,
and
then
it
tells
the
scheduler
I
want
you
to
immediately
resume
this
cast
that
we
blocked
so
from
the
task
perspective.
It
calls
I,
oh
and
it
stops
and
nothing
happens
until
the
I
finishes,
and
then
it
resumes.
A
So,
as
far
as
the
task
is
concerned,
io
is
synchronous
and
blocking
which,
from
the
schedulers
perspective,
we
start
at
the
I/o
and
then
went
and
did
something
else
and
then
later
the
I/o
finished
and
we
might
have
multiple
I/o
actions
overlapping
in
different
tasks.
So,
as
far
as
the
scheduler
is
concerned,
we
have
a
synchronous,
non-blocking
I/o,
and
what
this
ends
up
doing.
Is
you
end
up
with
the
ease
of
programming
in
synchronous
I/o,
but
you
get
the
performance
characteristics
of
non-blocking
I/o,
and
this
is
all
hidden
to
the
programmer.
A
A
A
This
will
be.
V
is
single
threaded
when
you
create
a
handle
or
a
watcher,
its
associated
with
the
event
loop.
You
created
it
out,
and
it
can
only
do
I
owe
on
that
event
loop,
but
we
don't
know
that
watchers
are
going
to
always
on
the
event
loop
they're
created
on.
If
a
task
gets
stolen
by
someone
else,
it's
going
to
be
on
a
different
trend.
If
a
task
sends
it
over
channel
to
a
different
task
that
could
be
on
another
threader.
A
That
task
could
be
stolen
and
then
that
task
could
be
on
a
different
thread
and
try
to
do
I
owe
on
the
watcher
and
bad
things
will
happen.
If
you
try
to
do
that,
you'll,
probably
seg
fault
or
just
start
getting
nonsense,
and
we
would
really
prefer
our
Oh
system
cannot
start
randomly
psyched
halting
all
over
the
place.
That
would
not
get
us
very
many
users.
A
A
So
we
can't
just
pin
a
task
one,
because
we
want
the
performance
and
to
even
if
you
pin
the
task
it
could
still
receive
watchers
from
other
event
loops
and
if
it
tried
to
do
I
owe
on
that
then
now
you
just
have
nothing
to
do,
because
you
have
to
stay
on
your
scheduler,
but
you
can't
do
I
own
that
scheduler.
You
need
to
go
so
where
do
I?
Oh
and
then
what
you
do
you
just
abort,
because
there's
nothing
to
do,
but.
A
We
can
fix
that,
so
this
is
actually
what
really
happens
when
you
call
Reid
is
there's
all
this.
Wrapping
around
the
the
synchronous
read
call
that
we
just
discussed
there's
actually
this
homing
io
wrapping
code
that
works
around
it.
So
when
you
first
create
a
watcher,
it
has
the
secret
little
field
that
contains
a
handle
to
its
scheduler,
and
when
you
start
to
do
an
IO
call,
the
first
thing
that
it
does
before
it
tries
to
do
any
I/o.
A
Is
it
actually
yields
the
task
and
it
tells
the
scheduler
send
me
to
wherever
my
home
is-
and
maybe
this
is
the
same
scheduler
you're
on.
Maybe
it's
someone
else
and
you'll
go
as
a
message
to
that
scheduler
and
sit
in
the
queue
and
eventually
you'll,
get
to
the
front
and
you'll
wake
up
on
your
home.
Scheduler
awesome
you're
on
your
home
scheduler,
it's
time
to
do
I!
Oh,
she
started
I
Oh
in
the
test
blocks
since
the
test
blocks
you're
not
going
to
get
moved
off
until
the
eye
open.
Please.
A
So
you
don't
have
to
worry
about
that.
Eventually,
the
IO
finishes
you're
in
the
event
loop.
Eventually,
you
wake
up
all
right,
you're
done
often,
but
as
it
stands
right
now,
you're
now
pinned
onto
the
home
the
schedule
on
to
that
scheduler.
So
if
you
tried
to
get
if
you
were
stolen
and
tried
to
go
somewhere
else
before
you
execute
your
new
code,
that
scheduler
would
send
you
back.
That's
not
what
we
want.
A
Actually,
this
is
actually
all
encapsulated
for
you
in
a
wrapper
method,
and
all
you
do
is
you
give
the
closure
that
actually
does
your
I/o
and
it
takes
care
of
all
of
the
scheduling
for
you
and
there's
also
a
variant
that
gives
the
I/o
action
the
scheduler
that
allows
the
iOS
and
perform
its
own
scheduling
operations,
which
is
how
you
then
do
the
blocking
I.
Oh,
there
are
other
variants
that
don't
need
to
need
to
block
the
task
which
don't
need
that
schedule
and
there's
leather
bearings
as
well.
A
A
A
We
just
use
a
collection
of
traits
which
is
rust
parlance
for
what
a
Java
programmer
would
call
an
interface
or
a
haskell
programmer
would
call
a
type
class
to
define
the
I/o
operations
that
we
can
actually
do
and
the
high
level
stuff
is
just
built
on
top
of
those
traits
and
it
doesn't
know
how
its
implemented
and
the
low
level
stuff
just
implements
the
traits
and
then
there's
like
the
air
that
just
defines
the
trait.
So
it
gives
you
a
factory
to
construct
trait
objects.
A
Put
the
high
level
system
to
use-
and
it
gives
us
a
little
bit
of
overhead,
because
the
trade
objects
use
dynamic
dispatch
when
you
call
things
like
read
ultimately,
but
it's
worth
it
for
the
loose
coupling
that
we
gain
so
now
our
ion
system
is
independent
nations,
honeycomb
block,
exciting
space
news
and
everything
we
still
need
to
make
it
resource
safe,
and
this
is
all
actually
at
the
high
level
through
the
type
system.
And
why
do
we
need
to
do
this?
A
Well,
resources
like
file,
descriptors
and
sockets,
and
pipes
and
timers,
and
all
this
are
stateful
in
their
operations
that
are
only
valid
at
certain
times
and
in
a
lot
of
AP
is
this
is
true,
but
it's
not
actually
enforced
in
any
way.
If
you're
in
the
like
sea
level,
socket
API,
you
can
easily
call
read
before
you
call
bind
on
the
socket
and
doesn't
make
any
sense,
nothing
to
stop
you
and
in
more
modern
languages,
it's
a
little
bit
better,
but
it's
still
not
perfect,
but
really
we
should
forbid
all
of
the
invalid
uses.
A
It
should
not
even
be
possible
to
do
something.
That's
wrong
and
my
languages
can
get
a
little
bit
of
the
way
there.
You
can
do
something
like
if
you
have
a
TCP
stream,
which
you
can
read
from
you,
can
only
get
that
by
accepting
an
incoming
connection
from
a
listener
or
by
successfully
making
a
connect
call.
So
you
can't
read
from
an
unconnected
socket,
basically,
which
is
good,
great
okay,
but
then
there's
other
stuff
that
it
can't
do
like
it
can't
require
you
to
close
the
socket
before
you
free
it.
A
It
can't
or
another
example
here
is:
if
you
have
a
listener,
you
have
basically
three
ways
you
could
structure
it
either
it
starts
listening
when
you
create
it,
it
starts
listening
the
first
time
you
try
to
accept
something
or
there's
an
explicit
method.
You
have
to
call
to
start
listening
something
happening
over
there.
A
Okay,
all
right
or
exposes
a
particular,
listen
method
that
you
have
to
call
explicitly
and
if
it
starts
listening,
when
you
create
it,
that
gives
you
a
little
less
control
which
it's
acceptable,
but
it'd
be
better.
If
we
could
control
it.
If
it
starts,
when
you
first
call
except,
then
you
run
into
a
problem.
A
If
you
can't
actually,
if
you're
writing
multi-threaded
tests,
you
can't
actually
establish
that
the
server
has
started
before
you
have
like
a
client
task,
try
to
connect
to
it,
which
just
ends
up
becoming
annoying,
because
you
have
to
write
all
this
other
code
to
do
it
or
you
can
expose
a
listen
method
of
virtual
listener.
But
you
end
up
with
the
problem
of
you.
What
happens
if
you
call
listen
when
you're
already
listening,
you
shouldn't
be
able
to
start
a
listener
when
you've
already
started
the
listener.
A
That
doesn't
make
any
sense
that
shouldn't
even
be
possible,
but
you
can't
do
that
with
type
systems
in
Java,
because
you
can't
model
consumption
but
linear
types
which
rust
has
let
you
model
consumption.
A
linear
type
is
basically
a
type
that
ceases.
It's
a
it's.
If
something
has
a
linear
type
and
you
use
it,
you
don't
have
it
anymore,
it's
gone.
You
can't
make
copies
of
it.
Really.
A
A
So
r
us
has
a
variant
of
linear
types
called
affine
types,
which
actually
means
you
can
either
use
it
once
or
not
use
it,
and
basically
what
this
lets
you
do
is
let's
write
functions
that
require
the
caller
to
give
up
ownership
of
an
argument
to
the
function,
and
then
the
caller
will
no
longer
have
that
and
I
can't
use
it
again.
So,
for
example,
if
the
arguments
not
copyable,
if
it
was
copyable,
then
you
can
like
if
it's
copy
of
like
an
integer
is
copyable.
A
A
A
So
the
way
that
you
do
this
to
make
API
is
that
kind
of
encode.
This
kind
of
state
consumption
property,
for
example,
is
if
you
have
a
listener,
it
doesn't
start
listening
until
you
call
listen,
but
when
you
call
listen,
it
consumes
the
listener
and
you
don't
have
to
listener
anymore.
Instead,
what
you
get
is
an
acceptor
which
gives
you
an
accept
method
which
waits
for
an
incoming
connection,
or
actually
it
also
lets
you
create
an
iterator
over
incoming
connections.
A
If
you
wrote
a
basic
web
server,
but
doing
for
stream
in
accept
incoming
and
then
you've
a
body
and
that's
it,
but
what
the
snakes
makes
it
impossible
to
accept
before
the
listener
starts,
and
it
makes
it
impossible
to
start
listening
twice.
It's
just
you.
If
you
try
to
do
that,
the
type
checker
will
yell
at
you
until
you
stop
trying
to
do
that.
A
A
A
To
get
working
until
we
actually
build
the
thing:
it's
we
run
into
a
problem
repeatedly
since
russ's
dogfooding
everything,
but
the
rust
compiler
is
written
in
rust.
The
run
run
to
rust.
Runtime
is
written
in
rust
and
we're
using
that
to
further
right
rust.
So
we
run
into
a
lot
of
problems
of.
We
really
need
this
feature,
but
it
doesn't
exist
yet
because
we
haven't
implemented
it
and
we
need
to
implement
it
before
we
can
implement
it.
So
like
we
have
to
do
this.