<commit_before>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Worker that runs in a virtio-video thread.

use std::collections::VecDeque;

use base::{error, info, Event, Tube, WaitContext};
use vm_memory::GuestMemory;

use crate::virtio::queue::{DescriptorChain, Queue};
use crate::virtio::video::async_cmd_desc_map::AsyncCmdDescMap;
use crate::virtio::video::command::{QueueType, VideoCmd};
use crate::virtio::video::device::{
    AsyncCmdResponse, AsyncCmdTag, Device, Token, VideoCmdResponseType, VideoEvtResponseType,
};
use crate::virtio::video::event::{self, EvtType, VideoEvt};
use crate::virtio::video::response::{self, Response};
use crate::virtio::video::{Error, Result};
use crate::virtio::{Interrupt, Reader, SignalableInterrupt, Writer};

pub struct Worker {
    interrupt: Interrupt,
    mem: GuestMemory,
    cmd_queue: Queue,
    cmd_evt: Event,
    event_queue: Queue,
    event_evt: Event,
    kill_evt: Event,
    resource_bridge: Tube,
}

/// Pair of a descriptor chain and a response to be written.
type WritableResp = (DescriptorChain, response::CmdResponse);

impl Worker {
    pub fn new(
        interrupt: Interrupt,
        mem: GuestMemory,
        cmd_queue: Queue,
        cmd_evt: Event,
        event_queue: Queue,
        event_evt: Event,
        kill_evt: Event,
        resource_bridge: Tube,
    ) -> Self {
        Self {
            interrupt,
            mem,
            cmd_queue,
            cmd_evt,
            event_queue,
            event_evt,
            kill_evt,
            resource_bridge,
        }
    }

    /// Writes responses into the command queue.
    fn write_responses(&mut self, responses: &mut VecDeque<WritableResp>) -> Result<()> {
        if responses.is_empty() {
            return Ok(());
        }
        while let Some((desc, response)) = responses.pop_front() {
            let desc_index = desc.index;
            let mut writer =
                Writer::new(self.mem.clone(), desc).map_err(Error::InvalidDescriptorChain)?;
            if let Err(e) = response.write(&mut writer) {
                error!(
                    "failed to write a command response for {:?}: {}",
                    response, e
                );
            }
            self.cmd_queue
                .add_used(&self.mem, desc_index, writer.bytes_written() as u32);
        }
        self.interrupt.signal_used_queue(self.cmd_queue.vector);
        Ok(())
    }

    /// Writes a `VideoEvt` into the event queue.
    fn write_event(&mut self, event: event::VideoEvt) -> Result<()> {
        let desc = self
            .event_queue
            .pop(&self.mem)
            .ok_or(Error::DescriptorNotAvailable)?;

        let desc_index = desc.index;
        let mut writer =
            Writer::new(self.mem.clone(), desc).map_err(Error::InvalidDescriptorChain)?;
        event
            .write(&mut writer)
            .map_err(|error| Error::WriteEventFailure { event, error })?;
        self.event_queue
            .add_used(&self.mem, desc_index, writer.bytes_written() as u32);
        self.interrupt.signal_used_queue(self.event_queue.vector);
        Ok(())
    }

    fn write_event_responses(
        &mut self,
        event_responses: Vec<VideoEvtResponseType>,
        desc_map: &mut AsyncCmdDescMap,
        stream_id: u32,
    ) -> Result<()> {
        let mut responses: VecDeque<WritableResp> = Default::default();
        for event_response in event_responses {
            match event_response {
                VideoEvtResponseType::AsyncCmd(async_response) => {
                    let AsyncCmdResponse {
                        tag,
                        response: cmd_result,
                    } = async_response;
                    match desc_map.remove(&tag) {
                        Some(desc) => {
                            let cmd_response = match cmd_result {
                                Ok(r) => r,
                                Err(e) => {
                                    error!("returning async error response: {}", &e);
                                    e.into()
                                }
                            };
                            responses.push_back((desc, cmd_response))
                        }
                        None => match tag {
                            // TODO(b/153406792): Drain is cancelled by clearing either of the
                            // stream's queues. To work around a limitation in the VDA api, the
                            // output queue is cleared synchronously without going through VDA.
                            // Because of this, the cancellation response from VDA for the
                            // input queue might fail to find the drain's AsyncCmdTag.
                            AsyncCmdTag::Drain { stream_id: _ } => {
                                info!("ignoring unknown drain response");
                            }
                            _ => {
                                error!("dropping response for an untracked command: {:?}", tag);
                            }
                        },
                    }
                }
                VideoEvtResponseType::Event(evt) => {
                    self.write_event(evt)?;
                }
            }
        }

        if let Err(e) = self.write_responses(&mut responses) {
            error!("Failed to write event responses: {:?}", e);
            // Ignore result of write_event for a fatal error.
            let _ = self.write_event(VideoEvt {
                typ: EvtType::Error,
                stream_id,
            });
            return Err(e);
        }

        Ok(())
    }

    /// Handles a `DescriptorChain` value sent via the command queue and returns a `VecDeque`
    /// of `WritableResp` to be sent to the guest.
    fn handle_command_desc(
        &mut self,
        device: &mut dyn Device,
        wait_ctx: &WaitContext<Token>,
        desc_map: &mut AsyncCmdDescMap,
        desc: DescriptorChain,
    ) -> Result<VecDeque<WritableResp>> {
        let mut responses: VecDeque<WritableResp> = Default::default();
        let mut reader =
            Reader::new(self.mem.clone(), desc.clone()).map_err(Error::InvalidDescriptorChain)?;

        let cmd = VideoCmd::from_reader(&mut reader).map_err(Error::ReadFailure)?;

        // If a destruction command comes, cancel pending requests.
        // TODO(b/161774071): Allow `process_cmd` to return multiple responses and move this
        // into encoder/decoder.
        let async_responses = match cmd {
            VideoCmd::ResourceDestroyAll {
                stream_id,
                queue_type,
            } => desc_map.create_cancellation_responses(&stream_id, Some(queue_type), None),
            VideoCmd::StreamDestroy { stream_id } => {
                desc_map.create_cancellation_responses(&stream_id, None, None)
            }
            VideoCmd::QueueClear {
                stream_id,
                queue_type: QueueType::Output,
            } => {
                // TODO(b/153406792): Due to a workaround for a limitation in the VDA api,
                // clearing the output queue doesn't go through the same Async path as clearing
                // the input queue. However, we still need to cancel the pending resources.
                desc_map.create_cancellation_responses(&stream_id, Some(QueueType::Output), None)
            }
            _ => Default::default(),
        };
        for async_response in async_responses {
            let AsyncCmdResponse {
                tag,
                response: cmd_result,
            } = async_response;
            let destroy_response = match cmd_result {
                Ok(r) => r,
                Err(e) => {
                    error!("returning async error response: {}", &e);
                    e.into()
                }
            };
            match desc_map.remove(&tag) {
                Some(destroy_desc) => {
                    responses.push_back((destroy_desc, destroy_response));
                }
                None => error!("dropping response for an untracked command: {:?}", tag),
            }
        }

        // Process the command by the device.
        let (cmd_response, event_responses_with_id) =
            device.process_cmd(cmd, &wait_ctx, &self.resource_bridge);
        match cmd_response {
            VideoCmdResponseType::Sync(r) => {
                responses.push_back((desc, r));
            }
            VideoCmdResponseType::Async(tag) => {
                // If the command expects an asynchronous response,
                // store `desc` to use it after the back-end device notifies the
                // completion.
                desc_map.insert(tag, desc);
            }
        }
        if let Some((stream_id, event_responses)) = event_responses_with_id {
            self.write_event_responses(event_responses, desc_map, stream_id)?;
        }

        Ok(responses)
    }

    /// Handles each command in the command queue.
    fn handle_command_queue(
        &mut self,
        device: &mut dyn Device,
        wait_ctx: &WaitContext<Token>,
        desc_map: &mut AsyncCmdDescMap,
    ) -> Result<()> {
        let _ = self.cmd_evt.read();
        while let Some(desc) = self.cmd_queue.pop(&self.mem) {
            let mut resps = self.handle_command_desc(device, wait_ctx, desc_map, desc)?;
            self.write_responses(&mut resps)?;
        }
        Ok(())
    }

    /// Handles an event notified via an event.
    fn handle_event(
        &mut self,
        device: &mut dyn Device,
        desc_map: &mut AsyncCmdDescMap,
        stream_id: u32,
    ) -> Result<()> {
        if let Some(event_responses) = device.process_event(desc_map, stream_id) {
            self.write_event_responses(event_responses, desc_map, stream_id)?;
        }
        Ok(())
    }

    pub fn run(&mut self, mut device: Box<dyn Device>) -> Result<()> {
        let wait_ctx: WaitContext<Token> = WaitContext::build_with(&[
            (&self.cmd_evt, Token::CmdQueue),
            (&self.event_evt, Token::EventQueue),
            (&self.kill_evt, Token::Kill),
        ])
        .and_then(|wc| {
            if let Some(resample_evt) = self.interrupt.get_resample_evt() {
                wc.add(resample_evt, Token::InterruptResample)?;
            }
            Ok(wc)
        })
        .map_err(Error::WaitContextCreationFailed)?;

        // Stores descriptors in which responses for asynchronous commands will be written.
        let mut desc_map: AsyncCmdDescMap = Default::default();

        loop {
            let wait_events = wait_ctx.wait().map_err(Error::WaitError)?;

            for wait_event in wait_events.iter().filter(|e| e.is_readable) {
                match wait_event.token {
                    Token::CmdQueue => {
                        self.handle_command_queue(device.as_mut(), &wait_ctx, &mut desc_map)?;
                    }
                    Token::EventQueue => {
                        let _ = self.event_evt.read();
                    }
                    Token::Event { id } => {
                        self.handle_event(device.as_mut(), &mut desc_map, id)?;
                    }
                    Token::InterruptResample => {
                        self.interrupt.interrupt_resample();
                    }
                    Token::Kill => return Ok(()),
                }
            }
        }
    }
}
<commit_msg>virtio: video: move desc_map into Worker<commit_after>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Worker that runs in a virtio-video thread.

use std::collections::VecDeque;

use base::{error, info, Event, Tube, WaitContext};
use vm_memory::GuestMemory;

use crate::virtio::queue::{DescriptorChain, Queue};
use crate::virtio::video::async_cmd_desc_map::AsyncCmdDescMap;
use crate::virtio::video::command::{QueueType, VideoCmd};
use crate::virtio::video::device::{
    AsyncCmdResponse, AsyncCmdTag, Device, Token, VideoCmdResponseType, VideoEvtResponseType,
};
use crate::virtio::video::event::{self, EvtType, VideoEvt};
use crate::virtio::video::response::{self, Response};
use crate::virtio::video::{Error, Result};
use crate::virtio::{Interrupt, Reader, SignalableInterrupt, Writer};

pub struct Worker {
    interrupt: Interrupt,
    mem: GuestMemory,
    cmd_queue: Queue,
    cmd_evt: Event,
    event_queue: Queue,
    event_evt: Event,
    kill_evt: Event,
    resource_bridge: Tube,
    // Stores descriptors in which responses for asynchronous commands will be written.
    desc_map: AsyncCmdDescMap,
}

/// Pair of a descriptor chain and a response to be written.
type WritableResp = (DescriptorChain, response::CmdResponse);

impl Worker {
    pub fn new(
        interrupt: Interrupt,
        mem: GuestMemory,
        cmd_queue: Queue,
        cmd_evt: Event,
        event_queue: Queue,
        event_evt: Event,
        kill_evt: Event,
        resource_bridge: Tube,
    ) -> Self {
        Self {
            interrupt,
            mem,
            cmd_queue,
            cmd_evt,
            event_queue,
            event_evt,
            kill_evt,
            resource_bridge,
            desc_map: Default::default(),
        }
    }

    /// Writes responses into the command queue.
    fn write_responses(&mut self, responses: &mut VecDeque<WritableResp>) -> Result<()> {
        if responses.is_empty() {
            return Ok(());
        }
        while let Some((desc, response)) = responses.pop_front() {
            let desc_index = desc.index;
            let mut writer =
                Writer::new(self.mem.clone(), desc).map_err(Error::InvalidDescriptorChain)?;
            if let Err(e) = response.write(&mut writer) {
                error!(
                    "failed to write a command response for {:?}: {}",
                    response, e
                );
            }
            self.cmd_queue
                .add_used(&self.mem, desc_index, writer.bytes_written() as u32);
        }
        self.interrupt.signal_used_queue(self.cmd_queue.vector);
        Ok(())
    }

    /// Writes a `VideoEvt` into the event queue.
    fn write_event(&mut self, event: event::VideoEvt) -> Result<()> {
        let desc = self
            .event_queue
            .pop(&self.mem)
            .ok_or(Error::DescriptorNotAvailable)?;

        let desc_index = desc.index;
        let mut writer =
            Writer::new(self.mem.clone(), desc).map_err(Error::InvalidDescriptorChain)?;
        event
            .write(&mut writer)
            .map_err(|error| Error::WriteEventFailure { event, error })?;
        self.event_queue
            .add_used(&self.mem, desc_index, writer.bytes_written() as u32);
        self.interrupt.signal_used_queue(self.event_queue.vector);
        Ok(())
    }

    fn write_event_responses(
        &mut self,
        event_responses: Vec<VideoEvtResponseType>,
        stream_id: u32,
    ) -> Result<()> {
        let mut responses: VecDeque<WritableResp> = Default::default();
        for event_response in event_responses {
            match event_response {
                VideoEvtResponseType::AsyncCmd(async_response) => {
                    let AsyncCmdResponse {
                        tag,
                        response: cmd_result,
                    } = async_response;
                    match self.desc_map.remove(&tag) {
                        Some(desc) => {
                            let cmd_response = match cmd_result {
                                Ok(r) => r,
                                Err(e) => {
                                    error!("returning async error response: {}", &e);
                                    e.into()
                                }
                            };
                            responses.push_back((desc, cmd_response))
                        }
                        None => match tag {
                            // TODO(b/153406792): Drain is cancelled by clearing either of the
                            // stream's queues. To work around a limitation in the VDA api, the
                            // output queue is cleared synchronously without going through VDA.
                            // Because of this, the cancellation response from VDA for the
                            // input queue might fail to find the drain's AsyncCmdTag.
                            AsyncCmdTag::Drain { stream_id: _ } => {
                                info!("ignoring unknown drain response");
                            }
                            _ => {
                                error!("dropping response for an untracked command: {:?}", tag);
                            }
                        },
                    }
                }
                VideoEvtResponseType::Event(evt) => {
                    self.write_event(evt)?;
                }
            }
        }

        if let Err(e) = self.write_responses(&mut responses) {
            error!("Failed to write event responses: {:?}", e);
            // Ignore result of write_event for a fatal error.
            let _ = self.write_event(VideoEvt {
                typ: EvtType::Error,
                stream_id,
            });
            return Err(e);
        }

        Ok(())
    }

    /// Handles a `DescriptorChain` value sent via the command queue and returns a `VecDeque`
    /// of `WritableResp` to be sent to the guest.
    fn handle_command_desc(
        &mut self,
        device: &mut dyn Device,
        wait_ctx: &WaitContext<Token>,
        desc: DescriptorChain,
    ) -> Result<VecDeque<WritableResp>> {
        let mut responses: VecDeque<WritableResp> = Default::default();
        let mut reader =
            Reader::new(self.mem.clone(), desc.clone()).map_err(Error::InvalidDescriptorChain)?;

        let cmd = VideoCmd::from_reader(&mut reader).map_err(Error::ReadFailure)?;

        // If a destruction command comes, cancel pending requests.
        // TODO(b/161774071): Allow `process_cmd` to return multiple responses and move this
        // into encoder/decoder.
        let async_responses = match cmd {
            VideoCmd::ResourceDestroyAll {
                stream_id,
                queue_type,
            } => self
                .desc_map
                .create_cancellation_responses(&stream_id, Some(queue_type), None),
            VideoCmd::StreamDestroy { stream_id } => self
                .desc_map
                .create_cancellation_responses(&stream_id, None, None),
            VideoCmd::QueueClear {
                stream_id,
                queue_type: QueueType::Output,
            } => {
                // TODO(b/153406792): Due to a workaround for a limitation in the VDA api,
                // clearing the output queue doesn't go through the same Async path as clearing
                // the input queue. However, we still need to cancel the pending resources.
                self.desc_map.create_cancellation_responses(
                    &stream_id,
                    Some(QueueType::Output),
                    None,
                )
            }
            _ => Default::default(),
        };
        for async_response in async_responses {
            let AsyncCmdResponse {
                tag,
                response: cmd_result,
            } = async_response;
            let destroy_response = match cmd_result {
                Ok(r) => r,
                Err(e) => {
                    error!("returning async error response: {}", &e);
                    e.into()
                }
            };
            match self.desc_map.remove(&tag) {
                Some(destroy_desc) => {
                    responses.push_back((destroy_desc, destroy_response));
                }
                None => error!("dropping response for an untracked command: {:?}", tag),
            }
        }

        // Process the command by the device.
        let (cmd_response, event_responses_with_id) =
            device.process_cmd(cmd, &wait_ctx, &self.resource_bridge);
        match cmd_response {
            VideoCmdResponseType::Sync(r) => {
                responses.push_back((desc, r));
            }
            VideoCmdResponseType::Async(tag) => {
                // If the command expects an asynchronous response,
                // store `desc` to use it after the back-end device notifies the
                // completion.
                self.desc_map.insert(tag, desc);
            }
        }
        if let Some((stream_id, event_responses)) = event_responses_with_id {
            self.write_event_responses(event_responses, stream_id)?;
        }

        Ok(responses)
    }

    /// Handles each command in the command queue.
    fn handle_command_queue(
        &mut self,
        device: &mut dyn Device,
        wait_ctx: &WaitContext<Token>,
    ) -> Result<()> {
        let _ = self.cmd_evt.read();
        while let Some(desc) = self.cmd_queue.pop(&self.mem) {
            let mut resps = self.handle_command_desc(device, wait_ctx, desc)?;
            self.write_responses(&mut resps)?;
        }
        Ok(())
    }

    /// Handles an event notified via an event.
    fn handle_event(&mut self, device: &mut dyn Device, stream_id: u32) -> Result<()> {
        if let Some(event_responses) = device.process_event(&mut self.desc_map, stream_id) {
            self.write_event_responses(event_responses, stream_id)?;
        }
        Ok(())
    }

    pub fn run(&mut self, mut device: Box<dyn Device>) -> Result<()> {
        let wait_ctx: WaitContext<Token> = WaitContext::build_with(&[
            (&self.cmd_evt, Token::CmdQueue),
            (&self.event_evt, Token::EventQueue),
            (&self.kill_evt, Token::Kill),
        ])
        .and_then(|wc| {
            if let Some(resample_evt) = self.interrupt.get_resample_evt() {
                wc.add(resample_evt, Token::InterruptResample)?;
            }
            Ok(wc)
        })
        .map_err(Error::WaitContextCreationFailed)?;

        loop {
            let wait_events = wait_ctx.wait().map_err(Error::WaitError)?;

            for wait_event in wait_events.iter().filter(|e| e.is_readable) {
                match wait_event.token {
                    Token::CmdQueue => {
                        self.handle_command_queue(device.as_mut(), &wait_ctx)?;
                    }
                    Token::EventQueue => {
                        let _ = self.event_evt.read();
                    }
                    Token::Event { id } => {
                        self.handle_event(device.as_mut(), id)?;
                    }
                    Token::InterruptResample => {
                        self.interrupt.interrupt_resample();
                    }
                    Token::Kill => return Ok(()),
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use js::value::{Value, ResultValue, VFunction, VNumber, VInteger, VObject, VBoolean, to_value};
use js::function::{NativeFunc, NativeFunction};
use collections::treemap::TreeMap;
use std::gc::Gc;
use std::cell::RefCell;
use std::f64::{NAN, MAX_VALUE, MIN_VALUE, INFINITY, NEG_INFINITY, EPSILON};
/// Parse a float
pub fn parse_float(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	let parsed = from_str(args.get(0).borrow().to_str());
	return Ok(Gc::new(VNumber(match parsed {
		Some(v) => v,
		None => NAN
	})));
}
/// Parse an int
pub fn parse_int(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	let parsed = from_str(args.get(0).borrow().to_str());
	return Ok(Gc::new(match parsed {
		Some(v) => VInteger(v),
		None => VNumber(NAN)
	}));
}
/// Check if a value when converted to a number is finite
pub fn is_finite(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	if args.len() == 0 {
		Ok(Gc::new(VBoolean(false)))
	} else {
		let num = args.get(0).borrow().to_num();
		Ok(Gc::new(VBoolean(num.is_finite())))
	}
}
/// Check if a number is finite
pub fn strict_is_finite(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	if args.len() == 0 {
		Ok(Gc::new(VBoolean(false)))
	} else {
	let num = args.get(0).borrow();
		Ok(Gc::new(VBoolean(match *num {
			VNumber(v) => v.is_finite(),
			VInteger(_) => true, // integers can't be infinite
			_ => false
		})))
	}
}
/// Check if a value when converted to a number is equal to NaN
pub fn is_nan(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	if args.len() == 0 {
		Ok(Gc::new(VBoolean(false)))
	} else {
		let num = args.get(0).borrow().to_num();
		Ok(Gc::new(VBoolean(num.is_nan())))
	}
}
/// Check if a number is equal to NaN
pub fn strict_is_nan(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	if args.len() == 0 {
		Ok(Gc::new(VBoolean(false)))
	} else {
	let num = args.get(0).borrow();
		Ok(Gc::new(VBoolean(match *num {
			VNumber(v) => v.is_nan(),
			VInteger(_) => true, // integers can't be NaN
			_ => false
		})))
	}
}
/// Initialise the parse functions on a global object
pub fn init(obj:Value) {
	obj.borrow().set_field(~"NaN", to_value(NAN));
	obj.borrow().set_field(~"Infinity", to_value(INFINITY));
	obj.borrow().set_field(~"parseFloat", to_value(parse_float));
	obj.borrow().set_field(~"parseInt", to_value(parse_int));
	obj.borrow().set_field(~"isFinite", to_value(is_finite));
	obj.borrow().set_field(~"isNaN", to_value(is_nan));
}
/// Create a new 'Number' object
pub fn _create() -> Value {
	let mut number = TreeMap::new();
	number.insert(~"NaN", to_value(NAN));
	number.insert(~"MAX_VALUE", to_value(MAX_VALUE));
	number.insert(~"MIN_VALUE", to_value(MIN_VALUE));
	number.insert(~"POSITIVE_INFINITY", to_value(INFINITY));
	number.insert(~"NEGATIVE_INFINITY", to_value(NEG_INFINITY));
	number.insert(~"EPSILON", to_value(EPSILON));
	number.insert(~"parseFloat", to_value(parse_float));
	number.insert(~"parseInt", to_value(parse_int));
	number.insert(~"isFinite", to_value(strict_is_finite));
	number.insert(~"isNaN", to_value(strict_is_nan));
	to_value(number)
}<commit_msg>Use to_value and from_value in Number<commit_after>use js::value::{Value, ResultValue, VFunction, VNumber, VInteger, VObject, VBoolean, to_value, from_value};
use js::function::{NativeFunc, NativeFunction};
use collections::treemap::TreeMap;
use std::gc::Gc;
use std::cell::RefCell;
use std::f64::{NAN, MAX_VALUE, MIN_VALUE, INFINITY, NEG_INFINITY, EPSILON};
/// Parse a float
pub fn parse_float(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	let parsed = from_str::<f64>(from_value::<~str>(*args.get(0)).unwrap());
	return Ok(to_value(match parsed {
		Some(v) => v,
		None => NAN
	}));
}
/// Parse an int
pub fn parse_int(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	let parsed = from_str::<i32>(from_value::<~str>(*args.get(0)).unwrap());
	return Ok(match parsed {
		Some(v) => to_value(v),
		None => to_value(NAN)
	});
}
/// Check if a value when converted to a number is finite
pub fn is_finite(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(to_value(if args.len() == 0 {
		false
	} else {
		from_value::<f64>(*args.get(0)).unwrap().is_finite()
	}))
}
/// Check if a number is finite
pub fn strict_is_finite(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(to_value(if args.len() == 0 {
		false
	} else {
		let num = args.get(0).borrow();
		match *num {
			VNumber(v) => v.is_finite(),
			VInteger(_) => true, // integers can't be infinite
			_ => false
		}
	}))
}
/// Check if a value when converted to a number is equal to NaN
pub fn is_nan(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(to_value(if args.len() == 0 {
		false
	} else {
		from_value::<f64>(*args.get(0)).unwrap().is_nan()
	}))
}
/// Check if a number is equal to NaN
pub fn strict_is_nan(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(to_value(if args.len() == 0 {
		false
	} else {
		let num = args.get(0).borrow();
		match *num {
			VNumber(v) => v.is_nan(),
			VInteger(_) => true, // integers can't be NaN
			_ => false
		}
	}))
}
/// Initialise the parse functions on a global object
pub fn init(obj:Value) {
	obj.borrow().set_field(~"NaN", to_value(NAN));
	obj.borrow().set_field(~"Infinity", to_value(INFINITY));
	obj.borrow().set_field(~"parseFloat", to_value(parse_float));
	obj.borrow().set_field(~"parseInt", to_value(parse_int));
	obj.borrow().set_field(~"isFinite", to_value(is_finite));
	obj.borrow().set_field(~"isNaN", to_value(is_nan));
}
/// Create a new 'Number' object
pub fn _create() -> Value {
	let mut number = TreeMap::new();
	number.insert(~"NaN", to_value(NAN));
	number.insert(~"MAX_VALUE", to_value(MAX_VALUE));
	number.insert(~"MIN_VALUE", to_value(MIN_VALUE));
	number.insert(~"POSITIVE_INFINITY", to_value(INFINITY));
	number.insert(~"NEGATIVE_INFINITY", to_value(NEG_INFINITY));
	number.insert(~"EPSILON", to_value(EPSILON));
	number.insert(~"parseFloat", to_value(parse_float));
	number.insert(~"parseInt", to_value(parse_int));
	number.insert(~"isFinite", to_value(strict_is_finite));
	number.insert(~"isNaN", to_value(strict_is_nan));
	to_value(number)
}<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(feature = "semaphore",
            reason = "the interaction between semaphores and the acquisition/release \
                      of resources is currently unclear",
            issue = "27798")]
#![rustc_deprecated(since = "1.7.0",
                    reason = "easily confused with system sempahores and not \
                              used enough to pull its weight")]
#![allow(deprecated)]

use ops::Drop;
use sync::{Mutex, Condvar};

/// A counting, blocking, semaphore.
///
/// Semaphores are a form of atomic counter where access is only granted if the
/// counter is a positive value. Each acquisition will block the calling thread
/// until the counter is positive, and each release will increment the counter
/// and unblock any threads if necessary.
///
/// # Examples
///
/// ```
/// #![feature(semaphore)]
///
/// use std::sync::Semaphore;
///
/// // Create a semaphore that represents 5 resources
/// let sem = Semaphore::new(5);
///
/// // Acquire one of the resources
/// sem.acquire();
///
/// // Acquire one of the resources for a limited period of time
/// {
///     let _guard = sem.access();
///     // ...
/// } // resources is released here
///
/// // Release our initially acquired resource
/// sem.release();
/// ```
pub struct Semaphore {
    lock: Mutex<isize>,
    cvar: Condvar,
}

/// An RAII guard which will release a resource acquired from a semaphore when
/// dropped.
pub struct SemaphoreGuard<'a> {
    sem: &'a Semaphore,
}

impl Semaphore {
    /// Creates a new semaphore with the initial count specified.
    ///
    /// The count specified can be thought of as a number of resources, and a
    /// call to `acquire` or `access` will block until at least one resource is
    /// available. It is valid to initialize a semaphore with a negative count.
    pub fn new(count: isize) -> Semaphore {
        Semaphore {
            lock: Mutex::new(count),
            cvar: Condvar::new(),
        }
    }

    /// Acquires a resource of this semaphore, blocking the current thread until
    /// it can do so.
    ///
    /// This method will block until the internal count of the semaphore is at
    /// least 1.
    pub fn acquire(&self) {
        let mut count = self.lock.lock().unwrap();
        while *count <= 0 {
            count = self.cvar.wait(count).unwrap();
        }
        *count -= 1;
    }

    /// Release a resource from this semaphore.
    ///
    /// This will increment the number of resources in this semaphore by 1 and
    /// will notify any pending waiters in `acquire` or `access` if necessary.
    pub fn release(&self) {
        *self.lock.lock().unwrap() += 1;
        self.cvar.notify_one();
    }

    /// Acquires a resource of this semaphore, returning an RAII guard to
    /// release the semaphore when dropped.
    ///
    /// This function is semantically equivalent to an `acquire` followed by a
    /// `release` when the guard returned is dropped.
    pub fn access(&self) -> SemaphoreGuard {
        self.acquire();
        SemaphoreGuard { sem: self }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Drop for SemaphoreGuard<'a> {
    fn drop(&mut self) {
        self.sem.release();
    }
}

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

    use sync::Arc;
    use super::Semaphore;
    use sync::mpsc::channel;
    use thread;

    #[test]
    fn test_sem_acquire_release() {
        let s = Semaphore::new(1);
        s.acquire();
        s.release();
        s.acquire();
    }

    #[test]
    fn test_sem_basic() {
        let s = Semaphore::new(1);
        let _g = s.access();
    }

    #[test]
    fn test_sem_as_mutex() {
        let s = Arc::new(Semaphore::new(1));
        let s2 = s.clone();
        let _t = thread::spawn(move|| {
            let _g = s2.access();
        });
        let _g = s.access();
    }

    #[test]
    fn test_sem_as_cvar() {
        /* Child waits and parent signals */
        let (tx, rx) = channel();
        let s = Arc::new(Semaphore::new(0));
        let s2 = s.clone();
        let _t = thread::spawn(move|| {
            s2.acquire();
            tx.send(()).unwrap();
        });
        s.release();
        let _ = rx.recv();

        /* Parent waits and child signals */
        let (tx, rx) = channel();
        let s = Arc::new(Semaphore::new(0));
        let s2 = s.clone();
        let _t = thread::spawn(move|| {
            s2.release();
            let _ = rx.recv();
        });
        s.acquire();
        tx.send(()).unwrap();
    }

    #[test]
    fn test_sem_multi_resource() {
        // Parent and child both get in the critical section at the same
        // time, and shake hands.
        let s = Arc::new(Semaphore::new(2));
        let s2 = s.clone();
        let (tx1, rx1) = channel();
        let (tx2, rx2) = channel();
        let _t = thread::spawn(move|| {
            let _g = s2.access();
            let _ = rx2.recv();
            tx1.send(()).unwrap();
        });
        let _g = s.access();
        tx2.send(()).unwrap();
        rx1.recv().unwrap();
    }

    #[test]
    fn test_sem_runtime_friendly_blocking() {
        let s = Arc::new(Semaphore::new(1));
        let s2 = s.clone();
        let (tx, rx) = channel();
        {
            let _g = s.access();
            thread::spawn(move|| {
                tx.send(()).unwrap();
                drop(s2.access());
                tx.send(()).unwrap();
            });
            rx.recv().unwrap(); // wait for child to come alive
        }
        rx.recv().unwrap(); // wait for child to be done
    }
}
<commit_msg>Semaphore not sempahore<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(feature = "semaphore",
            reason = "the interaction between semaphores and the acquisition/release \
                      of resources is currently unclear",
            issue = "27798")]
#![rustc_deprecated(since = "1.7.0",
                    reason = "easily confused with system semaphores and not \
                              used enough to pull its weight")]
#![allow(deprecated)]

use ops::Drop;
use sync::{Mutex, Condvar};

/// A counting, blocking, semaphore.
///
/// Semaphores are a form of atomic counter where access is only granted if the
/// counter is a positive value. Each acquisition will block the calling thread
/// until the counter is positive, and each release will increment the counter
/// and unblock any threads if necessary.
///
/// # Examples
///
/// ```
/// #![feature(semaphore)]
///
/// use std::sync::Semaphore;
///
/// // Create a semaphore that represents 5 resources
/// let sem = Semaphore::new(5);
///
/// // Acquire one of the resources
/// sem.acquire();
///
/// // Acquire one of the resources for a limited period of time
/// {
///     let _guard = sem.access();
///     // ...
/// } // resources is released here
///
/// // Release our initially acquired resource
/// sem.release();
/// ```
pub struct Semaphore {
    lock: Mutex<isize>,
    cvar: Condvar,
}

/// An RAII guard which will release a resource acquired from a semaphore when
/// dropped.
pub struct SemaphoreGuard<'a> {
    sem: &'a Semaphore,
}

impl Semaphore {
    /// Creates a new semaphore with the initial count specified.
    ///
    /// The count specified can be thought of as a number of resources, and a
    /// call to `acquire` or `access` will block until at least one resource is
    /// available. It is valid to initialize a semaphore with a negative count.
    pub fn new(count: isize) -> Semaphore {
        Semaphore {
            lock: Mutex::new(count),
            cvar: Condvar::new(),
        }
    }

    /// Acquires a resource of this semaphore, blocking the current thread until
    /// it can do so.
    ///
    /// This method will block until the internal count of the semaphore is at
    /// least 1.
    pub fn acquire(&self) {
        let mut count = self.lock.lock().unwrap();
        while *count <= 0 {
            count = self.cvar.wait(count).unwrap();
        }
        *count -= 1;
    }

    /// Release a resource from this semaphore.
    ///
    /// This will increment the number of resources in this semaphore by 1 and
    /// will notify any pending waiters in `acquire` or `access` if necessary.
    pub fn release(&self) {
        *self.lock.lock().unwrap() += 1;
        self.cvar.notify_one();
    }

    /// Acquires a resource of this semaphore, returning an RAII guard to
    /// release the semaphore when dropped.
    ///
    /// This function is semantically equivalent to an `acquire` followed by a
    /// `release` when the guard returned is dropped.
    pub fn access(&self) -> SemaphoreGuard {
        self.acquire();
        SemaphoreGuard { sem: self }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Drop for SemaphoreGuard<'a> {
    fn drop(&mut self) {
        self.sem.release();
    }
}

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

    use sync::Arc;
    use super::Semaphore;
    use sync::mpsc::channel;
    use thread;

    #[test]
    fn test_sem_acquire_release() {
        let s = Semaphore::new(1);
        s.acquire();
        s.release();
        s.acquire();
    }

    #[test]
    fn test_sem_basic() {
        let s = Semaphore::new(1);
        let _g = s.access();
    }

    #[test]
    fn test_sem_as_mutex() {
        let s = Arc::new(Semaphore::new(1));
        let s2 = s.clone();
        let _t = thread::spawn(move|| {
            let _g = s2.access();
        });
        let _g = s.access();
    }

    #[test]
    fn test_sem_as_cvar() {
        /* Child waits and parent signals */
        let (tx, rx) = channel();
        let s = Arc::new(Semaphore::new(0));
        let s2 = s.clone();
        let _t = thread::spawn(move|| {
            s2.acquire();
            tx.send(()).unwrap();
        });
        s.release();
        let _ = rx.recv();

        /* Parent waits and child signals */
        let (tx, rx) = channel();
        let s = Arc::new(Semaphore::new(0));
        let s2 = s.clone();
        let _t = thread::spawn(move|| {
            s2.release();
            let _ = rx.recv();
        });
        s.acquire();
        tx.send(()).unwrap();
    }

    #[test]
    fn test_sem_multi_resource() {
        // Parent and child both get in the critical section at the same
        // time, and shake hands.
        let s = Arc::new(Semaphore::new(2));
        let s2 = s.clone();
        let (tx1, rx1) = channel();
        let (tx2, rx2) = channel();
        let _t = thread::spawn(move|| {
            let _g = s2.access();
            let _ = rx2.recv();
            tx1.send(()).unwrap();
        });
        let _g = s.access();
        tx2.send(()).unwrap();
        rx1.recv().unwrap();
    }

    #[test]
    fn test_sem_runtime_friendly_blocking() {
        let s = Arc::new(Semaphore::new(1));
        let s2 = s.clone();
        let (tx, rx) = channel();
        {
            let _g = s.access();
            thread::spawn(move|| {
                tx.send(()).unwrap();
                drop(s2.access());
                tx.send(()).unwrap();
            });
            rx.recv().unwrap(); // wait for child to come alive
        }
        rx.recv().unwrap(); // wait for child to be done
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(box_syntax)]
#![feature(cell_extras)]
#![feature(custom_derive)]
#![feature(drain)]
#![feature(hashmap_hasher)]
#![feature(mpsc_select)]
#![feature(plugin)]
#![feature(raw)]
#![feature(step_by)]
#![feature(str_char)]
#![feature(unsafe_no_drop_flag)]

#![deny(unsafe_code)]

#![plugin(plugins)]

extern crate app_units;
extern crate azure;
#[macro_use]
extern crate bitflags;
extern crate canvas_traits;
extern crate cssparser;
extern crate encoding;
extern crate euclid;
extern crate fnv;
extern crate gfx;
extern crate gfx_traits;
extern crate ipc_channel;
extern crate layout_traits;
extern crate libc;
#[macro_use]
extern crate log;
extern crate msg;
extern crate net_traits;
#[macro_use]
#[no_link]
extern crate plugins as servo_plugins;
#[macro_use]
extern crate profile_traits;
extern crate rustc_serialize;
extern crate script;
extern crate script_traits;
#[macro_use(state_pseudo_classes)] extern crate selectors;
extern crate serde;
extern crate serde_json;
extern crate smallvec;
#[macro_use(atom, ns)] extern crate string_cache;
extern crate style;
extern crate style_traits;
extern crate time;
extern crate unicode_bidi;
extern crate unicode_script;
extern crate url;
#[macro_use]
extern crate util;

#[macro_use]
mod layout_debug;

mod animation;
mod block;
mod construct;
mod context;
mod data;
mod display_list_builder;
mod flex;
mod floats;
mod flow;
mod flow_list;
mod flow_ref;
mod fragment;
mod generated_content;
mod incremental;
mod inline;
pub mod layout_task;
mod list_item;
mod model;
mod multicol;
mod opaque_node;
mod parallel;
mod query;
mod sequential;
mod table;
mod table_caption;
mod table_cell;
mod table_colgroup;
mod table_row;
mod table_rowgroup;
mod table_wrapper;
mod text;
mod traversal;
mod wrapper;

mod css {
    pub mod matching;
}
<commit_msg>Removed use of a #![feature] that is now stable<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(box_syntax)]
#![feature(cell_extras)]
#![feature(custom_derive)]
#![feature(hashmap_hasher)]
#![feature(mpsc_select)]
#![feature(plugin)]
#![feature(raw)]
#![feature(step_by)]
#![feature(str_char)]
#![feature(unsafe_no_drop_flag)]

#![deny(unsafe_code)]

#![plugin(plugins)]

extern crate app_units;
extern crate azure;
#[macro_use]
extern crate bitflags;
extern crate canvas_traits;
extern crate cssparser;
extern crate encoding;
extern crate euclid;
extern crate fnv;
extern crate gfx;
extern crate gfx_traits;
extern crate ipc_channel;
extern crate layout_traits;
extern crate libc;
#[macro_use]
extern crate log;
extern crate msg;
extern crate net_traits;
#[macro_use]
#[no_link]
extern crate plugins as servo_plugins;
#[macro_use]
extern crate profile_traits;
extern crate rustc_serialize;
extern crate script;
extern crate script_traits;
#[macro_use(state_pseudo_classes)] extern crate selectors;
extern crate serde;
extern crate serde_json;
extern crate smallvec;
#[macro_use(atom, ns)] extern crate string_cache;
extern crate style;
extern crate style_traits;
extern crate time;
extern crate unicode_bidi;
extern crate unicode_script;
extern crate url;
#[macro_use]
extern crate util;

#[macro_use]
mod layout_debug;

mod animation;
mod block;
mod construct;
mod context;
mod data;
mod display_list_builder;
mod flex;
mod floats;
mod flow;
mod flow_list;
mod flow_ref;
mod fragment;
mod generated_content;
mod incremental;
mod inline;
pub mod layout_task;
mod list_item;
mod model;
mod multicol;
mod opaque_node;
mod parallel;
mod query;
mod sequential;
mod table;
mod table_caption;
mod table_cell;
mod table_colgroup;
mod table_row;
mod table_rowgroup;
mod table_wrapper;
mod text;
mod traversal;
mod wrapper;

mod css {
    pub mod matching;
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Single-threaded TCP echo server with a bounded buffer pool. Allocates N buffers upon
//! initialization and uses them to serve up to N clients concurrently. When all buffers are in use,
//! the server waits until the next buffer becomes available before accepting the next client
//! connection.

extern crate gj;
extern crate gjio;

use gj::{EventLoop, Promise, PromiseFulfiller, TaskReaper, TaskSet};
use gjio::{AsyncRead, AsyncWrite, Slice};
use std::cell::RefCell;
use std::rc::Rc;

/// Container for buffers that are not currently being used on a connection.
struct BufferPool {
    buffers: Vec<Vec<u8>>,
    waiting: Option<PromiseFulfiller<Buffer, ::std::io::Error>>,
}

struct Buffer {
    buf: Vec<u8>,
    pool: Rc<RefCell<BufferPool>>,
}

impl AsRef<[u8]> for Buffer {
    fn as_ref<'a>(&'a self) -> &'a [u8] {
        &self.buf[..]
    }
}

impl AsMut<[u8]> for Buffer {
    fn as_mut<'a>(&'a mut self) -> &'a mut [u8] {
        &mut self.buf[..]
    }
}

impl Drop for Buffer {
    fn drop(&mut self) {
        let vec = ::std::mem::replace(&mut self.buf, Vec::with_capacity(0));
        let waiting = self.pool.borrow_mut().waiting.take();
        match waiting {
            Some(fulfiller) => fulfiller.fulfill(Buffer { buf: vec, pool: self.pool.clone() }),
            None => self.pool.borrow_mut().buffers.push(vec),
        }
    }
}

impl BufferPool {
    pub fn new(buf_size: usize, num_buffers: usize) -> BufferPool {
        BufferPool { buffers: vec![vec![0; buf_size]; num_buffers], waiting: None }
    }

    /// Retrieves a buffer from the pool, waiting until one is available if there are none
    /// already available. Fails if another task is already waiting for a buffer.
    pub fn pop(pool: &Rc<RefCell<BufferPool>>) -> Promise<Buffer, ::std::io::Error> {
        let &mut BufferPool { ref mut buffers, ref mut waiting } = &mut *pool.borrow_mut();
        match buffers.pop() {
            Some(buf) => Promise::ok(Buffer { buf: buf, pool: pool.clone() }),
            None => {
                if waiting.is_some() {
                    Promise::err(::std::io::Error::new(::std::io::ErrorKind::Other,
                                                       "another client is already waiting"))
                } else {
                    let (promise, fulfiller) = Promise::and_fulfiller();
                    *waiting = Some(fulfiller);
                    promise
                }
            }
        }
    }
}

/// Reads `buf`-sized chunks of bytes from a stream until end-of-file, immediately writing each
/// chunk back to the same stream. Note that this function is recursive. In a naive implementation
/// of promises, such a function could potentially create an unbounded chain of promises. However,
/// GJ implements a tail-call optimization that shortens promise chains when possible, and therefore
/// this loop can run indefinitely, consuming only a small, bounded amount of memory.
fn echo(mut stream: gjio::SocketStream, buf: Buffer) -> Promise<(), ::std::io::Error> {
    stream.try_read(buf, 1).then(move |(buf, n)| {
        if n == 0 { // EOF
            Promise::ok(())
        } else {
            stream.write(Slice::new(buf, n)).then(move |slice| {
                echo(stream, slice.buf)
            })
        }
    })
}

struct Reaper;

impl TaskReaper<(), ::std::io::Error> for Reaper {
    fn task_failed(&mut self, error: ::std::io::Error) {
        println!("Task failed: {}", error);
    }
}

/// Waits for a buffer from the pool, accepts a connection, then spawns an echo() task on that
/// connection with that buffer.
fn accept_loop(mut listener: gjio::SocketListener,
               mut task_set: TaskSet<(), ::std::io::Error>,
               buffer_pool: Rc<RefCell<BufferPool>>)
               -> Promise<(), ::std::io::Error>
{
    BufferPool::pop(&buffer_pool).then(move |buf| {
        listener.accept().then(move |stream| {
            task_set.add(echo(stream, buf));
            accept_loop(listener, task_set, buffer_pool)
        })
    })
}

pub fn main() {
    let args: Vec<String> = ::std::env::args().collect();
    if args.len() != 2 {
        println!("usage: {} HOST:PORT", args[0]);
        return;
    }
    let buffer_pool = Rc::new(RefCell::new(BufferPool::new(1024, 64)));

    EventLoop::top_level(move |wait_scope| -> Result<(), ::std::io::Error> {
        use std::net::ToSocketAddrs;
        let mut event_port = try!(gjio::EventPort::new());
        let network = event_port.get_network();
        let addr = try!(args[1].to_socket_addrs()).next().expect("could not parse address");
        let mut address = network.get_tcp_address(addr);
        let listener = try!(address.listen());
        let reaper = Box::new(Reaper);
        accept_loop(listener, TaskSet::new(reaper), buffer_pool).lift().wait(wait_scope, &mut event_port)
    }).expect("top level");
}
<commit_msg>more cleanup for echo example<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Single-threaded TCP echo server with a bounded buffer pool. Allocates N buffers upon
//! initialization and uses them to serve up to N clients concurrently. When all buffers are in use,
//! the server waits until the next buffer becomes available before accepting the next client
//! connection.

extern crate gj;
extern crate gjio;

use gj::{EventLoop, Promise, PromiseFulfiller, TaskReaper, TaskSet};
use gjio::{AsyncRead, AsyncWrite, Slice};
use std::cell::RefCell;
use std::rc::Rc;

/// Container for buffers that are not currently being used on a connection.
struct BufferPool {
    buffers: Vec<Vec<u8>>,
    waiting: Option<PromiseFulfiller<Buffer, ::std::io::Error>>,
}

impl BufferPool {
    pub fn new(buf_size: usize, num_buffers: usize) -> BufferPool {
        BufferPool { buffers: vec![vec![0; buf_size]; num_buffers], waiting: None }
    }

    /// Retrieves a buffer from the pool, waiting until one is available if there are none
    /// already available. Fails if another task is already waiting for a buffer.
    pub fn pop(pool: &Rc<RefCell<BufferPool>>) -> Promise<Buffer, ::std::io::Error> {
        let &mut BufferPool { ref mut buffers, ref mut waiting } = &mut *pool.borrow_mut();
        match buffers.pop() {
            Some(buf) => Promise::ok(Buffer { buf: buf, pool: pool.clone() }),
            None => {
                if waiting.is_some() {
                    Promise::err(::std::io::Error::new(::std::io::ErrorKind::Other,
                                                       "another client is already waiting"))
                } else {
                    let (promise, fulfiller) = Promise::and_fulfiller();
                    *waiting = Some(fulfiller);
                    promise
                }
            }
        }
    }

    pub fn push(pool: &Rc<RefCell<BufferPool>>, buf: Vec<u8>) {
        let waiting = pool.borrow_mut().waiting.take();
        match waiting {
            Some(fulfiller) => fulfiller.fulfill(Buffer { buf: buf, pool: pool.clone() }),
            None => pool.borrow_mut().buffers.push(buf),
        }
    }
}

// A buffer borrowed from a BufferPool. When a Buffer dropped, its storage is returned to the pool.
struct Buffer {
    buf: Vec<u8>,
    pool: Rc<RefCell<BufferPool>>,
}

impl Drop for Buffer {
    fn drop(&mut self) {
        let buf = ::std::mem::replace(&mut self.buf, Vec::with_capacity(0));
        BufferPool::push(&self.pool, buf);
    }
}

impl AsRef<[u8]> for Buffer {
    fn as_ref<'a>(&'a self) -> &'a [u8] { &self.buf[..] }
}

impl AsMut<[u8]> for Buffer {
    fn as_mut<'a>(&'a mut self) -> &'a mut [u8] { &mut self.buf[..] }
}

/// Reads `buf`-sized chunks of bytes from a stream until end-of-file, immediately writing each
/// chunk back to the same stream. Note that this function is recursive. In a naive implementation
/// of promises, such a function could potentially create an unbounded chain of promises. However,
/// GJ implements a tail-call optimization that shortens promise chains when possible, and therefore
/// this loop can run indefinitely, consuming only a small, bounded amount of memory.
fn echo(mut stream: gjio::SocketStream, buf: Buffer) -> Promise<(), ::std::io::Error> {
    stream.try_read(buf, 1).then(move |(buf, n)| {
        if n == 0 { // EOF
            Promise::ok(())
        } else {
            stream.write(Slice::new(buf, n)).then(move |slice| {
                echo(stream, slice.buf)
            })
        }
    })
}

struct Reaper;

impl TaskReaper<(), ::std::io::Error> for Reaper {
    fn task_failed(&mut self, error: ::std::io::Error) {
        println!("Task failed: {}", error);
    }
}

/// Waits for a buffer from the pool, accepts a connection, then spawns an echo() task on that
/// connection with that buffer.
fn accept_loop(mut listener: gjio::SocketListener,
               mut task_set: TaskSet<(), ::std::io::Error>,
               buffer_pool: Rc<RefCell<BufferPool>>)
               -> Promise<(), ::std::io::Error>
{
    BufferPool::pop(&buffer_pool).then(move |buf| {
        listener.accept().then(move |stream| {
            task_set.add(echo(stream, buf));
            accept_loop(listener, task_set, buffer_pool)
        })
    })
}

pub fn main() {
    let args: Vec<String> = ::std::env::args().collect();
    if args.len() != 2 {
        println!("usage: {} HOST:PORT", args[0]);
        return;
    }
    let buffer_pool = Rc::new(RefCell::new(BufferPool::new(1024, 64)));

    EventLoop::top_level(move |wait_scope| -> Result<(), ::std::io::Error> {
        use std::net::ToSocketAddrs;
        let mut event_port = try!(gjio::EventPort::new());
        let network = event_port.get_network();
        let addr = try!(args[1].to_socket_addrs()).next().expect("could not parse address");
        let mut address = network.get_tcp_address(addr);
        let listener = try!(address.listen());
        let reaper = Box::new(Reaper);
        accept_loop(listener, TaskSet::new(reaper), buffer_pool).lift().wait(wait_scope, &mut event_port)
    }).expect("top level");
}
<|endoftext|>


<commit_before>//! A reimplementation of the `std::sync::mpsc` interface using `crossbeam-channel`.
//!
//! This is a channel implementation mimicking MPSC channels from the standard library, but the
//! internals actually use `crossbeam-channel`. There's an auxilliary channel `disconnected`, which
//! becomes closed once the receiver gets dropped, thus notifying the senders that the MPSC channel
//! is disconnected.

#[macro_use]
extern crate crossbeam_channel as channel;

use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{RecvError, RecvTimeoutError, SendError, TryRecvError, TrySendError};
use std::thread;
use std::time::Duration;

pub struct Sender<T> {
    pub inner: channel::Sender<T>,
    disconnected: channel::Receiver<()>,
    is_disconnected: Arc<AtomicBool>,
}

impl<T> Sender<T> {
    pub fn send(&self, t: T) -> Result<(), SendError<T>> {
        if self.is_disconnected.load(Ordering::SeqCst) {
            Err(SendError(t))
        } else {
            self.inner.send(t);
            Ok(())
        }
    }
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Sender<T> {
        Sender {
            inner: self.inner.clone(),
            disconnected: self.disconnected.clone(),
            is_disconnected: self.is_disconnected.clone(),
        }
    }
}

pub struct SyncSender<T> {
    pub inner: channel::Sender<T>,
    disconnected: channel::Receiver<()>,
    is_disconnected: Arc<AtomicBool>,
}

impl<T> SyncSender<T> {
    pub fn send(&self, t: T) -> Result<(), SendError<T>> {
        if self.is_disconnected.load(Ordering::SeqCst) {
            Err(SendError(t))
        } else {
            select! {
                send(self.inner, t) => Ok(()),
                default => {
                    select! {
                        send(self.inner, t) => Ok(()),
                        recv(self.disconnected) => Err(SendError(t)),
                    }
                }
            }
        }
    }

    pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
        if self.is_disconnected.load(Ordering::SeqCst) {
            Err(TrySendError::Disconnected(t))
        } else {
            select! {
                send(self.inner, t) => Ok(()),
                default => Err(TrySendError::Full(t)),
            }
        }
    }
}

impl<T> Clone for SyncSender<T> {
    fn clone(&self) -> SyncSender<T> {
        SyncSender {
            inner: self.inner.clone(),
            disconnected: self.disconnected.clone(),
            is_disconnected: self.is_disconnected.clone(),
        }
    }
}

pub struct Receiver<T> {
    pub inner: channel::Receiver<T>,
    _disconnected: channel::Sender<()>,
    is_disconnected: Arc<AtomicBool>,
}

impl<T> Receiver<T> {
    pub fn try_recv(&self) -> Result<T, TryRecvError> {
        select! {
            recv(self.inner, msg) => match msg {
                None => Err(TryRecvError::Disconnected),
                Some(msg) => Ok(msg),
            }
            default => Err(TryRecvError::Empty),
        }
    }

    pub fn recv(&self) -> Result<T, RecvError> {
        match self.inner.recv() {
            None => Err(RecvError),
            Some(msg) => Ok(msg),
        }
    }

    pub fn recv_timeout(&self, timeout: Duration) -> Result<T, RecvTimeoutError> {
        select! {
            recv(self.inner, msg) => match msg {
                None => Err(RecvTimeoutError::Disconnected),
                Some(msg) => Ok(msg),
            }
            default => {
                select! {
                    recv(self.inner, msg) => match msg {
                        None => Err(RecvTimeoutError::Disconnected),
                        Some(msg) => Ok(msg),
                    }
                    recv(channel::after(timeout)) => Err(RecvTimeoutError::Timeout),
                }
            }
        }
    }

    pub fn iter(&self) -> Iter<T> {
        Iter { inner: self }
    }

    pub fn try_iter(&self) -> TryIter<T> {
        TryIter { inner: self }
    }
}

impl<T> Drop for Receiver<T> {
    fn drop(&mut self) {
        self.is_disconnected.store(true, Ordering::SeqCst);
    }
}

impl<'a, T> IntoIterator for &'a Receiver<T> {
    type Item = T;
    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Iter<'a, T> {
        self.iter()
    }
}

impl<T> IntoIterator for Receiver<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> IntoIter<T> {
        IntoIter { inner: self }
    }
}

pub struct TryIter<'a, T: 'a> {
    inner: &'a Receiver<T>,
}

impl<'a, T> Iterator for TryIter<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.inner.try_recv().ok()
    }
}

pub struct Iter<'a, T: 'a> {
    inner: &'a Receiver<T>,
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.inner.recv().ok()
    }
}

pub struct IntoIter<T> {
    inner: Receiver<T>,
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.inner.recv().ok()
    }
}

pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
    let (s1, r1) = channel::unbounded();
    let (s2, r2) = channel::bounded(1);
    let is_disconnected = Arc::new(AtomicBool::new(false));

    let s = Sender {
        inner: s1,
        disconnected: r2,
        is_disconnected: is_disconnected.clone(),
    };
    let r = Receiver {
        inner: r1,
        _disconnected: s2,
        is_disconnected,
    };
    (s, r)
}

pub fn sync_channel<T>(bound: usize) -> (SyncSender<T>, Receiver<T>) {
    let (s1, r1) = channel::bounded(bound);
    let (s2, r2) = channel::bounded(1);
    let is_disconnected = Arc::new(AtomicBool::new(false));

    let s = SyncSender {
        inner: s1,
        disconnected: r2,
        is_disconnected: is_disconnected.clone(),
    };
    let r = Receiver {
        inner: r1,
        _disconnected: s2,
        is_disconnected,
    };
    (s, r)
}

macro_rules! mpsc_select {
    ($($name:pat = $rx:ident.$meth:ident() => $code:expr),+) => {{
        select! {
            $(
                $meth($rx.inner, msg) => {
                    let $name = match msg {
                        None => Err(::std::sync::mpsc::RecvError),
                        Some(msg) => Ok(msg),
                    };
                    $code
                }
            )+
        }
    }};
}

fn main() {
    // Example #1:
    let (tx, rx) = channel();
    thread::spawn(move || tx.send(10).unwrap());
    assert_eq!(rx.recv().unwrap(), 10);

    // Example #2:
    let (tx, rx) = sync_channel::<i32>(0);
    thread::spawn(move || tx.send(53).unwrap());
    rx.recv().unwrap();

    // Example #3:
    let (_tx1, rx1) = channel::<i32>();
    let (tx2, rx2) = channel::<i32>();
    tx2.send(0).unwrap();
    mpsc_select! {
        _ = rx1.recv() => panic!(),
        m = rx2.recv() => assert_eq!(m, Ok(0))
    }
}
<commit_msg>Cleanup<commit_after>//! A reimplementation of the `std::sync::mpsc` interface using `crossbeam-channel`.
//!
//! This is a channel implementation mimicking MPSC channels from the standard library, but the
//! internals actually use `crossbeam-channel`. There's an auxilliary channel `disconnected`, which
//! becomes closed once the receiver gets dropped, thus notifying the senders that the MPSC channel
//! is disconnected.

#[macro_use]
extern crate crossbeam_channel as channel;

use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{RecvError, RecvTimeoutError, SendError, TryRecvError, TrySendError};
use std::thread;
use std::time::Duration;

pub struct Sender<T> {
    pub inner: channel::Sender<T>,
    disconnected: channel::Receiver<()>,
    is_disconnected: Arc<AtomicBool>,
}

impl<T> Sender<T> {
    pub fn send(&self, t: T) -> Result<(), SendError<T>> {
        if self.is_disconnected.load(Ordering::SeqCst) {
            Err(SendError(t))
        } else {
            self.inner.send(t);
            Ok(())
        }
    }
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Sender<T> {
        Sender {
            inner: self.inner.clone(),
            disconnected: self.disconnected.clone(),
            is_disconnected: self.is_disconnected.clone(),
        }
    }
}

pub struct SyncSender<T> {
    pub inner: channel::Sender<T>,
    disconnected: channel::Receiver<()>,
    is_disconnected: Arc<AtomicBool>,
}

impl<T> SyncSender<T> {
    pub fn send(&self, t: T) -> Result<(), SendError<T>> {
        if self.is_disconnected.load(Ordering::SeqCst) {
            Err(SendError(t))
        } else {
            select! {
                send(self.inner, t) => Ok(()),
                default => {
                    select! {
                        send(self.inner, t) => Ok(()),
                        recv(self.disconnected) => Err(SendError(t)),
                    }
                }
            }
        }
    }

    pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
        if self.is_disconnected.load(Ordering::SeqCst) {
            Err(TrySendError::Disconnected(t))
        } else {
            select! {
                send(self.inner, t) => Ok(()),
                default => Err(TrySendError::Full(t)),
            }
        }
    }
}

impl<T> Clone for SyncSender<T> {
    fn clone(&self) -> SyncSender<T> {
        SyncSender {
            inner: self.inner.clone(),
            disconnected: self.disconnected.clone(),
            is_disconnected: self.is_disconnected.clone(),
        }
    }
}

pub struct Receiver<T> {
    pub inner: channel::Receiver<T>,
    _disconnected: channel::Sender<()>,
    is_disconnected: Arc<AtomicBool>,
}

impl<T> Receiver<T> {
    pub fn try_recv(&self) -> Result<T, TryRecvError> {
        select! {
            recv(self.inner, msg) => match msg {
                None => Err(TryRecvError::Disconnected),
                Some(msg) => Ok(msg),
            }
            default => Err(TryRecvError::Empty),
        }
    }

    pub fn recv(&self) -> Result<T, RecvError> {
        match self.inner.recv() {
            None => Err(RecvError),
            Some(msg) => Ok(msg),
        }
    }

    pub fn recv_timeout(&self, timeout: Duration) -> Result<T, RecvTimeoutError> {
        select! {
            recv(self.inner, msg) => match msg {
                None => Err(RecvTimeoutError::Disconnected),
                Some(msg) => Ok(msg),
            }
            default => {
                select! {
                    recv(self.inner, msg) => match msg {
                        None => Err(RecvTimeoutError::Disconnected),
                        Some(msg) => Ok(msg),
                    }
                    recv(channel::after(timeout)) => Err(RecvTimeoutError::Timeout),
                }
            }
        }
    }

    pub fn iter(&self) -> Iter<T> {
        Iter { inner: self }
    }

    pub fn try_iter(&self) -> TryIter<T> {
        TryIter { inner: self }
    }
}

impl<T> Drop for Receiver<T> {
    fn drop(&mut self) {
        self.is_disconnected.store(true, Ordering::SeqCst);
    }
}

impl<'a, T> IntoIterator for &'a Receiver<T> {
    type Item = T;
    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Iter<'a, T> {
        self.iter()
    }
}

impl<T> IntoIterator for Receiver<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> IntoIter<T> {
        IntoIter { inner: self }
    }
}

pub struct TryIter<'a, T: 'a> {
    inner: &'a Receiver<T>,
}

impl<'a, T> Iterator for TryIter<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.inner.try_recv().ok()
    }
}

pub struct Iter<'a, T: 'a> {
    inner: &'a Receiver<T>,
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.inner.recv().ok()
    }
}

pub struct IntoIter<T> {
    inner: Receiver<T>,
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.inner.recv().ok()
    }
}

pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
    let (s1, r1) = channel::unbounded();
    let (s2, r2) = channel::bounded(1);
    let is_disconnected = Arc::new(AtomicBool::new(false));

    let s = Sender {
        inner: s1,
        disconnected: r2,
        is_disconnected: is_disconnected.clone(),
    };
    let r = Receiver {
        inner: r1,
        _disconnected: s2,
        is_disconnected,
    };
    (s, r)
}

pub fn sync_channel<T>(bound: usize) -> (SyncSender<T>, Receiver<T>) {
    let (s1, r1) = channel::bounded(bound);
    let (s2, r2) = channel::bounded(1);
    let is_disconnected = Arc::new(AtomicBool::new(false));

    let s = SyncSender {
        inner: s1,
        disconnected: r2,
        is_disconnected: is_disconnected.clone(),
    };
    let r = Receiver {
        inner: r1,
        _disconnected: s2,
        is_disconnected,
    };
    (s, r)
}

macro_rules! mpsc_select {
    (
        $($name:pat = $rx:ident.$meth:ident() => $code:expr),+
    ) => ({
        select! {
            $(
                $meth(($rx).inner, msg) => {
                    let $name = match msg {
                        None => Err(::std::sync::mpsc::RecvError),
                        Some(msg) => Ok(msg),
                    };
                    $code
                }
            )+
        }
    })
}

fn main() {
    // Example #1:
    let (tx, rx) = channel();
    thread::spawn(move || tx.send(10).unwrap());
    assert_eq!(rx.recv().unwrap(), 10);

    // Example #2:
    let (tx, rx) = sync_channel::<i32>(0);
    thread::spawn(move || tx.send(53).unwrap());
    rx.recv().unwrap();

    // Example #3:
    let (_tx1, rx1) = channel::<i32>();
    let (tx2, rx2) = channel::<i32>();
    tx2.send(0).unwrap();
    mpsc_select! {
        _ = rx1.recv() => panic!(),
        m = rx2.recv() => assert_eq!(m, Ok(0))
    }
}
<|endoftext|>


<commit_before>use std::sync::Arc;

use smithay::delegate_seat;
use smithay::reexports::wayland_server::Display;
use smithay::wayland::seat::{self as seat, Seat, SeatHandler};

use seat::SeatState;

use wayland_server::backend::{ClientData, ClientId, DisconnectReason};
use wayland_server::socket::ListeningSocket;

struct App {
    seat_state: SeatState<Self>,
    seat: Seat<Self>,
}

impl SeatHandler for App {
    fn seat_state(&mut self) -> &mut SeatState<Self> {
        &mut self.seat_state
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut display: Display<App> = Display::new()?;

    let seat_state = SeatState::new();
    let seat = Seat::new(&mut display, "Example", None);

    let mut state = App { seat_state, seat };

    let keyboard = state
        .seat
        .add_keyboard(&mut display.handle(), Default::default(), 25, 600, |_, _| {})?;

    let listener = ListeningSocket::bind("wayland-5").unwrap();

    let mut clients = Vec::new();

    loop {
        if let Some(stream) = listener.accept().unwrap() {
            println!("Got a client: {:?}", stream);

            let client = display.insert_client(stream, Arc::new(ClientState)).unwrap();
            clients.push(client);
        }

        keyboard.input(
            &mut display.handle(),
            1,
            smithay::backend::input::KeyState::Pressed,
            0.into(),
            0,
            |_, _| {
                if false {
                    seat::FilterResult::Intercept(0)
                } else {
                    seat::FilterResult::Forward
                }
            },
        );

        keyboard.set_focus(&mut display.handle(), None, 0.into());

        display.dispatch_clients(&mut state)?;
        display.flush_clients()?;
    }
}

struct ClientState;
impl ClientData<App> for ClientState {
    fn initialized(&self, _client_id: ClientId) {
        println!("initialized");
    }

    fn disconnected(&self, _client_id: ClientId, _reason: DisconnectReason) {
        println!("disconnected");
    }
}

delegate_seat!(App);
<commit_msg>seat-example: fix error minus macros<commit_after>use std::sync::Arc;

use smithay::delegate_seat;
use smithay::reexports::wayland_server::Display;
use smithay::wayland::seat::{self as seat, Seat, SeatHandler};

use seat::SeatState;

use wayland_server::backend::{ClientData, ClientId, DisconnectReason};
use wayland_server::socket::ListeningSocket;

struct App {
    seat_state: SeatState<Self>,
    seat: Seat<Self>,
}

impl SeatHandler for App {
    fn seat_state(&mut self) -> &mut SeatState<Self> {
        &mut self.seat_state
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut display: Display<App> = Display::new()?;

    let seat_state = SeatState::new();
    let seat = Seat::new(&mut display, "Example", None);

    let mut state = App { seat_state, seat };

    let keyboard = state
        .seat
        .add_keyboard(&mut display.handle(), Default::default(), 25, 600, |_, _| {})?;

    let listener = ListeningSocket::bind("wayland-5").unwrap();

    let mut clients = Vec::new();

    loop {
        if let Some(stream) = listener.accept().unwrap() {
            println!("Got a client: {:?}", stream);

            let client = display.insert_client(stream, Arc::new(ClientState)).unwrap();
            clients.push(client);
        }

        keyboard.input(
            &mut display.handle(),
            1,
            smithay::backend::input::KeyState::Pressed,
            0.into(),
            0,
            |_, _| {
                if false {
                    seat::FilterResult::Intercept(0)
                } else {
                    seat::FilterResult::Forward
                }
            },
        );

        keyboard.set_focus(&mut display.handle(), None, 0.into());

        display.dispatch_clients(&mut state)?;
        display.flush_clients()?;
    }
}

struct ClientState;
impl ClientData for ClientState {
    fn initialized(&self, _client_id: ClientId) {
        println!("initialized");
    }

    fn disconnected(&self, _client_id: ClientId, _reason: DisconnectReason) {
        println!("disconnected");
    }
}

delegate_seat!(App);
<|endoftext|>


<commit_before>//
// zhtta.rs
//
// Running on Rust 0.8
//
// Starting code for PS3
//
// Note: it would be very unwise to run this server on a machine that is
// on the Internet and contains any sensitive files!
//
// University of Virginia - cs4414 Fall 2013
// Weilin Xu and David Evans
// Version 0.3

extern mod extra;

use std::rt::io::*;
use std::rt::io::net::ip::SocketAddr;
use std::io::println;
use std::cell::Cell;
use std::{os, str, io};
use extra::arc;
use std::comm::*;

static PORT:    int = 4414;
static IP: &'static str = "127.0.0.1";
static mut visitor_count: uint = 0;

struct sched_msg {
    stream: Option<std::rt::io::net::tcp::TcpStream>,
    filepath: ~std::path::PosixPath
}

fn main() {
    let req_vec: ~[sched_msg] = ~[];
    let shared_req_vec = arc::RWArc::new(req_vec);
    let add_vec = shared_req_vec.clone();
    let take_vec = shared_req_vec.clone();

    let (port, chan) = stream();
    let chan = SharedChan::new(chan);

    // dequeue file requests, and send responses.
    // FIFO
    do spawn {
        let (sm_port, sm_chan) = stream();

        // a task for sending responses.
        do spawn {
            loop {
                let mut tf: sched_msg = sm_port.recv(); // wait for the dequeued request to handle
                match io::read_whole_file(tf.filepath) { // killed if file size is larger than memory size.
                    Ok(file_data) => {
                        println(fmt!("begin serving file [%?]", tf.filepath));
                        // A web server should always reply a HTTP header for any legal HTTP request.
                        tf.stream.write("HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream; charset=UTF-8\r\n\r\n".as_bytes());
                        tf.stream.write(file_data);
                        println(fmt!("finish file [%?]", tf.filepath));
                    }
                    Err(err) => {
                        println(err);
                    }
                }
            }
        }

        loop {
            port.recv(); // wait for arrving notification
            do take_vec.write |vec| {
                if ((*vec).len() > 0) {
                    // LIFO didn't make sense in service scheduling, so we modify it as FIFO by using shift_opt() rather than pop().
                    let tf_opt: Option<sched_msg> = (*vec).shift_opt();
                    let tf = tf_opt.unwrap();
                    println(fmt!("shift from queue, size: %ud", (*vec).len()));
                    sm_chan.send(tf); // send the request to send-response-task to serve.
                }
            }
        }
    }

    let ip = match FromStr::from_str(IP) { Some(ip) => ip,
                                           None => { println(fmt!("Error: Invalid IP address <%s>", IP));
                                                     return;},
                                         };

    let socket = net::tcp::TcpListener::bind(SocketAddr {ip: ip, port: PORT as u16});

    println(fmt!("Listening on %s:%d ...", ip.to_str(), PORT));
    let mut acceptor = socket.listen().unwrap();

    for stream in acceptor.incoming() {
        let stream = Cell::new(stream);

        // Start a new task to handle the each connection
        let child_chan = chan.clone();
        let child_add_vec = add_vec.clone();
        do spawn {
            unsafe {
                visitor_count += 1;
            }

            let mut stream = stream.take();
            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);

            let req_group : ~[&str]= request_str.splitn_iter(' ', 3).collect();
            if req_group.len() > 2 {
                let path = req_group[1];
                println(fmt!("Request for path: \n%?", path));

                let file_path = ~os::getcwd().push(path.replace("/../", ""));
                if !os::path_exists(file_path) || os::path_is_dir(file_path) {
                    println(fmt!("Request received:\n%s", request_str));
                    let response: ~str = fmt!(
                        "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                         <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: %u

                         \r\n", unsafe{visitor_count});

                    stream.write(response.as_bytes());
                }
                else {
                    // Requests scheduling
                    let msg: sched_msg = sched_msg{stream: stream, filepath: file_path.clone()};
                    let (sm_port, sm_chan) = std::comm::stream();
                    sm_chan.send(msg);

                    do child_add_vec.write |vec| {
                        let msg = sm_port.recv();
                        (*vec).push(msg); // enqueue new request.
                        println("add to queue");
                    }
                    child_chan.send(""); //notify the new arriving request.
                    println(fmt!("get file request: %?", file_path));
                }
            }
            println!("connection terminates")
        }
    }
}
<commit_msg>Solved for problems 1 and 2<commit_after>//
// zhtta.rs
//
// Running on Rust 0.8
//
// Starting code for PS3
//
// Note: it would be very unwise to run this server on a machine that is
// on the Internet and contains any sensitive files!
//
// University of Virginia - cs4414 Fall 2013
// Weilin Xu and David Evans
// Version 0.1

extern mod extra;

use std::rt::io::*;
use std::rt::io::net::ip::{SocketAddr, Ipv4Addr};
use std::io::println;
use std::cell::Cell;
use std::{os, str, io};
use extra::arc;
use std::comm::*;
use extra::priority_queue;

static PORT:    int = 4414;
static IPV4_LOOPBACK: &'static str = "127.0.0.1";
static mut visitor_count: uint = 0;

struct sched_msg {
    stream: Option<std::rt::io::net::tcp::TcpStream>,
    filepath: ~std::path::PosixPath,
    topPriority: int,
}

impl sched_msg {

    //fn dispIP(&self) {

        //let mut xx =  self.stream.clone();
        /*
        match self.stream {
            Some(st) => {
                match st.peer_name() {
                    Some(pr) => {println("works");},
                    None => ()
                }
            },
            None => ()
        }
        */
    //}
}

impl Ord for sched_msg {
    fn lt(&self, other: &sched_msg) -> bool {

        let mut retVal:bool = false;

        if (self.topPriority <= other.topPriority) {
            retVal = true;
        }
        retVal
    }
}

fn main() {

    let safe_count: ~[uint] = ~[0];
    let shared_visit = arc::RWArc::new(safe_count);

    //let req_vec: ~[sched_msg] = ~[];
    let req_vec: ~priority_queue::PriorityQueue<sched_msg> = ~priority_queue::PriorityQueue::new();

    let shared_req_vec = arc::RWArc::new(req_vec);
    let add_vec = shared_req_vec.clone();
    let take_vec = shared_req_vec.clone();

    let (port, chan) = stream();
    let chan = SharedChan::new(chan);

    // add file requests into queue.
    do spawn {
        while(true) {
            do add_vec.write |vec| {
                let tf:sched_msg = port.recv();
                (*vec).push(tf);
                println("add to queue");
            }
        }
    }

    // take file requests from queue, and send a response.
    do spawn {
        while(true) {
            do take_vec.write |vec| {
                let mut tf = (*vec).pop();

                match io::read_whole_file(tf.filepath) {
                    Ok(file_data) => {

                        if(file_data.len() > 1) {
                            let tfLeft = file_data.slice_to(1).to_owned();
                            let tfRight = file_data.slice_from(1).to_owned();

                            println!("Writing left: {:?}", tfLeft);
                            tf.stream.write(tfLeft);
                            //tf.stream.flush();
                            println!("Writing right: {:?}", tfRight);
                            tf.stream.write(tfRight);
                        }
                        else {
                            tf.stream.write(file_data);
                        }
                    }
                    Err(err) => {
                        println(err);
                    }
                }
            }
        }
    }

    let socket = net::tcp::TcpListener::bind(SocketAddr {ip: Ipv4Addr(127,0,0,1), port: PORT as u16});

    println(fmt!("Listening on tcp port %d ...", PORT));

    let mut acceptor = socket.listen().unwrap();

    // we can limit the incoming connection count.
    //for stream in acceptor.incoming().take(10 as uint) {

    //Note: acceptor.incoming() is blocking
    loop {

        let stream = acceptor.accept();
        let stream = Cell::new(stream);

        // Start a new task to handle the connection
        let child_chan = chan.clone();

        let child_arc = shared_visit.clone();

        do spawn {

            //This value will be assigned the actual count for a particular user's specific request
            let mut actual_count:uint = 0;

            //We will use the cloned RWARC
            do child_arc.write |count_vec| {

                let prev_count = (*count_vec).pop();
                let new_count: uint = prev_count + 1;

                actual_count = new_count;

                (*count_vec).push(new_count);
            }

            let stream = stream.take();

            match stream {

                Some(s) => {

                    let mut stream = s;

                    let mut buf = [0, ..500];
                    stream.read(buf);
                    let request_str = str::from_utf8(buf);

                    let req_group : ~[&str]= request_str.splitn_iter(' ', 3).collect();
                    if req_group.len() > 2 {
                        let path = req_group[1];
                        println(fmt!("Request for path: \n%?", path));

                        let file_path = ~os::getcwd().push(path.replace("/../", ""));

                        //if path in cache -> serve file, else, proceed below

                        if !os::path_exists(file_path) || os::path_is_dir(file_path) {

                            println(fmt!("Request received:\n%s", request_str));
                            let response: ~str = fmt!(
                                "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                                 <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: %u

                                 \r\n", actual_count);

                            stream.write(response.as_bytes());
                        }
                        else {

                            let mut streamPriority: int = 0;

                            let ipStr: ~str = match (stream).peer_name() {
                                Some(pr) => pr.ip.to_str(),
                                None => ~"0.0.0.0"
                            };

                            let ipSplit: ~[~str] = ipStr.split_iter('.').filter(|&x| x != "")
                                 .map(|x| x.to_owned()).collect();

                            if ( (ipSplit[0] == ~"127" && ipSplit[1] == ~"0") || (ipSplit[0] == ~"128" && ipSplit[1] == ~"143")
                                || (ipSplit[0] == ~"137" && ipSplit[1] == ~"54") ) {

                                streamPriority = 1;
                            }

                            //println!("IP ADDRESS {:?} PRIORITY {:?}", ipSplit, streamPriority);

                            match io::file_reader(file_path) {
                                Ok(the_reader) => {

                                }
                            }

                            let msg: sched_msg = sched_msg{stream: Some(stream), filepath: file_path.clone(), topPriority: streamPriority};
                            child_chan.send(msg);

                            println(fmt!("get file request: %?", file_path));
                        }
                    }
                    println!("connection terminates")

                },
                None => ()
            }

        }

    }
}
<|endoftext|>


<commit_before>extern crate epub_builder;

use epub_builder::EpubBuilder;
use epub_builder::Result;
use epub_builder::ZipLibrary;
use epub_builder::EpubContent;
use epub_builder::ReferenceType;
use epub_builder::TocElement;

use std::io;
use std::io::Write;

// Try to print Zip file to stdout
fn run() -> Result<()> {
    // Some dummy content to fill our books
    let dummy_content = "Dummy content. This should be valid XHTML if you want a valid EPUB!";
    let dummy_image = "Not really a PNG image";
    let dummy_css = "body { background-color: pink }";

    // Create a new EpubBuilder using the zip library
    EpubBuilder::new(ZipLibrary::new())?
    // Set some metadata
        .metadata("author", "Joan Doe")?
        .metadata("title", "Dummy Book")?
    // Set the stylesheet (create a "stylesheet.css" file in EPUB that is used by some generated files)
        .stylesheet(dummy_css.as_bytes())?
    // Add a image cover file
        .add_cover_image("cover.png", dummy_image.as_bytes(), "image/png")?
    // Add a resource that is not part of the linear document structure
        .add_resource("some_image.png", dummy_image.as_bytes(), "image/png")?
    // Add a cover page
        .add_content(EpubContent::new("cover.xhtml", dummy_content.as_bytes())
                     .title("Cover")
                     .reftype(ReferenceType::Cover))?
    // Add a title page
        .add_content(EpubContent::new("title.xhtml", dummy_content.as_bytes())
                     .title("Title")
                     .reftype(ReferenceType::TitlePage))?
    // Add a chapter
        .add_content(EpubContent::new("chapter_1.xhtml", dummy_content.as_bytes())
                     .title("Chapter 1"))?
    // Add a second chapter; this one has more toc information about its internal structure
        .add_content(EpubContent::new("chapter_2.xhtml", dummy_content.as_bytes())
                     .title("Chapter 2")
                     .child(TocElement::new("chapter_2.xhtml#1", "Chapter 2, section 1")))?
    // Add a section. Since its level is set to 2, it will be attached to the previous chapter.
        .add_content(EpubContent::new("section.xhtml", dummy_content.as_bytes())
                     .title("Chapter 2, section 2")
                     .level(2))?
    // Add a chapter without a title, which will thus not appear in the TOC.
        .add_content(EpubContent::new("notes.xhtml", dummy_content.as_bytes()))?
    // Generate a toc inside of the document, that will be part of the linear structure.
        .inline_toc()
    // Finally, write the EPUB file to stdout
        .generate(&mut io::stdout())?;
    Ok(())
}

fn main() {
    match run() {
        Ok(_) => {
            writeln!(&mut io::stderr(),
                     "Successfully wrote epub document to stdout!")
                .unwrap()
        }
        Err(err) => writeln!(&mut io::stderr(), "Error: {}", err).unwrap(),
    };
}
<commit_msg>Use ReferenceType::Text in the example<commit_after>extern crate epub_builder;

use epub_builder::EpubBuilder;
use epub_builder::Result;
use epub_builder::ZipLibrary;
use epub_builder::EpubContent;
use epub_builder::ReferenceType;
use epub_builder::TocElement;

use std::io;
use std::io::Write;

// Try to print Zip file to stdout
fn run() -> Result<()> {
    // Some dummy content to fill our books
    let dummy_content = "Dummy content. This should be valid XHTML if you want a valid EPUB!";
    let dummy_image = "Not really a PNG image";
    let dummy_css = "body { background-color: pink }";

    // Create a new EpubBuilder using the zip library
    EpubBuilder::new(ZipLibrary::new())?
    // Set some metadata
        .metadata("author", "Joan Doe")?
        .metadata("title", "Dummy Book")?
    // Set the stylesheet (create a "stylesheet.css" file in EPUB that is used by some generated files)
        .stylesheet(dummy_css.as_bytes())?
    // Add a image cover file
        .add_cover_image("cover.png", dummy_image.as_bytes(), "image/png")?
    // Add a resource that is not part of the linear document structure
        .add_resource("some_image.png", dummy_image.as_bytes(), "image/png")?
    // Add a cover page
        .add_content(EpubContent::new("cover.xhtml", dummy_content.as_bytes())
                     .title("Cover")
                     .reftype(ReferenceType::Cover))?
    // Add a title page
        .add_content(EpubContent::new("title.xhtml", dummy_content.as_bytes())
                     .title("Title")
                     .reftype(ReferenceType::TitlePage))?
    // Add a chapter, mark it as beginning of the "real content"
        .add_content(EpubContent::new("chapter_1.xhtml", dummy_content.as_bytes())
                     .title("Chapter 1")
                     .reftype(ReferenceType::Text))?
    // Add a second chapter; this one has more toc information about its internal structure
        .add_content(EpubContent::new("chapter_2.xhtml", dummy_content.as_bytes())
                     .title("Chapter 2")
                     .child(TocElement::new("chapter_2.xhtml#1", "Chapter 2, section 1")))?
    // Add a section. Since its level is set to 2, it will be attached to the previous chapter.
        .add_content(EpubContent::new("section.xhtml", dummy_content.as_bytes())
                     .title("Chapter 2, section 2")
                     .level(2))?
    // Add a chapter without a title, which will thus not appear in the TOC.
        .add_content(EpubContent::new("notes.xhtml", dummy_content.as_bytes()))?
    // Generate a toc inside of the document, that will be part of the linear structure.
        .inline_toc()
    // Finally, write the EPUB file to stdout
        .generate(&mut io::stdout())?;
    Ok(())
}

fn main() {
    match run() {
        Ok(_) => {
            writeln!(&mut io::stderr(),
                     "Successfully wrote epub document to stdout!")
                .unwrap()
        }
        Err(err) => writeln!(&mut io::stderr(), "Error: {}", err).unwrap(),
    };
}
<|endoftext|>


<commit_before>extern crate irc;

use irc::*;
use std::io::*;

fn main() {
    let mut user = IrcUser::new("RockyTV", "yarircl", "Rust IRC Bot");
    user.set_password("1432");

    let mut client = IrcClient::new("chat.freenode.net:6667", user);
    let mut stream = client.connect();
    let mut buffer = String::new();

    let mut previous = 0;
    let mut current = 0;
    while client.conn_handler(&mut stream) {
        let ref curr_msg = client.messages[current];
        println!("{:?}", curr_msg.raw);

        if curr_msg.command == NumericReply::PRIVMSG {
            println!("{:?}", curr_msg);
            if curr_msg.params[1] == "!ping" {
                stream.send_message(&curr_msg.params[0], "Hello there!");
            }
        }

        previous = current;
        current += 1;
    }
}
<commit_msg>Update example<commit_after>extern crate irc;

use irc::*;
use std::io::*;

fn main() {
    let mut user = IrcUser::new("RockyTV", "yarircl");
    user.set_password("");
    user.set_realname("Rust IRC Bot");

    let mut client = IrcClient::new("chat.freenode.net:6667", user);
    let mut stream = client.connect();
    let mut buffer = String::new();
    let mut motd = false;

    let mut previous = 0;
    let mut current = 0;
    while client.conn_handler(&mut stream) {
        let ref curr_msg = client.messages[current];
        println!("{:?}", curr_msg.raw);

        if curr_msg.command == NumericReply::PRIVMSG {
            println!("{:?}", curr_msg);
            if curr_msg.params[1] == "!ping" {
                stream.send_message(&curr_msg.params[0], "Hello there!");
            }
            else if curr_msg.params[1] == "!motd" {
                println!("MOTD is:\r\n{}", client.server_motd);
            }
            else if curr_msg.params[1] == "!whois" {
                stream.send_raw_message("WHOIS Phrohdoh");
            }
            else if curr_msg.params[1] == "!join" {
                stream.join("#orcaware");
            }
        }

        previous = current;
        current += 1;
    }
}
<|endoftext|>