Skip to content

Commit 9ba9437

Browse files
committed
Revise text with knowledge learned since proposed
1 parent 0d9943e commit 9ba9437

File tree

1 file changed

+105
-74
lines changed

1 file changed

+105
-74
lines changed

text/0517-io-os-reform.md

Lines changed: 105 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,100 +1245,131 @@ elsewhere.
12451245
#### TCP
12461246
[TCP]: #tcp
12471247

1248-
For `TcpStream`, the changes are most easily expressed by giving the signatures directly:
1248+
The current `TcpStream` struct will be pared back from where it is today to the
1249+
following interface:
12491250

12501251
```rust
12511252
// TcpStream, which contains both a reader and a writer
12521253

12531254
impl TcpStream {
1254-
fn connect<A: ToSocketAddr>(addr: A) -> IoResult<TcpStreama>;
1255-
fn connect_deadline<A, D>(addr: A, deadline: D) -> IoResult<TcpStreama> where
1256-
A: ToSocketAddr, D: IntoDeadline;
1257-
1258-
fn reader(&mut self) -> &mut TcpReader;
1259-
fn writer(&mut self) -> &mut TcpWriter;
1260-
fn split(self) -> (TcpReader, TcpWriter);
1261-
1262-
fn peer_addr(&mut self) -> IoResult<SocketAddr>;
1263-
fn socket_addr(&mut self) -> IoResult<SocketAddr>;
1264-
}
1265-
1266-
impl Reader for TcpStream { ... }
1267-
impl Writer for TcpStream { ... }
1268-
1269-
impl Reader for Deadlined<TcpStream> { ... }
1270-
impl Writer for Deadlined<TcpStream> { ... }
1271-
1272-
// TcpReader
1273-
1274-
impl Reader for TcpReader { ... }
1275-
impl Reader for Deadlined<TcpReader> { ... }
1276-
1277-
impl TcpReader {
1278-
fn peer_addr(&mut self) -> IoResult<SocketAddr>;
1279-
fn socket_addr(&mut self) -> IoResult<SocketAddr>;
1280-
1281-
fn shutdown_token(&mut self) -> ShutdownToken;
1255+
fn connect<A: ToSocketAddrs>(addr: &A) -> io::Result<TcpStream>;
1256+
fn peer_addr(&mut self) -> io::Result<SocketAddr>;
1257+
fn socket_addr(&mut self) -> io::Result<SocketAddr>;
1258+
fn shutdown(&mut self, how: Shutdown) -> io::Result<()>;
1259+
fn duplicate(&self) -> io::Result<TcpStream>;
12821260
}
12831261

1284-
// TcpWriter
1285-
1286-
impl Writer for TcpWriter { ... }
1287-
impl Writer for Deadlined<TcpWriter> { ... }
1262+
impl Read for TcpStream { ... }
1263+
impl Write for TcpStream { ... }
1264+
impl<'a> Read for &'a TcpStream { ... }
1265+
impl<'a> Write for &'a TcpStream { ... }
1266+
#[cfg(unix)] impl AsRawFd for TcpStream { ... }
1267+
#[cfg(windows)] impl AsRawSocket for TcpStream { ... }
1268+
```
12881269

1289-
impl TcpWriter {
1290-
fn peer_addr(&mut self) -> IoResult<SocketAddr>;
1291-
fn socket_addr(&mut self) -> IoResult<SocketAddr>;
1270+
* `clone` has been replaced with a `duplicate` function. The implementation of
1271+
`duplicate` will map to using `dup` on Unix platforms and
1272+
`WSADuplicateSocket` on Windows platforms. The `TcpStream` itself will no
1273+
longer be reference counted itself under the hood.
1274+
* `close_{read,write}` are both removed in favor of binding the `shutdown`
1275+
function directly on sockets. This will map to the `shutdown` function on both
1276+
Unix and Windows.
1277+
* `set_timeout` has been removed for now (as well as other timeout-related
1278+
functions). It is likely that this may come back soon as a binding to
1279+
`setsockopt` to the `SO_RCVTIMEO` and `SO_SNDTIMEO` options. This RFC does not
1280+
currently proposed adding them just yet, however.
1281+
* Implementations of `Read` and `Write` are provided for `&TcpStream`. These
1282+
implementations are not necessarily ergonomic to call (requires taking an
1283+
explicit reference), but they express the ability to concurrently read and
1284+
write from a `TcpStream`
1285+
1286+
Various other options such as `nodelay` and `keepalive` will be left
1287+
`#[unstable]` for now.
1288+
1289+
The `TcpAcceptor` struct will be removed and all functionality will be folded
1290+
into the `TcpListener` structure. Specifically, this will be the resulting API:
12921291

1293-
fn shutdown_token(&mut self) -> ShutdownToken;
1292+
```rust
1293+
impl TcpListener {
1294+
fn bind<A: ToSocketAddrs>(addr: &A) -> io::Result<TcpListener>;
1295+
fn socket_addr(&mut self) -> io::Result<SocketAddr>;
1296+
fn duplicate(&self) -> io::Result<TcpListener>;
1297+
fn accept(&self) -> io::Result<(TcpStream, SocketAddr)>;
1298+
fn incoming(&self) -> Incoming;
12941299
}
12951300

1296-
// ShutdownToken
1297-
1298-
impl ShutdownToken {
1299-
fn shutdown(self);
1301+
impl<'a> Iterator for Incoming<'a> {
1302+
type Item = io::Result<TcpStream>;
1303+
...
13001304
}
1301-
1302-
impl Clone for ShutdownToken { ... }
1305+
#[cfg(unix)] impl AsRawFd for TcpListener { ... }
1306+
#[cfg(windows)] impl AsRawSocket for TcpListener { ... }
13031307
```
13041308

1305-
The idea is that a `TcpStream` provides both a reader and a writer,
1306-
and can be used directly as such, just as it can today. However, the
1307-
two sides can also be broken apart via the `split` method, which
1308-
allows them to be shipped off to separate threads. Moreover, each side
1309-
can yield a `ShutdownToken`, a `Clone` and `Send` value that can be
1310-
used to shut down that side of the socket, cancelling any in-progress
1311-
blocking operations, much like e.g. `close_read` does today.
1312-
1313-
The implementation of the `ShutdownToken` infrastructure should ensure
1314-
that there is essentially no cost imposed when the feature is not used
1315-
-- in particular, if a `ShutdownToken` has not been requested, a
1316-
single `read` or `write` should correspond to a single syscall.
1317-
1318-
For `TcpListener`, the only change is to rename `socket_name` to
1319-
`socket_addr`.
1320-
1321-
For `TcpAcceptor` we will:
1322-
1323-
* Add a `socket_addr` method.
1324-
* Possibly provide a convenience constructor for `bind`.
1325-
* Replace `close_accept` with `cancel_token()`.
1326-
* Remove `Clone`.
1327-
* Rename `IncomingConnecitons` to `Incoming`.
1309+
Some major changes from today's API include:
1310+
1311+
* The static distinction between `TcpAcceptor` and `TcpListener` has been
1312+
removed (more on this in the [socket][Sockets] section).
1313+
* The `clone` functionality has been removed in favor of `duplicate` (same
1314+
caveats as `TcpStream`).
1315+
* The `close_accept` functionality is removed entirely. This is not currently
1316+
implemented via `shutdown` (not supported well across platforms) and is
1317+
instead implemented via `select`. This functionality can return at a later
1318+
date with a more robust interface.
1319+
* The `set_timeout` functionality has also been removed in favor of returning at
1320+
a later date in a more robust fashion with `select`.
1321+
* The `accept` function no longer takes `&mut self` and returns `SocketAddr`.
1322+
The change in mutability is done to express that multiple `accept` calls can
1323+
happen concurrently.
1324+
* For convenience the iterator does not yield the `SocketAddr` from `accept`.
13281325

13291326
#### UDP
13301327
[UDP]: #udp
13311328

1332-
The UDP infrastructure should change to use the new deadline
1333-
infrastructure, but should not provide `Clone`, `ShutdownToken`s, or a
1334-
reader/writer split. In addition:
1329+
The UDP infrastructre will receive a similar face-lift as the TCP infrastructure
1330+
will:
13351331

1336-
* `recv_from` should become `recv`.
1337-
* `send_to` should become `send`.
1338-
* `socket_name` should become `socket_addr`.
1332+
```rust
1333+
impl UdpSocket {
1334+
fn bind<A: ToSocketAddrs>(addr: &A) -> io::Result<UdpSocket>;
1335+
fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)>;
1336+
fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: &A) -> io::Result<usize>;
1337+
fn socket_addr(&self) -> io::Result<SocketAddr>;
1338+
fn duplicate(&self) -> io::Result<UdpSocket>;
1339+
}
1340+
1341+
#[cfg(unix)] impl AsRawFd for UdpSocket { ... }
1342+
#[cfg(windows)] impl AsRawSocket for UdpSocket { ... }
1343+
```
13391344

1340-
Methods like `multicast` and `ttl` are left as `#[experimental]` for
1341-
now (they are derived from libuv's design).
1345+
Some important points of note are:
1346+
1347+
* The `send` and `recv` function take `&self` instead of `&mut self` to indicate
1348+
that they may be called safely in concurrent contexts.
1349+
* All configuration options such as `multicast` and `ttl` are left as
1350+
`#[unstable]` for now.
1351+
* All timeout support is removed. This may come back in the form of `setsockopt`
1352+
(as with TCP streams) or with a more general implementation of `select`.
1353+
* `clone` functionality has been replaced with `duplicate`.
1354+
1355+
#### Sockets
1356+
[Sockets]: #sockets
1357+
1358+
The current constructors for `TcpStream`, `TcpListener`, and `UdpSocket` are
1359+
largely "convenience constructors" as they do not expose the underlying details
1360+
that a socket can be configured before it is bound, connected, or listened on.
1361+
One of the more frequent configuration options is `SO_REUSEADDR` which is set by
1362+
default for `TcpListener` currently.
1363+
1364+
This RFC leaves it as an open question how best to implement this
1365+
pre-configuration. The constructors today will likely remain no matter what as
1366+
convenience constructors and a new structure would implement consuming methods
1367+
to transform itself to each of the various `TcpStream`, `TcpListener`, and
1368+
`UdpSocket`.
1369+
1370+
This RFC does, however, recommend not adding multiple constructors to the
1371+
various types to set various configuration options. This pattern is best
1372+
expressed via a flexible socket type to be added at a future date.
13421373

13431374
#### Addresses
13441375
[Addresses]: #addresses

0 commit comments

Comments
 (0)