Skip to content

Commit

Permalink
auto merge of #12509 : brson/rust/rollup, r=brson
Browse files Browse the repository at this point in the history
  • Loading branch information
bors committed Feb 24, 2014
2 parents 329fcd4 + d08952c commit 76b262f
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 129 deletions.
2 changes: 1 addition & 1 deletion src/doc/complement-cheatsheet.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ Description C signature Equivalent
---------------------- ---------------------------------------------- ------------------------------------------
no parameters `void foo(void);` `fn foo();`
return value `int foo(void);` `fn foo() -> c_int;`
function parameters `void foo(int x, int y);` `fn foo(x: int, y: int);`
function parameters `void foo(int x, int y);` `fn foo(x: c_int, y: c_int);`
in-out pointers `void foo(const int* in_ptr, int* out_ptr);` `fn foo(in_ptr: *c_int, out_ptr: *mut c_int);`

Note: The Rust signatures should be wrapped in an `extern "ABI" { ... }` block.
Expand Down
2 changes: 1 addition & 1 deletion src/doc/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,7 @@ type was invalid because the size was infinite!

An *owned box* (`~`) uses a dynamic memory allocation to provide the invariant
of always being the size of a pointer, regardless of the contained type. This
can be leverage to create a valid `List` definition:
can be leveraged to create a valid `List` definition:

~~~
enum List {
Expand Down
1 change: 1 addition & 0 deletions src/libstd/char.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ static TAG_FOUR_B: uint = 240u;
pub static MAX: char = '\U0010ffff';

/// Convert from `u32` to a character.
#[inline]
pub fn from_u32(i: u32) -> Option<char> {
// catch out-of-bounds and surrogates
if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
Expand Down
167 changes: 41 additions & 126 deletions src/libstd/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,18 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*! Synchronous I/O
// FIXME: cover these topics:
// path, reader, writer, stream, raii (close not needed),
// stdio, print!, println!, file access, process spawning,
// error handling

This module defines the Rust interface for synchronous I/O.
It models byte-oriented input and output with the Reader and Writer traits.
Types that implement both `Reader` and `Writer` are called 'streams',
and automatically implement the `Stream` trait.
Implementations are provided for common I/O streams like
file, TCP, UDP, Unix domain sockets.
Readers and Writers may be composed to add capabilities like string
parsing, encoding, and compression.

/*! I/O, including files, networking, timers, and processes
`std::io` provides Rust's basic I/O types,
for reading and writing to files, TCP, UDP,
and other types of sockets and pipes,
manipulating the file system, spawning processes and signal handling.
# Examples
Expand Down Expand Up @@ -77,9 +79,7 @@ Some examples of obvious things you might want to do
let lines: ~[~str] = file.lines().collect();
```
* Make a simple HTTP request
FIXME This needs more improvement: TcpStream constructor taking &str,
`write_str` and `write_line` methods.
* Make a simple TCP client connection and request
```rust,should_fail
# #[allow(unused_must_use)];
Expand All @@ -92,72 +92,35 @@ Some examples of obvious things you might want to do
let response = socket.read_to_end();
```
* Connect based on URL? Requires thinking about where the URL type lives
and how to make protocol handlers extensible, e.g. the "tcp" protocol
yields a `TcpStream`.
FIXME this is not implemented now.
* Make a simple TCP server
```rust
// connect("tcp://localhost:8080");
# fn main() { }
# fn foo() {
# #[allow(unused_must_use, dead_code)];
use std::io::net::tcp::TcpListener;
use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::io::{Acceptor, Listener};
let addr = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 80 };
let listener = TcpListener::bind(addr);
// bind the listener to the specified address
let mut acceptor = listener.listen();
// accept connections and process them
# fn handle_client<T>(_: T) {}
for stream in acceptor.incoming() {
spawn(proc() {
handle_client(stream);
});
}
// close the socket server
drop(acceptor);
# }
```
# Terms
* Reader - An I/O source, reads bytes into a buffer
* Writer - An I/O sink, writes bytes from a buffer
* Stream - Typical I/O sources like files and sockets are both Readers and Writers,
and are collectively referred to a `streams`.
such as encoding or decoding
# Blocking and synchrony
When discussing I/O you often hear the terms 'synchronous' and
'asynchronous', along with 'blocking' and 'non-blocking' compared and
contrasted. A synchronous I/O interface performs each I/O operation to
completion before proceeding to the next. Synchronous interfaces are
usually used in imperative style as a sequence of commands. An
asynchronous interface allows multiple I/O requests to be issued
simultaneously, without waiting for each to complete before proceeding
to the next.
Asynchronous interfaces are used to achieve 'non-blocking' I/O. In
traditional single-threaded systems, performing a synchronous I/O
operation means that the program stops all activity (it 'blocks')
until the I/O is complete. Blocking is bad for performance when
there are other computations that could be done.
Asynchronous interfaces are most often associated with the callback
(continuation-passing) style popularised by node.js. Such systems rely
on all computations being run inside an event loop which maintains a
list of all pending I/O events; when one completes the registered
callback is run and the code that made the I/O request continues.
Such interfaces achieve non-blocking at the expense of being more
difficult to reason about.
Rust's I/O interface is synchronous - easy to read - and non-blocking by default.
Remember that Rust tasks are 'green threads', lightweight threads that
are multiplexed onto a single operating system thread. If that system
thread blocks then no other task may proceed. Rust tasks are
relatively cheap to create, so as long as other tasks are free to
execute then non-blocking code may be written by simply creating a new
task.
When discussing blocking in regards to Rust's I/O model, we are
concerned with whether performing I/O blocks other Rust tasks from
proceeding. In other words, when a task calls `read`, it must then
wait (or 'sleep', or 'block') until the call to `read` is complete.
During this time, other tasks may or may not be executed, depending on
how `read` is implemented.
Rust's default I/O implementation is non-blocking; by cooperating
directly with the task scheduler it arranges to never block progress
of *other* tasks. Under the hood, Rust uses asynchronous I/O via a
per-scheduler (and hence per-thread) event loop. Synchronous I/O
requests are implemented by descheduling the running task and
performing an asynchronous request; the task is only resumed once the
asynchronous request completes.
# Error Handling
Expand All @@ -170,10 +133,11 @@ Rust's I/O employs a combination of techniques to reduce boilerplate
while still providing feedback about errors. The basic strategy:
* All I/O operations return `IoResult<T>` which is equivalent to
`Result<T, IoError>`. The core `Result` type is defined in the `std::result`
`Result<T, IoError>`. The `Result` type is defined in the `std::result`
module.
* If the `Result` type goes unused, then the compiler will by default emit a
warning about the unused result.
warning about the unused result. This is because `Result` has the
`#[must_use]` attribute.
* Common traits are implemented for `IoResult`, e.g.
`impl<R: Reader> Reader for IoResult<R>`, so that error values do not have
to be 'unwrapped' before use.
Expand All @@ -192,7 +156,7 @@ If you wanted to handle the error though you might write:
use std::io::File;
match File::create(&Path::new("diary.txt")).write(bytes!("Met a girl.\n")) {
Ok(()) => { /* succeeded */ }
Ok(()) => (), // succeeded
Err(e) => println!("failed to write to my diary: {}", e),
}
Expand All @@ -208,55 +172,6 @@ need to inspect or unwrap the `IoResult<File>` and we simply call `write_line`
on it. If `new` returned an `Err(..)` then the followup call to `write_line`
will also return an error.
# Issues with i/o scheduler affinity, work stealing, task pinning
# Resource management
* `close` vs. RAII
# Paths, URLs and overloaded constructors
# Scope
In scope for core
* Url?
Some I/O things don't belong in core
- url
- net - `fn connect`
- http
- flate
Out of scope
* Async I/O. We'll probably want it eventually
# FIXME Questions and issues
* Should default constructors take `Path` or `&str`? `Path` makes simple cases verbose.
Overloading would be nice.
* Add overloading for Path and &str and Url &str
* stdin/err/out
* print, println, etc.
* fsync
* relationship with filesystem querying, Directory, File types etc.
* Rename Reader/Writer to ByteReader/Writer, make Reader/Writer generic?
* Can Port and Chan be implementations of a generic Reader<T>/Writer<T>?
* Trait for things that are both readers and writers, Stream?
* How to handle newline conversion
* String conversion
* open vs. connect for generic stream opening
* Do we need `close` at all? dtors might be good enough
* How does I/O relate to the Iterator trait?
* std::base64 filters
* Using conditions is a big unknown since we don't have much experience with them
* Too many uses of OtherIoError
*/

#[allow(missing_doc)];
Expand Down
1 change: 1 addition & 0 deletions src/libstd/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1061,6 +1061,7 @@ static UTF8_CHAR_WIDTH: [u8, ..256] = [
];

/// Given a first byte, determine how many bytes are in this UTF-8 character
#[inline]
pub fn utf8_char_width(b: u8) -> uint {
return UTF8_CHAR_WIDTH[b] as uint;
}
Expand Down
2 changes: 1 addition & 1 deletion src/libtest/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@ impl<T: Writer> ConsoleTestState<T> {
let ratchet_success = match *ratchet_metrics {
None => true,
Some(ref pth) => {
try!(self.write_plain(format!("\nusing metrics ratcher: {}\n",
try!(self.write_plain(format!("\nusing metrics ratchet: {}\n",
pth.display())));
match ratchet_pct {
None => (),
Expand Down

0 comments on commit 76b262f

Please sign in to comment.