<commit_before>extern crate serialize;
extern crate nickel;
extern crate http;

use nickel::{ Nickel, Request, Response };
use std::io::net::ip::Ipv4Addr;

fn main() {

    let mut server = Nickel::new();

    fn bar_handler (_request: &Request, response: &mut Response) {
        response.send("This is the /bar handler");
    }

    // go to http://localhost:6767/bar to see this route in action
    server.get("/bar", bar_handler);

    fn foo_handler (_request: &Request, response: &mut Response) {
        response.send("This is the /foo handler");
    }

    // go to http://localhost:6767/foo to see this route in action
    server.get("/foo", foo_handler);

    server.listen(Ipv4Addr(127, 0, 0, 1), 6767);
}
<commit_msg>fix(example): return proper 404 for unmatched routes<commit_after>extern crate serialize;
extern crate nickel;
extern crate http;

use http::status::{ NotFound };
use nickel::{ Nickel, Request, Response, ErrorWithStatusCode, Action, NickelError, IntoMiddleware };
use std::io::net::ip::Ipv4Addr;

fn main() {

    let mut server = Nickel::new();

    fn bar_handler (_request: &Request, response: &mut Response) {
        response.send("This is the /bar handler");
    }

    // go to http://localhost:6767/bar to see this route in action
    server.get("/bar", bar_handler);

    fn foo_handler (_request: &Request, response: &mut Response) {
        response.send("This is the /foo handler");
    }

    // go to http://localhost:6767/foo to see this route in action
    server.get("/foo", foo_handler);

    //middleware to catch all non matched routes
    fn catch_all (_request: &Request, _response: &mut Response) -> Result<Action, NickelError> {
        Err(NickelError::new("File Not Found", ErrorWithStatusCode(NotFound)))
    }

    // middleware is optional and can be registered with `utilize`
    server.utilize(IntoMiddleware::from_fn(catch_all));

    server.listen(Ipv4Addr(127, 0, 0, 1), 6767);
}
<|endoftext|>


<commit_before>// Copyright 2015 The tiny-http Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*!
# Simple usage

## Creating the server

The easiest way to create a server is to call `Server::http()`.

The `http()` function returns an `IoResult<Server>` which will return an error
in the case where the server creation fails (for example if the listening port is already
occupied).

```no_run
let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
```

A newly-created `Server` will immediatly start listening for incoming connections and HTTP
requests.

## Receiving requests

Calling `server.recv()` will block until the next request is available.
This function returns an `IoResult<Request>`, so you need to handle the possible errors.

```no_run
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();

loop {
    // blocks until the next request is received
    let request = match server.recv() {
        Ok(rq) => rq,
        Err(e) => { println!("error: {}", e); break }
    };

    // do something with the request
    // ...
}
```

In a real-case scenario, you will probably want to spawn multiple worker tasks and call
`server.recv()` on all of them. Like this:

```no_run
# use std::sync::Arc;
# use std::thread;
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
let server = Arc::new(server);
let mut guards = Vec::with_capacity(4);

for _ in (0 .. 4) {
    let server = server.clone();

    let guard = thread::spawn(move || {
        loop {
            let rq = server.recv().unwrap();

            // ...
        }
    });

    guards.push(guard);
}
```

If you don't want to block, you can call `server.try_recv()` instead.

## Handling requests

The `Request` object returned by `server.recv()` contains informations about the client's request.
The most useful methods are probably `request.method()` and `request.url()` which return
the requested method (`GET`, `POST`, etc.) and url.

To handle a request, you need to create a `Response` object. See the docs of this object for
more infos. Here is an example of creating a `Response` from a file:

```no_run
# use std::fs::File;
# use std::path::Path;
let response = tiny_http::Response::from_file(File::open(&Path::new("image.png")).unwrap());
```

All that remains to do is call `request.respond()`:

```no_run
# use std::fs::File;
# use std::path::Path;
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
# let request = server.recv().unwrap();
# let response = tiny_http::Response::from_file(File::open(&Path::new("image.png")).unwrap());
let _ = request.respond(response);
```
*/
#![crate_name = "tiny_http"]
#![crate_type = "lib"]
#![forbid(unsafe_code)]

#[macro_use]
extern crate log;

extern crate ascii;
extern crate chunked_transfer;
extern crate encoding;
extern crate url;
extern crate chrono;

#[cfg(feature = "ssl")]
extern crate openssl;

use std::error::Error;
use std::io::Error as IoError;
use std::io::Result as IoResult;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::thread;
use std::net;
use std::net::{ToSocketAddrs, TcpStream, Shutdown};
use std::time::Duration;
use std::sync::atomic::Ordering::Relaxed;

use client::ClientConnection;
use util::MessagesQueue;

pub use common::{Header, HeaderField, HTTPVersion, Method, StatusCode};
pub use request::{Request, ReadWrite};
pub use response::{ResponseBox, Response};

mod client;
mod common;
mod request;
mod response;

#[allow(dead_code)]     // TODO: remove when everything is implemented
mod util;

/// The main class of this library.
///
/// Destroying this object will immediatly close the listening socket annd the reading
///  part of all the client's connections. Requests that have already been returned by
///  the `recv()` function will not close and the responses will be transferred to the client.
pub struct Server {
    // should be false as long as the server exists
    // when set to true, all the subtasks will close within a few hundreds ms
    close: Arc<AtomicBool>,

    // queue for messages received by child threads
    messages: Arc<MessagesQueue<Message>>,

    // result of TcpListener::local_addr()
    listening_addr: net::SocketAddr,
}

enum Message {
    Error(IoError),
    NewRequest(Request),
}

impl From<IoError> for Message {
    fn from(e: IoError) -> Message {
        Message::Error(e)
    }
}

impl From<Request> for Message {
    fn from(rq: Request) -> Message {
        Message::NewRequest(rq)
    }
}

// this trait is to make sure that Server implements Share and Send
#[doc(hidden)]
trait MustBeShareDummy : Sync + Send {}
#[doc(hidden)]
impl MustBeShareDummy for Server {}

pub struct IncomingRequests<'a> {
    server: &'a Server
}

/// Represents the parameters required to create a server.
#[derive(Debug, Clone)]
pub struct ServerConfig<A> where A: ToSocketAddrs {
    /// The addresses to listen to.
    pub addr: A,

    /// If `Some`, then the server will use SSL to encode the communications.
    pub ssl: Option<SslConfig>,
}

/// Configuration of the server for SSL.
#[derive(Debug, Clone)]
pub struct SslConfig {
    /// Contains the public certificate to send to clients.
    pub certificate: Vec<u8>,
    /// Contains the ultra-secret private key used to decode communications.
    pub private_key: Vec<u8>,
}

impl Server {
    /// Shortcut for a simple server on a specific address.
    #[inline]
    pub fn http<A>(addr: A) -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        Server::new(ServerConfig {
            addr: addr,
            ssl: None,
        })
    }

    /// Shortcut for an HTTPS server on a specific address.
    #[cfg(feature = "ssl")]
    #[inline]
    pub fn https<A>(addr: A, config: SslConfig)
                    -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        Server::new(ServerConfig {
            addr: addr,
            ssl: Some(config),
        })
    }

    /// Builds a new server that listens on the specified address.
    pub fn new<A>(config: ServerConfig<A>) -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        // building the "close" variable
        let close_trigger = Arc::new(AtomicBool::new(false));

        // building the TcpListener
        let (server, local_addr) = {
            let listener = try!(net::TcpListener::bind(config.addr));
            let local_addr = try!(listener.local_addr());
            debug!("Server listening on {}", local_addr);
            (listener, local_addr)
        };

        // building the SSL capabilities
        #[cfg(feature = "ssl")]
        type SslContext = openssl::ssl::SslContext;
        #[cfg(not(feature = "ssl"))]
        type SslContext = ();
        let ssl: Option<SslContext> = match config.ssl {
            #[cfg(feature = "ssl")]
            Some(mut config) => {
                use openssl::ssl;
                use openssl::x509::X509;
                use openssl::pkey::PKey;
                use openssl::ssl::SslVerifyMode;

                let mut ctxt = try!(SslContext::builder(ssl::SslMethod::tls()));
                try!(ctxt.set_cipher_list("DEFAULT"));
                let certificate = try!(X509::from_pem(&config.certificate[..]));
                try!(ctxt.set_certificate(&certificate));
                let private_key = try!(PKey::private_key_from_pem(&config.private_key[..]));
                try!(ctxt.set_private_key(&private_key));
                ctxt.set_verify(SslVerifyMode::NONE);
                try!(ctxt.check_private_key());

                // let's wipe the certificate and private key from memory, because we're
                // better safe than sorry
                for b in &mut config.certificate { *b = 0; }
                for b in &mut config.private_key { *b = 0; }

                Some(ctxt.build())
            },
            #[cfg(not(feature = "ssl"))]
            Some(_) => return Err("Building a server with SSL requires enabling the `ssl` feature \
                                   in tiny-http".to_owned().into()),
            None => None,
        };

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are pushed in the messages queue
        let messages = MessagesQueue::with_capacity(8);

        let inside_close_trigger = close_trigger.clone();
        let inside_messages = messages.clone();
        thread::spawn(move || {
            // a tasks pool is used to dispatch the connections into threads
            let tasks_pool = util::TaskPool::new();

            debug!("Running accept thread");
            while !inside_close_trigger.load(Relaxed) {
                let new_client = match server.accept() {
                    Ok((sock, _)) => {
                        use util::RefinedTcpStream;
                        let (read_closable, write_closable) = match ssl {
                            None => {
                                RefinedTcpStream::new(sock)
                            },
                            #[cfg(feature = "ssl")]
                            Some(ref ssl) => {
                                let ssl = openssl::ssl::Ssl::new(ssl).expect("Couldn't create ssl");
                                // trying to apply SSL over the connection
                                // if an error occurs, we just close the socket and resume listening
                                let sock = match ssl.accept(sock) {
                                    Ok(s) => s,
                                    Err(_) => continue
                                };

                                RefinedTcpStream::new(sock)
                            },
                            #[cfg(not(feature = "ssl"))]
                            Some(_) => unreachable!(),
                        };

                        Ok(ClientConnection::new(write_closable, read_closable))
                    },
                    Err(e) => Err(e),
                };

                match new_client {
                    Ok(client) => {
                        let messages = inside_messages.clone();
                        let mut client = Some(client);
                        tasks_pool.spawn(Box::new(move || {
                            if let Some(client) = client.take() {
                                for rq in client {
                                    messages.push(rq.into());
                                }
                            }
                        }));
                    },

                    Err(e) => {
                        error!("Error accepting new client: {}", e);
                        inside_messages.push(e.into());
                        break;
                    }
                }
            }
            debug!("Terminating accept thread");
        });

        // result
        Ok(Server {
            messages: messages,
            close: close_trigger,
            listening_addr: local_addr,
        })
    }

    /// Returns an iterator for all the incoming requests.
    ///
    /// The iterator will return `None` if the server socket is shutdown.
    #[inline]
    pub fn incoming_requests(&self) -> IncomingRequests {
        IncomingRequests { server: self }
    }

    /// Returns the address the server is listening to.
    #[inline]
    pub fn server_addr(&self) -> net::SocketAddr {
        self.listening_addr.clone()
    }

    /// Returns the number of clients currently connected to the server.
    pub fn num_connections(&self) -> usize {
        unimplemented!()
        //self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    pub fn recv(&self) -> IoResult<Request> {
        match self.messages.pop() {
            Message::Error(err) => return Err(err),
            Message::NewRequest(rq) => return Ok(rq),
        }
    }

    /// Same as `recv()` but doesn't block longer than timeout
    pub fn recv_timeout(&self, timeout: Duration) -> IoResult<Option<Request>> {
        match self.messages.pop_timeout(timeout) {
            Some(Message::Error(err)) => return Err(err),
            Some(Message::NewRequest(rq)) => return Ok(Some(rq)),
            None => return Ok(None)
        }
    }

    /// Same as `recv()` but doesn't block.
    pub fn try_recv(&self) -> IoResult<Option<Request>> {
        match self.messages.try_pop() {
            Some(Message::Error(err)) => return Err(err),
            Some(Message::NewRequest(rq)) => return Ok(Some(rq)),
            None => return Ok(None)
        }
    }
}

impl<'a> Iterator for IncomingRequests<'a> {
    type Item = Request;
    fn next(&mut self) -> Option<Request> {
        self.server.recv().ok()
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.close.store(true, Relaxed);
        // Connect briefly to ourselves to unblock the accept thread
        let maybe_stream = TcpStream::connect(self.listening_addr);
        if let Ok(stream) = maybe_stream {
            let _ = stream.shutdown(Shutdown::Both);
        }
    }
}
<commit_msg>Fix a small documentation typo<commit_after>// Copyright 2015 The tiny-http Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*!
# Simple usage

## Creating the server

The easiest way to create a server is to call `Server::http()`.

The `http()` function returns an `IoResult<Server>` which will return an error
in the case where the server creation fails (for example if the listening port is already
occupied).

```no_run
let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
```

A newly-created `Server` will immediatly start listening for incoming connections and HTTP
requests.

## Receiving requests

Calling `server.recv()` will block until the next request is available.
This function returns an `IoResult<Request>`, so you need to handle the possible errors.

```no_run
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();

loop {
    // blocks until the next request is received
    let request = match server.recv() {
        Ok(rq) => rq,
        Err(e) => { println!("error: {}", e); break }
    };

    // do something with the request
    // ...
}
```

In a real-case scenario, you will probably want to spawn multiple worker tasks and call
`server.recv()` on all of them. Like this:

```no_run
# use std::sync::Arc;
# use std::thread;
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
let server = Arc::new(server);
let mut guards = Vec::with_capacity(4);

for _ in (0 .. 4) {
    let server = server.clone();

    let guard = thread::spawn(move || {
        loop {
            let rq = server.recv().unwrap();

            // ...
        }
    });

    guards.push(guard);
}
```

If you don't want to block, you can call `server.try_recv()` instead.

## Handling requests

The `Request` object returned by `server.recv()` contains informations about the client's request.
The most useful methods are probably `request.method()` and `request.url()` which return
the requested method (`GET`, `POST`, etc.) and url.

To handle a request, you need to create a `Response` object. See the docs of this object for
more infos. Here is an example of creating a `Response` from a file:

```no_run
# use std::fs::File;
# use std::path::Path;
let response = tiny_http::Response::from_file(File::open(&Path::new("image.png")).unwrap());
```

All that remains to do is call `request.respond()`:

```no_run
# use std::fs::File;
# use std::path::Path;
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
# let request = server.recv().unwrap();
# let response = tiny_http::Response::from_file(File::open(&Path::new("image.png")).unwrap());
let _ = request.respond(response);
```
*/
#![crate_name = "tiny_http"]
#![crate_type = "lib"]
#![forbid(unsafe_code)]

#[macro_use]
extern crate log;

extern crate ascii;
extern crate chunked_transfer;
extern crate encoding;
extern crate url;
extern crate chrono;

#[cfg(feature = "ssl")]
extern crate openssl;

use std::error::Error;
use std::io::Error as IoError;
use std::io::Result as IoResult;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::thread;
use std::net;
use std::net::{ToSocketAddrs, TcpStream, Shutdown};
use std::time::Duration;
use std::sync::atomic::Ordering::Relaxed;

use client::ClientConnection;
use util::MessagesQueue;

pub use common::{Header, HeaderField, HTTPVersion, Method, StatusCode};
pub use request::{Request, ReadWrite};
pub use response::{ResponseBox, Response};

mod client;
mod common;
mod request;
mod response;

#[allow(dead_code)]     // TODO: remove when everything is implemented
mod util;

/// The main class of this library.
///
/// Destroying this object will immediatly close the listening socket and the reading
///  part of all the client's connections. Requests that have already been returned by
///  the `recv()` function will not close and the responses will be transferred to the client.
pub struct Server {
    // should be false as long as the server exists
    // when set to true, all the subtasks will close within a few hundreds ms
    close: Arc<AtomicBool>,

    // queue for messages received by child threads
    messages: Arc<MessagesQueue<Message>>,

    // result of TcpListener::local_addr()
    listening_addr: net::SocketAddr,
}

enum Message {
    Error(IoError),
    NewRequest(Request),
}

impl From<IoError> for Message {
    fn from(e: IoError) -> Message {
        Message::Error(e)
    }
}

impl From<Request> for Message {
    fn from(rq: Request) -> Message {
        Message::NewRequest(rq)
    }
}

// this trait is to make sure that Server implements Share and Send
#[doc(hidden)]
trait MustBeShareDummy : Sync + Send {}
#[doc(hidden)]
impl MustBeShareDummy for Server {}

pub struct IncomingRequests<'a> {
    server: &'a Server
}

/// Represents the parameters required to create a server.
#[derive(Debug, Clone)]
pub struct ServerConfig<A> where A: ToSocketAddrs {
    /// The addresses to listen to.
    pub addr: A,

    /// If `Some`, then the server will use SSL to encode the communications.
    pub ssl: Option<SslConfig>,
}

/// Configuration of the server for SSL.
#[derive(Debug, Clone)]
pub struct SslConfig {
    /// Contains the public certificate to send to clients.
    pub certificate: Vec<u8>,
    /// Contains the ultra-secret private key used to decode communications.
    pub private_key: Vec<u8>,
}

impl Server {
    /// Shortcut for a simple server on a specific address.
    #[inline]
    pub fn http<A>(addr: A) -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        Server::new(ServerConfig {
            addr: addr,
            ssl: None,
        })
    }

    /// Shortcut for an HTTPS server on a specific address.
    #[cfg(feature = "ssl")]
    #[inline]
    pub fn https<A>(addr: A, config: SslConfig)
                    -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        Server::new(ServerConfig {
            addr: addr,
            ssl: Some(config),
        })
    }

    /// Builds a new server that listens on the specified address.
    pub fn new<A>(config: ServerConfig<A>) -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        // building the "close" variable
        let close_trigger = Arc::new(AtomicBool::new(false));

        // building the TcpListener
        let (server, local_addr) = {
            let listener = try!(net::TcpListener::bind(config.addr));
            let local_addr = try!(listener.local_addr());
            debug!("Server listening on {}", local_addr);
            (listener, local_addr)
        };

        // building the SSL capabilities
        #[cfg(feature = "ssl")]
        type SslContext = openssl::ssl::SslContext;
        #[cfg(not(feature = "ssl"))]
        type SslContext = ();
        let ssl: Option<SslContext> = match config.ssl {
            #[cfg(feature = "ssl")]
            Some(mut config) => {
                use openssl::ssl;
                use openssl::x509::X509;
                use openssl::pkey::PKey;
                use openssl::ssl::SslVerifyMode;

                let mut ctxt = try!(SslContext::builder(ssl::SslMethod::tls()));
                try!(ctxt.set_cipher_list("DEFAULT"));
                let certificate = try!(X509::from_pem(&config.certificate[..]));
                try!(ctxt.set_certificate(&certificate));
                let private_key = try!(PKey::private_key_from_pem(&config.private_key[..]));
                try!(ctxt.set_private_key(&private_key));
                ctxt.set_verify(SslVerifyMode::NONE);
                try!(ctxt.check_private_key());

                // let's wipe the certificate and private key from memory, because we're
                // better safe than sorry
                for b in &mut config.certificate { *b = 0; }
                for b in &mut config.private_key { *b = 0; }

                Some(ctxt.build())
            },
            #[cfg(not(feature = "ssl"))]
            Some(_) => return Err("Building a server with SSL requires enabling the `ssl` feature \
                                   in tiny-http".to_owned().into()),
            None => None,
        };

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are pushed in the messages queue
        let messages = MessagesQueue::with_capacity(8);

        let inside_close_trigger = close_trigger.clone();
        let inside_messages = messages.clone();
        thread::spawn(move || {
            // a tasks pool is used to dispatch the connections into threads
            let tasks_pool = util::TaskPool::new();

            debug!("Running accept thread");
            while !inside_close_trigger.load(Relaxed) {
                let new_client = match server.accept() {
                    Ok((sock, _)) => {
                        use util::RefinedTcpStream;
                        let (read_closable, write_closable) = match ssl {
                            None => {
                                RefinedTcpStream::new(sock)
                            },
                            #[cfg(feature = "ssl")]
                            Some(ref ssl) => {
                                let ssl = openssl::ssl::Ssl::new(ssl).expect("Couldn't create ssl");
                                // trying to apply SSL over the connection
                                // if an error occurs, we just close the socket and resume listening
                                let sock = match ssl.accept(sock) {
                                    Ok(s) => s,
                                    Err(_) => continue
                                };

                                RefinedTcpStream::new(sock)
                            },
                            #[cfg(not(feature = "ssl"))]
                            Some(_) => unreachable!(),
                        };

                        Ok(ClientConnection::new(write_closable, read_closable))
                    },
                    Err(e) => Err(e),
                };

                match new_client {
                    Ok(client) => {
                        let messages = inside_messages.clone();
                        let mut client = Some(client);
                        tasks_pool.spawn(Box::new(move || {
                            if let Some(client) = client.take() {
                                for rq in client {
                                    messages.push(rq.into());
                                }
                            }
                        }));
                    },

                    Err(e) => {
                        error!("Error accepting new client: {}", e);
                        inside_messages.push(e.into());
                        break;
                    }
                }
            }
            debug!("Terminating accept thread");
        });

        // result
        Ok(Server {
            messages: messages,
            close: close_trigger,
            listening_addr: local_addr,
        })
    }

    /// Returns an iterator for all the incoming requests.
    ///
    /// The iterator will return `None` if the server socket is shutdown.
    #[inline]
    pub fn incoming_requests(&self) -> IncomingRequests {
        IncomingRequests { server: self }
    }

    /// Returns the address the server is listening to.
    #[inline]
    pub fn server_addr(&self) -> net::SocketAddr {
        self.listening_addr.clone()
    }

    /// Returns the number of clients currently connected to the server.
    pub fn num_connections(&self) -> usize {
        unimplemented!()
        //self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    pub fn recv(&self) -> IoResult<Request> {
        match self.messages.pop() {
            Message::Error(err) => return Err(err),
            Message::NewRequest(rq) => return Ok(rq),
        }
    }

    /// Same as `recv()` but doesn't block longer than timeout
    pub fn recv_timeout(&self, timeout: Duration) -> IoResult<Option<Request>> {
        match self.messages.pop_timeout(timeout) {
            Some(Message::Error(err)) => return Err(err),
            Some(Message::NewRequest(rq)) => return Ok(Some(rq)),
            None => return Ok(None)
        }
    }

    /// Same as `recv()` but doesn't block.
    pub fn try_recv(&self) -> IoResult<Option<Request>> {
        match self.messages.try_pop() {
            Some(Message::Error(err)) => return Err(err),
            Some(Message::NewRequest(rq)) => return Ok(Some(rq)),
            None => return Ok(None)
        }
    }
}

impl<'a> Iterator for IncomingRequests<'a> {
    type Item = Request;
    fn next(&mut self) -> Option<Request> {
        self.server.recv().ok()
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.close.store(true, Relaxed);
        // Connect briefly to ourselves to unblock the accept thread
        let maybe_stream = TcpStream::connect(self.listening_addr);
        if let Ok(stream) = maybe_stream {
            let _ = stream.shutdown(Shutdown::Both);
        }
    }
}
<|endoftext|>


<commit_before>use std::thread;
use std::sync::mpsc;

pub struct Promise<T,E> {
	receiver : mpsc::Receiver<Result<T,E>>
}

impl<T,E> Promise<T,E> where T: Send + 'static , E: Send + 'static {

	pub fn new<F>(f:F) -> Promise<T,E> where F: Send + 'static + FnOnce() -> Result<T,E> {
		let (tx,rx) = mpsc::channel();
		thread::spawn(move || { tx.send(f()) });
		Promise::<T,E> { receiver: rx }
	}

	pub fn new_serie<F>(vector_functions:Vec<F>) -> Promise<Vec<T>, E> where F: Send + 'static + FnOnce() -> Result<T,E> {
		let (tx,rx) = mpsc::channel();
		thread::spawn(move || {
			let mut responses:Vec<T> = Vec::with_capacity(vector_functions.len());
			for f in vector_functions {
				match f() {
					Ok(t) => responses.push(t),
					Err(e) =>  {
						let r:Result<Vec<T>,E> = Err(e);
						return tx.send(r)
					}
				}
			}
			let r:Result<Vec<T>,E> = Ok(responses);
			tx.send(r)
		});
		Promise::<Vec<T>,E> { receiver: rx }
	}

	pub fn all(vector:Vec<Promise<T,E>>) -> Promise<Vec<T>, E> {
		let (tx,rx) = mpsc::channel();
		thread::spawn(move || {
			let mut results = vector.iter().map(|promise| { promise.receiver.recv().unwrap() });
			tx.send(
				match results.find(|r| r.is_err()) {
					Some(t) => {
						let res:Result<Vec<T>,E> = Err(match t { Ok(_) => unreachable!(), Err(e) => e });
						res
					},
					None => {
						let ok_results = results.map(|r| match r { Ok(t) => t, Err(_) => unreachable!() }).collect();
						let res:Result<Vec<T>,E> = Ok(ok_results);
						res
					}
				}
			)
		});
		Promise::<Vec<T>, E> { receiver: rx }
	}

	pub fn then<TT,F>(self,f:F) -> Promise<TT,E> where F: Send + 'static + FnOnce(T) -> Result<TT,E>, TT: Send + 'static {
		let (tx,rx) = mpsc::channel();
		thread::spawn(move || {
			let res = self.receiver.recv().unwrap();
			match res {
				Ok(t) => tx.send(f(t)),
				Err(e) => tx.send(Err(e))
			}
		});
		Promise::<TT,E> { receiver: rx }
	}

	pub fn fail<F>(self,f:F) -> Promise<T,E> where F: Send + 'static + FnOnce(E) -> Result<T,E> {
		let (tx,rx) = mpsc::channel();
		thread::spawn(move || {
			let res = self.receiver.recv().unwrap();
			match res {
				Ok(t) => tx.send(Ok(t)),
				Err(e) => tx.send(f(e))
			}
		});
		Promise::<T,E> { receiver: rx }
	}

	pub fn finally<FT,FE>(self, ft:FT, fe:FE) where FT: Send + 'static + FnOnce(T) , FE: Send + 'static + FnOnce(E) {
		thread::spawn(move || {
			let res = self.receiver.recv().unwrap();
			match res {
				Ok(t) => ft(t),
				Err(e) => fe(e)
			};
		});
	}

	pub fn finally_sync<FT,FE>(self, ft:FT, fe:FE) where FT: Send + 'static + FnOnce(T) , FE: Send + 'static +FnOnce(E) {
		let res = self.receiver.recv().unwrap();
		match res {
			Ok(t) => ft(t),
			Err(e) => fe(e)
		};
	}

	pub fn sync(self) -> Result<T,E> {
		self.receiver.recv().unwrap()
	}
}

#[cfg(test)]
mod test {
	use super::*;

	#[test]
	fn creation() {
		for x in 0..10 {
			let promise = Promise::<u32,&str>::new(move || {
				match x {
					0 => Err("Division by zero"),
					_ => Ok(x * 2)
				}
			}).then(move |res| {
				assert_eq!(res, x * 2);
				Ok(res * 2)
			}).fail(|error| {
				assert_eq!(error, "Division by zero");
				Err(error)
			}) ;

			let result = promise.sync();

			match x {
				0 => assert!(result.is_err()),
				_ => {
					assert!(result.is_ok());
					assert_eq!(result.unwrap(), x * 4);
				}
			}
		}
	}
}<commit_msg>remove series function<commit_after>use std::thread;
use std::sync::mpsc;

pub struct Promise<T,E> {
	receiver : mpsc::Receiver<Result<T,E>>
}

impl<T,E> Promise<T,E> where T: Send + 'static , E: Send + 'static {

	pub fn new<F>(f:F) -> Promise<T,E> where F: Send + 'static + FnOnce() -> Result<T,E> {
		let (tx,rx) = mpsc::channel();
		thread::spawn(move || { tx.send(f()) });
		Promise::<T,E> { receiver: rx }
	}

	pub fn all(vector:Vec<Promise<T,E>>) -> Promise<Vec<T>, E> {
		let (tx,rx) = mpsc::channel();
		thread::spawn(move || {
			let mut results = vector.iter().map(|promise| { promise.receiver.recv().unwrap() });
			tx.send(
				match results.find(|r| r.is_err()) {
					Some(t) => {
						let res:Result<Vec<T>,E> = Err(match t { Ok(_) => unreachable!(), Err(e) => e });
						res
					},
					None => {
						let ok_results = results.map(|r| match r { Ok(t) => t, Err(_) => unreachable!() }).collect();
						let res:Result<Vec<T>,E> = Ok(ok_results);
						res
					}
				}
			)
		});
		Promise::<Vec<T>, E> { receiver: rx }
	}

	pub fn then<TT,F>(self,f:F) -> Promise<TT,E> where F: Send + 'static + FnOnce(T) -> Result<TT,E>, TT: Send + 'static {
		let (tx,rx) = mpsc::channel();
		thread::spawn(move || {
			let res = self.receiver.recv().unwrap();
			match res {
				Ok(t) => tx.send(f(t)),
				Err(e) => tx.send(Err(e))
			}
		});
		Promise::<TT,E> { receiver: rx }
	}

	pub fn fail<F>(self,f:F) -> Promise<T,E> where F: Send + 'static + FnOnce(E) -> Result<T,E> {
		let (tx,rx) = mpsc::channel();
		thread::spawn(move || {
			let res = self.receiver.recv().unwrap();
			match res {
				Ok(t) => tx.send(Ok(t)),
				Err(e) => tx.send(f(e))
			}
		});
		Promise::<T,E> { receiver: rx }
	}

	pub fn finally<FT,FE>(self, ft:FT, fe:FE) where FT: Send + 'static + FnOnce(T) , FE: Send + 'static + FnOnce(E) {
		thread::spawn(move || {
			let res = self.receiver.recv().unwrap();
			match res {
				Ok(t) => ft(t),
				Err(e) => fe(e)
			};
		});
	}

	pub fn finally_sync<FT,FE>(self, ft:FT, fe:FE) where FT: Send + 'static + FnOnce(T) , FE: Send + 'static +FnOnce(E) {
		let res = self.receiver.recv().unwrap();
		match res {
			Ok(t) => ft(t),
			Err(e) => fe(e)
		};
	}

	pub fn sync(self) -> Result<T,E> {
		self.receiver.recv().unwrap()
	}
}

#[cfg(test)]
mod test {
	use super::*;

	#[test]
	fn creation() {
		for x in 0..10 {
			let promise = Promise::<u32,&str>::new(move || {
				match x {
					0 => Err("Division by zero"),
					_ => Ok(x * 2)
				}
			}).then(move |res| {
				assert_eq!(res, x * 2);
				Ok(res * 2)
			}).fail(|error| {
				assert_eq!(error, "Division by zero");
				Err(error)
			}) ;

			let result = promise.sync();

			match x {
				0 => assert!(result.is_err()),
				_ => {
					assert!(result.is_ok());
					assert_eq!(result.unwrap(), x * 4);
				}
			}
		}
	}
}<|endoftext|>


<commit_before>#![feature(globs)]

extern crate serialize;

extern crate conduit;
extern crate middleware = "conduit-middleware";
extern crate utils = "conduit-utils";

use std::fmt;
use std::fmt::{Show, Formatter};
use serialize::{Decodable, json};

use conduit::Request;
use utils::RequestDelegator;
use middleware::Middleware;

pub struct BodyReader<T>;

trait JsonDecodable : Decodable<json::Decoder, json::DecoderError> {}
impl<T: Decodable<json::Decoder, json::DecoderError>> JsonDecodable for T {}

impl<T: JsonDecodable + 'static> Middleware for BodyReader<T> {
    fn before(&self, req: &mut Request) -> Result<(), Box<Show + 'static>> {
        let json: T = try!(decode::<T>(req.body()).map_err(|err| {
            box format!("Couldn't parse JSON: {}", show(&*err)) as Box<Show>
        }));

        req.mut_extensions().insert(json);
        Ok(())
    }
}

// Hack around the lack of impl Show for Box<Show>
struct Shower<'a> {
    inner: &'a Show + 'a
}

impl<'a> Show for Shower<'a> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        self.inner.fmt(f)
    }
}

fn show<'a>(s: &'a Show) -> Shower<'a> {
    Shower { inner: s }
}

fn decode<T: JsonDecodable + 'static>(reader: &mut Reader) -> Result<T, Box<Show>> {
    let j = try!(json::from_reader(reader).map_err(|e| box e as Box<Show>));
    let mut decoder = json::Decoder::new(j);
    Decodable::decode(&mut decoder).map_err(|e| box e as Box<Show>)
}

pub fn json_params<'a, T: JsonDecodable + 'static>(req: &'a Request) -> Option<&'a T> {
    req.extensions().find::<T>()
}

#[cfg(test)]
mod tests {
    extern crate conduit_test = "conduit-test";

    use {json_params, BodyReader};

    use std::collections::HashMap;
    use std::io::MemReader;
    use serialize::json;

    use conduit;
    use conduit::{Request, Response, Handler};
    use middleware::MiddlewareBuilder;

    #[deriving(PartialEq, Decodable, Encodable, Show)]
    struct Person {
        name: String,
        location: String
    }

    fn handler(req: &mut Request) -> Result<Response, ()> {
        let person = json_params::<Person>(req);
        let out = person.map(|p| json::encode(p)).expect("No JSON");

        Ok(Response {
            status: (200, "OK"),
            headers: HashMap::new(),
            body: box MemReader::new(out.into_bytes()) as Box<Reader + Send>
        })
    }

    #[test]
    fn test_body_params() {
        let mut req = conduit_test::MockRequest::new(conduit::Get, "/");
        req.with_body(r#"{ "name": "Alex Crichton", "location": "San Francisco" }"#);

        let mut middleware = MiddlewareBuilder::new(handler);
        middleware.add(BodyReader::<Person>);

        let mut res = middleware.call(&mut req).ok().expect("No response");
        let person = super::decode::<Person>(&mut *res.body).ok().expect("No JSON response");
        assert_eq!(person, Person {
            name: "Alex Crichton".to_string(),
            location: "San Francisco".to_string()
        });
    }
}
<commit_msg>Update to master<commit_after>#![feature(globs)]

extern crate serialize;

extern crate conduit;
extern crate "conduit-middleware" as middleware;
extern crate "conduit-utils" as utils;

use std::fmt;
use std::fmt::{Show, Formatter};
use serialize::{Decodable, json};

use conduit::Request;
use utils::RequestDelegator;
use middleware::Middleware;

pub struct BodyReader<T>;

trait JsonDecodable : Decodable<json::Decoder, json::DecoderError> {}
impl<T: Decodable<json::Decoder, json::DecoderError>> JsonDecodable for T {}

impl<T: JsonDecodable + 'static> Middleware for BodyReader<T> {
    fn before(&self, req: &mut Request) -> Result<(), Box<Show + 'static>> {
        let json: T = try!(decode::<T>(req.body()).map_err(|err| {
            box format!("Couldn't parse JSON: {}", show(&*err)) as Box<Show>
        }));

        req.mut_extensions().insert(json);
        Ok(())
    }
}

// Hack around the lack of impl Show for Box<Show>
struct Shower<'a> {
    inner: &'a Show + 'a
}

impl<'a> Show for Shower<'a> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        self.inner.fmt(f)
    }
}

fn show<'a>(s: &'a Show) -> Shower<'a> {
    Shower { inner: s }
}

fn decode<T: JsonDecodable + 'static>(reader: &mut Reader) -> Result<T, Box<Show>> {
    let j = try!(json::from_reader(reader).map_err(|e| box e as Box<Show>));
    let mut decoder = json::Decoder::new(j);
    Decodable::decode(&mut decoder).map_err(|e| box e as Box<Show>)
}

pub fn json_params<'a, T: JsonDecodable + 'static>(req: &'a Request) -> Option<&'a T> {
    req.extensions().find::<T>()
}

#[cfg(test)]
mod tests {
    extern crate "conduit-test" as conduit_test;

    use {json_params, BodyReader};

    use std::collections::HashMap;
    use std::io::MemReader;
    use serialize::json;

    use conduit;
    use conduit::{Request, Response, Handler};
    use middleware::MiddlewareBuilder;

    #[deriving(PartialEq, Decodable, Encodable, Show)]
    struct Person {
        name: String,
        location: String
    }

    fn handler(req: &mut Request) -> Result<Response, ()> {
        let person = json_params::<Person>(req);
        let out = person.map(|p| json::encode(p)).expect("No JSON");

        Ok(Response {
            status: (200, "OK"),
            headers: HashMap::new(),
            body: box MemReader::new(out.into_bytes()) as Box<Reader + Send>
        })
    }

    #[test]
    fn test_body_params() {
        let mut req = conduit_test::MockRequest::new(conduit::Get, "/");
        req.with_body(r#"{ "name": "Alex Crichton", "location": "San Francisco" }"#);

        let mut middleware = MiddlewareBuilder::new(handler);
        middleware.add(BodyReader::<Person>);

        let mut res = middleware.call(&mut req).ok().expect("No response");
        let person = super::decode::<Person>(&mut *res.body).ok().expect("No JSON response");
        assert_eq!(person, Person {
            name: "Alex Crichton".to_string(),
            location: "San Francisco".to_string()
        });
    }
}
<|endoftext|>


<commit_before>/*
Copyright ⓒ 2016 Daniel Keep.

Licensed under the MIT license (see LICENSE or <http://opensource.org
/licenses/MIT>) or the Apache License, Version 2.0 (see LICENSE of
<http://www.apache.org/licenses/LICENSE-2.0>), at your option. All
files in the project carrying such notice may not be copied, modified,
or distributed except according to those terms.
*/
/*!

Provides the [`Boolinator`](trait.Boolinator.html) trait, which lets you use `Option` and `Result`-style combinators with `bool`s.

**Links**

* [Latest Release](https://crates.io/crates/boolinator/)
* [Latest Docs](https://danielkeep.github.io/rust-boolinator/doc/boolinator/index.html)
* [Repository](https://github.com/DanielKeep/rust-boolinator)

## Compatibility

`boolinator` is tested against Rust 1.0+.  *Exhaustively* so.

*/
// Can't have undocumented APIs!  Nosiree!
#![deny(missing_docs)]

/**
This trait defines a number of combinator-style methods for use with `bool` values.

In general, `true`/`false` map to `Some(_)`/`None` and `Ok(_)`/`Err(_)` respectively.
*/
pub trait Boolinator: Sized {
    /**
    Converts this value into a logically equivalent `Some(())` or `None`.
    */
    fn as_option(self) -> Option<()>;

    /**
    If this value is `true`, returns `Some(some)`; `None` otherwise.
    */
    fn as_some<T>(self, some: T) -> Option<T>;

    /**
    If this value is `true`, returns `Some(some())`; `None` otherwise.
    */
    fn as_some_from<T, F>(self, some: F) -> Option<T>
    where F: FnOnce() -> T;

    /**
    If this value is `true`, returns `opt`; `None` otherwise.
    */
    fn and_option<T>(self, opt: Option<T>) -> Option<T>;

    /**
    If this value is `true`, returns `opt()`; `None` otherwise.
    */
    fn and_option_from<T, F>(self, opt: F) -> Option<T>
    where F: FnOnce() -> Option<T>;

    /**
    If this value is `true`, returns `Ok(ok)`; `Err(err)` otherwise.
    */
    fn as_result<T, E>(self, ok: T, err: E) -> Result<T, E>;

    /**
    If this value is `true`, returns `Ok(ok())`; `Err(err())` otherwise.
    */
    fn as_result_from<T, E, F, G>(self, ok: F, err: G) -> Result<T, E>
    where F: FnOnce() -> T, G: FnOnce() -> E;

    /**
    If this value is `true`, returns `Ok(())`; `Err(err)` otherwise.
    */
    fn ok_or<E>(self, err: E) -> Result<(), E>;

    /**
    If this value is `true`, returns `Ok(())`; `Err(err())` otherwise.
    */
    fn ok_or_else<E, G>(self, err: G) -> Result<(), E>
    where G: FnOnce() -> E;

    /**
    Panics with `msg` if this value is `false`, otherwise it does nothing.
    */
    fn expect(self, msg: &str);
}

impl Boolinator for bool {
    #[inline]
    fn as_option(self) -> Option<()> {
        if self { Some(()) } else { None }
    }

    fn as_some<T>(self, some: T) -> Option<T> {
        if self { Some(some) } else { None }
    }

    fn as_some_from<T, F>(self, some: F) -> Option<T>
    where F: FnOnce() -> T {
        if self { Some(some()) } else { None }
    }

    fn and_option<T>(self, opt: Option<T>) -> Option<T> {
        if self { opt } else { None }
    }

    fn and_option_from<T, F>(self, opt: F) -> Option<T>
    where F: FnOnce() -> Option<T> {
        if self { opt() } else { None }
    }

    fn as_result<T, E>(self, ok: T, err: E) -> Result<T, E> {
        if self { Ok(ok) } else { Err(err) }
    }

    fn as_result_from<T, E, F, G>(self, ok: F, err: G) -> Result<T, E>
    where F: FnOnce() -> T, G: FnOnce() -> E {
        if self { Ok(ok()) } else { Err(err()) }
    }

    fn ok_or<E>(self, err: E) -> Result<(), E> {
        if self { Ok(()) } else { Err(err) }
    }

    fn ok_or_else<E, G>(self, err: G) -> Result<(), E>
    where G: FnOnce() -> E {
        if self { Ok(()) } else { Err(err()) }
    }

    #[inline]
    fn expect(self, msg: &str) {
        if self { () } else { panic!("{}", msg) }
    }
}

/*
Serious code must have serious tests, and Boolinator is serious business!
*/
#[cfg(test)]
mod tests {
    use super::Boolinator; // as opposed to the original NES version.

    #[test]
    fn test_as_option() {
        // Very test.
        assert_eq!(true.as_option(), Some(()));
        assert_eq!(false.as_option(), None);
    }

    #[test]
    fn test_as_some() {
        // Much serious.
        let love = true;
        let everybody = love.as_some("body").expect("needs");
        assert_eq!(everybody, "body");

        assert_eq!((!love).as_some("money can buy"), None);
    }

    #[test]
    fn test_as_some_from() {
        // Wow.
        let mothers = vec![true, false, false, true, false, true];
        assert!(mothers.into_iter()
            .map(|e| e.as_some_from(|| Some("em")))
            .filter(Option::is_some)
            .count() > 0);
    }

    #[test]
    fn test_and_option() {
        // Such original.
        assert_eq!(true.and_option(Some("fries with that")), Some("fries with that"));
        assert_eq!(false.and_option(Some("fries with that")), None);
        assert_eq!(true.and_option(None), None::<()>);
        assert_eq!(false.and_option(None), None::<()>);
    }

    #[test]
    fn test_and_option_from() {
        // Such original.
        assert_eq!(true.and_option_from(|| Some("chips too, guv'")), Some("chips too, guv'"));
        assert_eq!(false.and_option_from(|| Some("chips too, guv'")), None);
        assert_eq!(true.and_option_from(|| None), None::<()>);
        assert_eq!(false.and_option_from(|| None), None::<()>);
    }

    #[test]
    fn test_as_result() {
        // Very result.
        assert_eq!(true.as_result("now; ", ", what?"),   Ok("now; "));
        assert_eq!(false.as_result("now; ", ", what?"),  Err(", what?"));
    }

    #[test]
    fn test_as_result_from() {
        // Code good.
        assert_eq!(true.as_result_from(|| "four space indent", || "anything else"), Ok("four space indent"));
        assert_eq!(false.as_result_from(|| "four space indent", || "anything else"), Err("anything else"));
    }

    #[test]
    fn test_ok_or() {
        // Ok.
        let mut annie = true;
        assert_eq!(annie.ok_or("hit back"), Ok(()));
        annie = false;
        assert_eq!(annie.ok_or("hit back"), Err("hit back"));
    }

    #[test]
    fn test_ok_or_else() {
        // Ok.
        let mut annie = true;
        assert_eq!(annie.ok_or_else(|| "hit back"), Ok(()));
        annie = false;
        assert_eq!(annie.ok_or_else(|| "hit back"), Err("hit back"));
    }

    const DREAMS: &'static str = "love and financial security";

    #[test]
    fn test_expect() {
        // Movies lie.
        true.expect(DREAMS);
    }

    #[test]
    #[should_panic]
    fn test_expect_reality() {
        // Send hugs.
        false.expect(DREAMS);
    }
}
<commit_msg>Make critical improvements to code generation.<commit_after>/*
Copyright ⓒ 2016 Daniel Keep.

Licensed under the MIT license (see LICENSE or <http://opensource.org
/licenses/MIT>) or the Apache License, Version 2.0 (see LICENSE of
<http://www.apache.org/licenses/LICENSE-2.0>), at your option. All
files in the project carrying such notice may not be copied, modified,
or distributed except according to those terms.
*/
/*!

Provides the [`Boolinator`](trait.Boolinator.html) trait, which lets you use `Option` and `Result`-style combinators with `bool`s.

**Links**

* [Latest Release](https://crates.io/crates/boolinator/)
* [Latest Docs](https://danielkeep.github.io/rust-boolinator/doc/boolinator/index.html)
* [Repository](https://github.com/DanielKeep/rust-boolinator)

## Compatibility

`boolinator` is tested against Rust 1.0+.  *Exhaustively* so.

*/
// Can't have undocumented APIs!  Nosiree!
#![deny(missing_docs)]

/**
This trait defines a number of combinator-style methods for use with `bool` values.

In general, `true`/`false` map to `Some(_)`/`None` and `Ok(_)`/`Err(_)` respectively.
*/
pub trait Boolinator: Sized {
    /**
    Converts this value into a logically equivalent `Some(())` or `None`.
    */
    fn as_option(self) -> Option<()>;

    /**
    If this value is `true`, returns `Some(some)`; `None` otherwise.
    */
    fn as_some<T>(self, some: T) -> Option<T>;

    /**
    If this value is `true`, returns `Some(some())`; `None` otherwise.
    */
    fn as_some_from<T, F>(self, some: F) -> Option<T>
    where F: FnOnce() -> T;

    /**
    If this value is `true`, returns `opt`; `None` otherwise.
    */
    fn and_option<T>(self, opt: Option<T>) -> Option<T>;

    /**
    If this value is `true`, returns `opt()`; `None` otherwise.
    */
    fn and_option_from<T, F>(self, opt: F) -> Option<T>
    where F: FnOnce() -> Option<T>;

    /**
    If this value is `true`, returns `Ok(ok)`; `Err(err)` otherwise.
    */
    fn as_result<T, E>(self, ok: T, err: E) -> Result<T, E>;

    /**
    If this value is `true`, returns `Ok(ok())`; `Err(err())` otherwise.
    */
    fn as_result_from<T, E, F, G>(self, ok: F, err: G) -> Result<T, E>
    where F: FnOnce() -> T, G: FnOnce() -> E;

    /**
    If this value is `true`, returns `Ok(())`; `Err(err)` otherwise.
    */
    fn ok_or<E>(self, err: E) -> Result<(), E>;

    /**
    If this value is `true`, returns `Ok(())`; `Err(err())` otherwise.
    */
    fn ok_or_else<E, G>(self, err: G) -> Result<(), E>
    where G: FnOnce() -> E;

    /**
    Panics with `msg` if this value is `false`, otherwise it does nothing.
    */
    fn expect(self, msg: &str);
}

impl Boolinator for bool {
    #[inline]
    fn as_option(self) -> Option<()> {
        if self { Some(()) } else { None }
    }

    #[inline]
    fn as_some<T>(self, some: T) -> Option<T> {
        if self { Some(some) } else { None }
    }

    #[inline]
    fn as_some_from<T, F>(self, some: F) -> Option<T>
    where F: FnOnce() -> T {
        if self { Some(some()) } else { None }
    }

    #[inline]
    fn and_option<T>(self, opt: Option<T>) -> Option<T> {
        if self { opt } else { None }
    }

    #[inline]
    fn and_option_from<T, F>(self, opt: F) -> Option<T>
    where F: FnOnce() -> Option<T> {
        if self { opt() } else { None }
    }

    #[inline]
    fn as_result<T, E>(self, ok: T, err: E) -> Result<T, E> {
        if self { Ok(ok) } else { Err(err) }
    }

    #[inline]
    fn as_result_from<T, E, F, G>(self, ok: F, err: G) -> Result<T, E>
    where F: FnOnce() -> T, G: FnOnce() -> E {
        if self { Ok(ok()) } else { Err(err()) }
    }

    #[inline]
    fn ok_or<E>(self, err: E) -> Result<(), E> {
        if self { Ok(()) } else { Err(err) }
    }

    #[inline]
    fn ok_or_else<E, G>(self, err: G) -> Result<(), E>
    where G: FnOnce() -> E {
        if self { Ok(()) } else { Err(err()) }
    }

    #[inline]
    fn expect(self, msg: &str) {
        if self { () } else { panic!("{}", msg) }
    }
}

/*
Serious code must have serious tests, and Boolinator is serious business!
*/
#[cfg(test)]
mod tests {
    use super::Boolinator; // as opposed to the original NES version.

    #[test]
    fn test_as_option() {
        // Very test.
        assert_eq!(true.as_option(), Some(()));
        assert_eq!(false.as_option(), None);
    }

    #[test]
    fn test_as_some() {
        // Much serious.
        let love = true;
        let everybody = love.as_some("body").expect("needs");
        assert_eq!(everybody, "body");

        assert_eq!((!love).as_some("money can buy"), None);
    }

    #[test]
    fn test_as_some_from() {
        // Wow.
        let mothers = vec![true, false, false, true, false, true];
        assert!(mothers.into_iter()
            .map(|e| e.as_some_from(|| Some("em")))
            .filter(Option::is_some)
            .count() > 0);
    }

    #[test]
    fn test_and_option() {
        // Such original.
        assert_eq!(true.and_option(Some("fries with that")), Some("fries with that"));
        assert_eq!(false.and_option(Some("fries with that")), None);
        assert_eq!(true.and_option(None), None::<()>);
        assert_eq!(false.and_option(None), None::<()>);
    }

    #[test]
    fn test_and_option_from() {
        // Such original.
        assert_eq!(true.and_option_from(|| Some("chips too, guv'")), Some("chips too, guv'"));
        assert_eq!(false.and_option_from(|| Some("chips too, guv'")), None);
        assert_eq!(true.and_option_from(|| None), None::<()>);
        assert_eq!(false.and_option_from(|| None), None::<()>);
    }

    #[test]
    fn test_as_result() {
        // Very result.
        assert_eq!(true.as_result("now; ", ", what?"),   Ok("now; "));
        assert_eq!(false.as_result("now; ", ", what?"),  Err(", what?"));
    }

    #[test]
    fn test_as_result_from() {
        // Code good.
        assert_eq!(true.as_result_from(|| "four space indent", || "anything else"), Ok("four space indent"));
        assert_eq!(false.as_result_from(|| "four space indent", || "anything else"), Err("anything else"));
    }

    #[test]
    fn test_ok_or() {
        // Ok.
        let mut annie = true;
        assert_eq!(annie.ok_or("hit back"), Ok(()));
        annie = false;
        assert_eq!(annie.ok_or("hit back"), Err("hit back"));
    }

    #[test]
    fn test_ok_or_else() {
        // Ok.
        let mut annie = true;
        assert_eq!(annie.ok_or_else(|| "hit back"), Ok(()));
        annie = false;
        assert_eq!(annie.ok_or_else(|| "hit back"), Err("hit back"));
    }

    const DREAMS: &'static str = "love and financial security";

    #[test]
    fn test_expect() {
        // Movies lie.
        true.expect(DREAMS);
    }

    #[test]
    #[should_panic]
    fn test_expect_reality() {
        // Send hugs.
        false.expect(DREAMS);
    }
}
<|endoftext|>


<commit_before>#![feature(fnbox)]

//! Work-stealing job-queue implementation.
//! Inspired by the Molecular Matters blog posts.

use std::borrow::Borrow;
use std::boxed::FnBox;
use std::cell::{Cell, RefCell};
use std::collections::VecDeque;
use std::marker::PhantomData;
use std::mem;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{channel, Sender, Receiver, TryRecvError};

use ::rand::thread_rng;
use ::rand::distributions::{IndependentSample, Range};

extern crate rand;

/// Messages that can be sent to workers.
enum WorkerMessage {
    Stop,
}

/// A job is a unit of work to be done.
struct Job {
    func: Option<Box<FnBox(&Worker) + 'static + Send>>,
    finished: AtomicBool,
}

impl Job {
    // make a new, unrooted job.
    fn new<F: FnOnce(&Worker) + 'static + Send>(f: F) -> Job {
        Job {
            func: Some(Box::new(f)),
            finished: AtomicBool::new(false),
        }
    }

    // run this job.
    fn run(&mut self, worker: &Worker) {
        let f: Box<FnBox(&Worker) + 'static + Send> = match self.func.take() {
            Some(f) => f,
            // jobs should never be run more than once.
            None => unreachable!(),
        };

        FnBox::call_box(f, (worker,));

        self.finished.store(true, Ordering::SeqCst);
    }

    fn is_finished(&self) -> bool {
        self.finished.load(Ordering::SeqCst)
    }
}

/// A thread-safe double-ended queue for jobs.
/// Right now, it's just a dumb locking wrapper of VecDeque.
struct JobQueue {
    inner: Mutex<VecDeque<*mut Job>>,
}

impl JobQueue {
    fn new() -> Self {
        JobQueue {
            inner: Mutex::new(VecDeque::new()),
        }
    }

    // pop a job from the private end of the queue.
    // only the owner of this queue should call this.
    fn pop(&self) -> Option<*mut Job> {
        let mut guard = match self.inner.lock() {
            Ok(g) => g,
            Err(p) => p.into_inner(),
        };

        guard.pop_back()
    }

    // steal a job from the public end of the queu.
    fn steal(&self) -> Option<*mut Job> {
        let mut guard = match self.inner.lock() {
            Ok(g) => g,
            Err(p) => p.into_inner(),
        };

        guard.pop_front()
    }

    // push another job to the queue.
    fn push(&self, job: *mut Job) {
        let mut guard = match self.inner.lock() {
            Ok(g) => g,
            Err(p) => p.into_inner(),
        };

        guard.push_back(job);
    }
}

unsafe impl Send for JobQueue {}
unsafe impl Sync for JobQueue {}

/// A worker thread. This logically owns a queue of jobs to run, and
/// a list of other worker threads' queues to steal from.
pub struct Worker {
    queue: Arc<JobQueue>,
    siblings: Box<[Arc<JobQueue>]>,
}

impl Worker {
    /// Submit a job to be run by this worker.
    /// You must use this handle to join
    pub fn submit<F: FnOnce(&Worker) + 'static + Send>(&self, f: F) -> JoinHandle {
        let job = Box::new(Job::new(f));
        self.give_job(&*job as *const _ as *mut Job);

        JoinHandle {
            job: job,
            worker: self,
        }
    }

    /// Create an execution scope where you can run jobs with a non-static
    /// lifetime.
    pub fn scope<'a, 'b, F>(&'a self, f: F)
    where F: FnOnce(&Scope<'a, 'b>) {
        let scope = Scope {
            worker: self,
            children: RefCell::new(Vec::new()),
            _marker: PhantomData,
        };

        f(&scope);

        drop(scope);
    }

    fn give_job(&self, job: *mut Job) {
        self.queue.push(job);
    }

    // Get a job from this queue or another.
    fn get_job(&self) -> Option<*mut Job> {
        if let Some(job) = self.queue.pop() {
            Some(job)
        } else {
            let mut rng = thread_rng();
            // ranges are [low, high)
            let dist_range = Range::new(0, self.siblings.len());

            let other_queue: &Arc<JobQueue> = &self.siblings[dist_range.ind_sample(&mut rng)];
            if &**other_queue as *const JobQueue != &*self.queue as *const JobQueue {
                other_queue.steal()
            } else {
                None
            }
        }
    }

    fn run_job(&self) {
        if let Some(job) = self.get_job() {
            unsafe { (*job).run(self) }
        }
    }
}

/// A handle to a specific job.
/// Users can either call `wait()` to explicitly wait for the job
/// to finish, or the job will be waited for at the end of scope.
/// This handle will not cause any memory unsafety when leaked.
#[must_use]
pub struct JoinHandle<'a> {
    job: Box<Job>,
    worker: &'a Worker,
}

impl<'a> JoinHandle<'a> {
    /// Wait for this job to be finished.
    /// This is identical to dropping the guard.
    pub fn wait(self) {
        drop(self);
    }

    fn wait_(&self) {
        // work while we wait.
        while !self.job.is_finished() {
            self.worker.run_job();
        }
    }

    // TODO: find a way to release that doesn't involve
    // leaking memory or dropping the box.
    // I suspect it'll come when I change boxing jobs to
    // allocating them from a thread-local pool.
}

impl<'a> Drop for JoinHandle<'a> {
    fn drop(&mut self) {
        self.wait_();
    }
}

/// An execution scope for jobs.
pub struct Scope<'a, 'b> {
    worker: &'a Worker,
    children: RefCell<Vec<Box<Job>>>,
    _marker: PhantomData<Cell<&'b ()>>,
}

impl<'a, 'b> Scope<'a, 'b>{
    /// Submit a job to be completed within this scope.
    pub fn submit<F>(&'a self, f: F) -> ChildHandle<'a>
    where F: FnOnce(&Worker) + 'b + Send {
        let bounded_fn: Box<FnBox(&Worker) + 'b + Send> = Box::new(f);
        let unbounded_fn: Box<FnBox(&Worker) + 'static + Send> = unsafe { mem::transmute(bounded_fn) };

        let job = Box::new(Job {
            func: Some(unbounded_fn),
            finished: AtomicBool::new(false),
        });

        let job_ptr = &*job as *const _ as *mut Job;
        self.children.borrow_mut().push(job);

        self.worker.give_job(job_ptr);

        // this handle is safe to leak and drop:
        // the scope object owns the jobs' memory and
        // also enforces that the jobs don't outlive it.
        ChildHandle {
            job: job_ptr,
            worker: &self.worker,
        }
    }

    fn wait_all(&self) {
        // wait until all the children are done.
        for child in self.children.borrow().iter() {
            while !child.is_finished() {
                self.worker.run_job();
            }
        }
    }
}

impl<'a, 'b> Drop for Scope<'a, 'b> {
    fn drop(&mut self) {
        self.wait_all();
    }
}

/// A handle to a job spawned within a scope. Users can manually
/// `wait()` until it's completed. They can also `release()`
/// the guard to defer its completion to an arbitrary time
/// within its lifetime.
pub struct ChildHandle<'a> {
    job: *mut Job,
    worker: &'a Worker,
}

impl<'a> ChildHandle<'a> {
    /// Wait for this job to be finished.
    pub fn wait(self) {
        if self.job.is_null() { return; }

        // work while we wait.
        while unsafe { !(*self.job).is_finished() } {
            self.worker.run_job();
        }
    }

    /// Releases this job. This allows it to be finished
    /// at any point within the job's lifetime.
    pub fn release(self) {
        drop(self)
    }
}

/// The JobSystem holds a worker for the thread it exists on,
/// as well as handles to all the other threads.
pub struct JobSystem {
    handles: Vec<Sender<WorkerMessage>>,
    worker: Worker,
    // to mark it !Send
    _marker: PhantomData<*mut ()>,
}

impl JobSystem {
    /// Gets a reference to the worker for this thread.
    pub fn get_worker(&self) -> &Worker {
        &self.worker
    }
}

// No unsafety is induced by not stopping the handles.
// However, the threads will spin forever, which probably
// isn't ideal.
impl Drop for JobSystem {
    fn drop(&mut self) {
        for handle in &mut self.handles {
            // at this point, either the worker receives
            // the message or it's already shut down.
            let _ = handle.send(WorkerMessage::Stop);
        }
    }
}

/// Create a new `JobSystem` with `n_threads` workers, including the
/// current thread. This will fail if `n_threads` is 0.
pub fn make_pool(n_threads: usize) -> Option<JobSystem> {
    use std::thread;

    if n_threads == 0 {
        return None;
    }

    // make a queue for every thread, including this one.
    let queues: Vec<_> = (0..n_threads)
        .map(|_| Arc::new(JobQueue::new())).collect();

    let queues = queues.into_boxed_slice();

    let mut handles = Vec::new();

    // Spawn a worker thread for every queue but the last one,
    // since that belongs to the thread this is spawned on.
    for queue in queues.iter().cloned().take(queues.len() - 1) {
        let (tx, rx) = channel();
        let siblings = queues.clone();

        thread::spawn(move || {
            let worker = Worker {
                queue: queue,
                siblings: siblings,
            };
            worker_main(worker, rx);
        });
        handles.push(tx);
    }

    Some(JobSystem {
        handles: handles,
        worker: Worker {
            queue: queues.last().unwrap().clone(),
            siblings: queues,
        },
        _marker: PhantomData,
    })
}

// the main thread for each worker
fn worker_main(worker: Worker, rx: Receiver<WorkerMessage>) {
    loop {
        // check for message
        match rx.try_recv() {
            // time to stop!
            Ok(WorkerMessage::Stop) => {
                break;
            }

            // somehow the JobSystem got dropped without disconnecting.
            Err(TryRecvError::Disconnected) => {
                break;
            }

            _ => {}
        }

        // run a job
        worker.run_job();
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn basic_spawning() {
        // four worker threads, including this one.
        let pool = make_pool(4).unwrap();
        let this_worker = pool.get_worker();

        let mut my_jobs = Vec::new();

        for _ in 0..100 {
            let handle = this_worker.submit(|_| println!("Hello!"));
            my_jobs.push(handle);
        }
    }

    #[test]
    fn child_jobs() {
        let pool = make_pool(4).unwrap();
        let this_worker = pool.get_worker();

        this_worker.submit(|worker| {
            let mut jobs = Vec::new();
            for _ in 0..100 {
                let handle = worker.submit(|_| println!("Hello!"));
                jobs.push(handle);
            };
        }).wait();
    }

    #[test]
    fn scoping() {
        let pool = make_pool(4).unwrap();
        let this_worker = pool.get_worker();
        this_worker.submit(|worker| {
            let mut v = vec![0; 256];

            worker.scope(|scope| {
                for chunk in v.chunks_mut(32) {
                    scope.submit(move |_| {
                        for i in chunk { *i += 1 }
                    }).release();
                }
            });

            for i in v {
                assert_eq!(i, 1);
            }

        }).wait();
    }
}<commit_msg>Removed unnecessary dependency on Cell for invariant lifetime<commit_after>#![feature(fnbox)]

//! Work-stealing job-queue implementation.
//! Inspired by the Molecular Matters blog posts.

use std::borrow::Borrow;
use std::boxed::FnBox;
use std::cell::RefCell;
use std::collections::VecDeque;
use std::marker::PhantomData;
use std::mem;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{channel, Sender, Receiver, TryRecvError};

use ::rand::thread_rng;
use ::rand::distributions::{IndependentSample, Range};

extern crate rand;

/// Messages that can be sent to workers.
enum WorkerMessage {
    Stop,
}

/// A job is a unit of work to be done.
struct Job {
    func: Option<Box<FnBox(&Worker) + 'static + Send>>,
    finished: AtomicBool,
}

impl Job {
    // make a new, unrooted job.
    fn new<F: FnOnce(&Worker) + 'static + Send>(f: F) -> Job {
        Job {
            func: Some(Box::new(f)),
            finished: AtomicBool::new(false),
        }
    }

    // run this job.
    fn run(&mut self, worker: &Worker) {
        let f: Box<FnBox(&Worker) + 'static + Send> = match self.func.take() {
            Some(f) => f,
            // jobs should never be run more than once.
            None => unreachable!(),
        };

        FnBox::call_box(f, (worker,));

        self.finished.store(true, Ordering::SeqCst);
    }

    fn is_finished(&self) -> bool {
        self.finished.load(Ordering::SeqCst)
    }
}

/// A thread-safe double-ended queue for jobs.
/// Right now, it's just a dumb locking wrapper of VecDeque.
struct JobQueue {
    inner: Mutex<VecDeque<*mut Job>>,
}

impl JobQueue {
    fn new() -> Self {
        JobQueue {
            inner: Mutex::new(VecDeque::new()),
        }
    }

    // pop a job from the private end of the queue.
    // only the owner of this queue should call this.
    fn pop(&self) -> Option<*mut Job> {
        let mut guard = match self.inner.lock() {
            Ok(g) => g,
            Err(p) => p.into_inner(),
        };

        guard.pop_back()
    }

    // steal a job from the public end of the queu.
    fn steal(&self) -> Option<*mut Job> {
        let mut guard = match self.inner.lock() {
            Ok(g) => g,
            Err(p) => p.into_inner(),
        };

        guard.pop_front()
    }

    // push another job to the queue.
    fn push(&self, job: *mut Job) {
        let mut guard = match self.inner.lock() {
            Ok(g) => g,
            Err(p) => p.into_inner(),
        };

        guard.push_back(job);
    }
}

unsafe impl Send for JobQueue {}
unsafe impl Sync for JobQueue {}

/// A worker thread. This logically owns a queue of jobs to run, and
/// a list of other worker threads' queues to steal from.
pub struct Worker {
    queue: Arc<JobQueue>,
    siblings: Box<[Arc<JobQueue>]>,
}

impl Worker {
    /// Submit a job to be run by this worker.
    /// You must use this handle to join
    pub fn submit<F: FnOnce(&Worker) + 'static + Send>(&self, f: F) -> JoinHandle {
        let job = Box::new(Job::new(f));
        self.give_job(&*job as *const _ as *mut Job);

        JoinHandle {
            job: job,
            worker: self,
        }
    }

    /// Create an execution scope where you can run jobs with a non-static
    /// lifetime.
    pub fn scope<'a, 'b, F>(&'a self, f: F)
    where F: FnOnce(&Scope<'a, 'b>) {
        let scope = Scope {
            worker: self,
            children: RefCell::new(Vec::new()),
            _marker: PhantomData,
        };

        f(&scope);

        drop(scope);
    }

    fn give_job(&self, job: *mut Job) {
        self.queue.push(job);
    }

    // Get a job from this queue or another.
    fn get_job(&self) -> Option<*mut Job> {
        if let Some(job) = self.queue.pop() {
            Some(job)
        } else {
            let mut rng = thread_rng();
            // ranges are [low, high)
            let dist_range = Range::new(0, self.siblings.len());

            let other_queue: &Arc<JobQueue> = &self.siblings[dist_range.ind_sample(&mut rng)];
            if &**other_queue as *const JobQueue != &*self.queue as *const JobQueue {
                other_queue.steal()
            } else {
                None
            }
        }
    }

    fn run_job(&self) {
        if let Some(job) = self.get_job() {
            unsafe { (*job).run(self) }
        }
    }
}

/// A handle to a specific job.
/// Users can either call `wait()` to explicitly wait for the job
/// to finish, or the job will be waited for at the end of scope.
/// This handle will not cause any memory unsafety when leaked.
#[must_use]
pub struct JoinHandle<'a> {
    job: Box<Job>,
    worker: &'a Worker,
}

impl<'a> JoinHandle<'a> {
    /// Wait for this job to be finished.
    /// This is identical to dropping the guard.
    pub fn wait(self) {
        drop(self);
    }

    fn wait_(&self) {
        // work while we wait.
        while !self.job.is_finished() {
            self.worker.run_job();
        }
    }

    // TODO: find a way to release that doesn't involve
    // leaking memory or dropping the box.
    // I suspect it'll come when I change boxing jobs to
    // allocating them from a thread-local pool.
}

impl<'a> Drop for JoinHandle<'a> {
    fn drop(&mut self) {
        self.wait_();
    }
}

/// An execution scope for jobs.
pub struct Scope<'a, 'b> {
    worker: &'a Worker,
    children: RefCell<Vec<Box<Job>>>,
    _marker: PhantomData<*mut &'b Job>,
}

impl<'a, 'b> Scope<'a, 'b>{
    /// Submit a job to be completed within this scope.
    pub fn submit<F>(&'a self, f: F) -> ChildHandle<'a>
    where F: FnOnce(&Worker) + 'b + Send {
        let bounded_fn: Box<FnBox(&Worker) + 'b + Send> = Box::new(f);
        let unbounded_fn: Box<FnBox(&Worker) + 'static + Send> = unsafe { mem::transmute(bounded_fn) };

        let job = Box::new(Job {
            func: Some(unbounded_fn),
            finished: AtomicBool::new(false),
        });

        let job_ptr = &*job as *const _ as *mut Job;
        self.children.borrow_mut().push(job);

        self.worker.give_job(job_ptr);

        // this handle is safe to leak and drop:
        // the scope object owns the jobs' memory and
        // also enforces that the jobs don't outlive it.
        ChildHandle {
            job: job_ptr,
            worker: &self.worker,
        }
    }

    fn wait_all(&self) {
        // wait until all the children are done.
        for child in self.children.borrow().iter() {
            while !child.is_finished() {
                self.worker.run_job();
            }
        }
    }
}

impl<'a, 'b> Drop for Scope<'a, 'b> {
    fn drop(&mut self) {
        self.wait_all();
    }
}

/// A handle to a job spawned within a scope. Users can manually
/// `wait()` until it's completed. They can also `release()`
/// the guard to defer its completion to an arbitrary time
/// within its lifetime.
pub struct ChildHandle<'a> {
    job: *mut Job,
    worker: &'a Worker,
}

impl<'a> ChildHandle<'a> {
    /// Wait for this job to be finished.
    pub fn wait(self) {
        if self.job.is_null() { return; }

        // work while we wait.
        while unsafe { !(*self.job).is_finished() } {
            self.worker.run_job();
        }
    }

    /// Releases this job. This allows it to be finished
    /// at any point within the job's lifetime.
    pub fn release(self) {
        drop(self)
    }
}

/// The JobSystem holds a worker for the thread it exists on,
/// as well as handles to all the other threads.
pub struct JobSystem {
    handles: Vec<Sender<WorkerMessage>>,
    worker: Worker,
    // to mark it !Send
    _marker: PhantomData<*mut ()>,
}

impl JobSystem {
    /// Gets a reference to the worker for this thread.
    pub fn get_worker(&self) -> &Worker {
        &self.worker
    }
}

// No unsafety is induced by not stopping the handles.
// However, the threads will spin forever, which probably
// isn't ideal.
impl Drop for JobSystem {
    fn drop(&mut self) {
        for handle in &mut self.handles {
            // at this point, either the worker receives
            // the message or it's already shut down.
            let _ = handle.send(WorkerMessage::Stop);
        }
    }
}

/// Create a new `JobSystem` with `n_threads` workers, including the
/// current thread. This will fail if `n_threads` is 0.
pub fn make_pool(n_threads: usize) -> Option<JobSystem> {
    use std::thread;

    if n_threads == 0 {
        return None;
    }

    // make a queue for every thread, including this one.
    let queues: Vec<_> = (0..n_threads)
        .map(|_| Arc::new(JobQueue::new())).collect();

    let queues = queues.into_boxed_slice();

    let mut handles = Vec::new();

    // Spawn a worker thread for every queue but the last one,
    // since that belongs to the thread this is spawned on.
    for queue in queues.iter().cloned().take(queues.len() - 1) {
        let (tx, rx) = channel();
        let siblings = queues.clone();

        thread::spawn(move || {
            let worker = Worker {
                queue: queue,
                siblings: siblings,
            };
            worker_main(worker, rx);
        });
        handles.push(tx);
    }

    Some(JobSystem {
        handles: handles,
        worker: Worker {
            queue: queues.last().unwrap().clone(),
            siblings: queues,
        },
        _marker: PhantomData,
    })
}

// the main thread for each worker
fn worker_main(worker: Worker, rx: Receiver<WorkerMessage>) {
    loop {
        // check for message
        match rx.try_recv() {
            // time to stop!
            Ok(WorkerMessage::Stop) => {
                break;
            }

            // somehow the JobSystem got dropped without disconnecting.
            Err(TryRecvError::Disconnected) => {
                break;
            }

            _ => {}
        }

        // run a job
        worker.run_job();
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn basic_spawning() {
        // four worker threads, including this one.
        let pool = make_pool(4).unwrap();
        let this_worker = pool.get_worker();

        let mut my_jobs = Vec::new();

        for _ in 0..100 {
            let handle = this_worker.submit(|_| println!("Hello!"));
            my_jobs.push(handle);
        }
    }

    #[test]
    fn child_jobs() {
        let pool = make_pool(4).unwrap();
        let this_worker = pool.get_worker();

        this_worker.submit(|worker| {
            let mut jobs = Vec::new();
            for _ in 0..100 {
                let handle = worker.submit(|_| println!("Hello!"));
                jobs.push(handle);
            };
        }).wait();
    }

    #[test]
    fn scoping() {
        let pool = make_pool(4).unwrap();
        let this_worker = pool.get_worker();
        this_worker.submit(|worker| {
            let mut v = vec![0; 256];

            worker.scope(|scope| {
                for chunk in v.chunks_mut(32) {
                    scope.submit(move |_| {
                        for i in chunk { *i += 1 }
                    }).release();
                }
            });

            for i in v {
                assert_eq!(i, 1);
            }

        }).wait();
    }
}<|endoftext|>