<commit_before>use std::io;
use std::io::Read;
use command::Command;

type Cell = u8;

pub struct VM {
    pub cells: [Cell; 30_000],
    pub data_pointer: usize,
}

impl VM {
    pub fn new() -> VM {
        VM { cells: [0; 30_000], data_pointer: 0 }
    }

    pub fn output(&self) {
        print!("{}", self.cells[self.data_pointer] as char);
    }

    pub fn input(&mut self) {
        match io::stdin().bytes().next() {
            Some(res) => match res {
                Ok(value) => self.cells[self.data_pointer] = value,
                Err(error) => panic!(error),
            },
            None => {}
        }
        println!("");
    }

    pub fn increment(&mut self) {
        self.cells[self.data_pointer] = self.cells[self.data_pointer].checked_add(1).unwrap_or(0);
    }

    pub fn decrement(&mut self) {
        self.cells[self.data_pointer] -= 1;
    }

    pub fn right_shift(&mut self) {
        self.data_pointer += 1;
    }

    pub fn left_shift(&mut self) {
        self.data_pointer += 1;
    }

    pub fn apply(&mut self, command: Command) {
        match command {
            Command::Output => self.output(),
            Command::Input => self.input(),
            Command::Increment => self.increment(),
            Command::Decrement => self.decrement(),
            Command::RightShift => self.right_shift(),
            Command::LeftShift => self.left_shift(),
            _ => {},
        }
    }
}
<commit_msg>Change decrement to underflow<commit_after>use std::io;
use std::io::Read;
use command::Command;

type Cell = u8;

pub struct VM {
    pub cells: [Cell; 30_000],
    pub data_pointer: usize,
}

impl VM {
    pub fn new() -> VM {
        VM { cells: [0; 30_000], data_pointer: 0 }
    }

    pub fn output(&self) {
        print!("{}", self.cells[self.data_pointer] as char);
    }

    pub fn input(&mut self) {
        match io::stdin().bytes().next() {
            Some(res) => match res {
                Ok(value) => self.cells[self.data_pointer] = value,
                Err(error) => panic!(error),
            },
            None => {}
        }
        println!("");
    }

    pub fn increment(&mut self) {
        self.cells[self.data_pointer] = self.cells[self.data_pointer].checked_add(1).unwrap_or(0);
    }

    pub fn decrement(&mut self) {
        self.cells[self.data_pointer] = self.cells[self.data_pointer]
            .checked_sub(1)
            .unwrap_or(Cell::max_value());
    }

    pub fn right_shift(&mut self) {
        self.data_pointer += 1;
    }

    pub fn left_shift(&mut self) {
        self.data_pointer += 1;
    }

    pub fn apply(&mut self, command: Command) {
        match command {
            Command::Output => self.output(),
            Command::Input => self.input(),
            Command::Increment => self.increment(),
            Command::Decrement => self.decrement(),
            Command::RightShift => self.right_shift(),
            Command::LeftShift => self.left_shift(),
            _ => {},
        }
    }
}
<|endoftext|>


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

//! Encapsulate running the `hab-sup` executable for tests.

use std::env;
use std::process::{Child, Command, Stdio};
use std::path::{Path, PathBuf};
use std::string::ToString;

use super::test_butterfly;

extern crate rand;
use self::rand::distributions::{IndependentSample, Range};

pub struct TestSup {
    pub hab_root: PathBuf,
    pub origin_name: String,
    pub package_name: String,
    pub service_group: String,
    pub http_port: u16,
    pub butterfly_port: u16,
    pub butterfly_client: test_butterfly::Client,
    pub cmd: Command,
    pub process: Option<Child>,
}

/// Return a random unprivileged, unregistered TCP port number.
fn random_port() -> u16 {
    // IANA port registrations go to 49151
    let between = Range::new(49152, ::std::u16::MAX);
    let mut rng = rand::thread_rng();
    between.ind_sample(&mut rng)
}

/// Find an executable relative to the current integration testing
/// executable.
///
/// Thus if the current executable is
///
///    /home/me/habitat/target/debug/deps/compilation-ccaf2f45c24e3840
///
/// and we look for `hab-sup`, we'll find it at
///
///    /home/me/habitat/target/debug/hab-sup
///
fn find_exe<B>(binary_name: B) -> PathBuf
    where B: AsRef<Path>
{
    let exe_root = env::current_exe()
        .unwrap()
        .parent()  // deps
        .unwrap()
        .parent()  // debug
        .unwrap()
        .to_path_buf();
    let bin = exe_root.join(binary_name.as_ref());
    assert!(
        bin.exists(),
        format!("Expected to find a {:?} executable at {:?}", binary_name.as_ref(), bin)
    );
    bin
}

impl TestSup {
    /// Create a new `TestSup` that will listen on randomly-selected
    /// ports for both gossip and HTTP requests so tests run in
    /// parallel don't step on each other.
    ///
    /// See also `new`.
    pub fn new_with_random_ports<R, O, P, S>(
        fs_root: R,
        origin: O,
        pkg_name: P,
        service_group: S,
    ) -> TestSup
    where
        R: AsRef<Path>,
        O: ToString,
        P: ToString,
        S: ToString,
    {
        let http_port = random_port();
        let butterfly_port = http_port + 1;
        TestSup::new(
            fs_root,
            origin,
            pkg_name,
            service_group,
            http_port,
            butterfly_port,
        )
    }

    /// Bundle up a Habitat supervisor process along with an
    /// associated Butterfly client for injecting new configuration
    /// values. The supervisor executable is the one that has been
    /// compiled for the current `cargo test` invocation.
    ///
    /// The supervisor is configured to run a single package for a
    /// test. This package is assumed to have already been installed
    /// relative to `fs_root` (i.e., the `FS_ROOT` environment
    /// variable, which in our tests will be a randomly-named
    /// temporary directory that this supervisor will view as `/`.).
    ///
    /// A Butterfly client is also created for interacting with this
    /// supervisor and package. It is properly configured according to
    /// the value provided for `butterfly_port`. To use it, see the
    /// `apply_config` function.
    ///
    /// (No HTTP interaction with the supervisor is currently called
    /// for, so we don't have a HTTP client.)
    pub fn new<R, O, P, S>(
        fs_root: R,
        origin: O,
        pkg_name: P,
        service_group: S,
        http_port: u16,
        butterfly_port: u16,
    ) -> TestSup
    where
        R: AsRef<Path>,
        O: ToString,
        P: ToString,
        S: ToString,
    {
        let sup_exe = find_exe("hab-sup");
        let launcher_exe = find_exe("hab-launch");

        let mut cmd = Command::new(&launcher_exe);
        let listen_host = "0.0.0.0";

        let origin = origin.to_string();
        let pkg_name = pkg_name.to_string();
        let service_group = service_group.to_string();

        cmd.env("FS_ROOT", fs_root.as_ref().to_string_lossy().as_ref())
            .env("HAB_SUP_BINARY", &sup_exe)
            .env("HAB_DEPOT_URL", "http://hab.sup.test/v1/depot")
            .arg("start")
            .arg("--listen-gossip")
            .arg(format!("{}:{}", listen_host, butterfly_port))
            .arg("--listen-http")
            .arg(format!("{}:{}", listen_host, http_port))
            .arg(format!("{}/{}", origin, pkg_name))
            .stdin(Stdio::null())
            .stdout(Stdio::piped())
            .stderr(Stdio::piped());

        let bc = test_butterfly::Client::new(&pkg_name, &service_group, butterfly_port);

        TestSup {
            hab_root: fs_root.as_ref().to_path_buf(),
            origin_name: origin,
            package_name: pkg_name,
            service_group: service_group.to_string(),
            http_port: http_port,
            butterfly_port: butterfly_port,
            butterfly_client: bc,
            cmd: cmd,
            process: None,
        }
    }

    /// Spawn a process actually running the supervisor.
    pub fn start(&mut self) {
        let child = self.cmd.spawn().expect("Couldn't start the supervisor!");
        self.process = Some(child);
    }

    /// The equivalent of performing `hab apply` with the given
    /// configuration.
    pub fn apply_config<T>(&mut self, toml_config: T)
    where
        T: ToString,
    {
        self.butterfly_client.apply(toml_config.to_string())
    }
}

// We kill the supervisor so you don't have to!
impl Drop for TestSup {
    fn drop(&mut self) {
        self.process
            .take()
            .expect("No process to kill!")
            .kill()
            .expect("Tried to kill supervisor!");
    }
}
<commit_msg>Add some smarts around picking random ports for test supervisors<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Encapsulate running the `hab-sup` executable for tests.

use std::collections::HashSet;
use std::env;
use std::net::TcpListener;
use std::path::{Path, PathBuf};
use std::process::{Child, Command, Stdio};
use std::string::ToString;
use std::sync::Mutex;
use std::thread;
use std::time::Duration;

use super::test_butterfly;

extern crate rand;
use self::rand::distributions::{IndependentSample, Range};

lazy_static! {
    /// Keep track of all TCP ports currently being used by TestSup
    /// instances. Allows us to run tests in parallel without fear of
    /// port conflicts between them.
    static ref CLAIMED_PORTS: Mutex<HashSet<u16>> = {
        Mutex::new(HashSet::new())
    };
}

pub struct TestSup {
    pub hab_root: PathBuf,
    pub origin_name: String,
    pub package_name: String,
    pub service_group: String,
    pub http_port: u16,
    pub butterfly_port: u16,
    pub butterfly_client: test_butterfly::Client,
    pub cmd: Command,
    pub process: Option<Child>,
}

/// Return a free TCP port number. We test to see that the system has
/// not already bound the port, while also tracking which ports are
/// being used by other test supervisors that may be running alongside
/// this one.
///
/// Once you receive a port number from this function, you can be
/// reasonably sure that you're the only one that will be using
/// it. There could be a race condition if the machine the tests are
/// running on just happens to claim the same port number for
/// something between the time we check and the time the TestSup
/// claims it. If that happens to you, you should probably buy lottery
/// tickets, though.
///
/// This function will recursively call itself with a decremented
/// value for `tries` if it happens to pick a port that's already in
/// use. Once all tries are used up, it panics! Yay!
fn unclaimed_port(tries: u16) -> u16 {
    if tries == 0 {
        panic!("Couldn't find an unclaimed port for the test supervisor!")
    }
    let p = random_port();
    match TcpListener::bind(format!("127.0.0.1:{}", p)) {
        Ok(listener) => {
            // The system hasn't bound it. Now we make sure none of
            // our other tests have bound it.
            let mut ports = CLAIMED_PORTS.lock().unwrap();
            if ports.contains(&p) {
                // Oops, another test is using it, try again
                thread::sleep(Duration::from_millis(500));
                unclaimed_port(tries - 1)
            }
            else {
                // Nobody was using it. Return the port; the TcpListener
                // that is currently bound to the port will be dropped,
                // thus freeing the port for our use.
                ports.insert(p);
                p
            }
        },
        Err(_) => {
            // port already in use, try again
            unclaimed_port(tries - 1)
        }
    }
}

/// Return a random unprivileged, unregistered TCP port number.
fn random_port() -> u16 {
    // IANA port registrations go to 49151
    let between = Range::new(49152, ::std::u16::MAX);
    let mut rng = rand::thread_rng();
    between.ind_sample(&mut rng)
}

/// Find an executable relative to the current integration testing
/// executable.
///
/// Thus if the current executable is
///
///    /home/me/habitat/target/debug/deps/compilation-ccaf2f45c24e3840
///
/// and we look for `hab-sup`, we'll find it at
///
///    /home/me/habitat/target/debug/hab-sup
///
fn find_exe<B>(binary_name: B) -> PathBuf
    where B: AsRef<Path>
{
    let exe_root = env::current_exe()
        .unwrap()
        .parent()  // deps
        .unwrap()
        .parent()  // debug
        .unwrap()
        .to_path_buf();
    let bin = exe_root.join(binary_name.as_ref());
    assert!(
        bin.exists(),
        format!("Expected to find a {:?} executable at {:?}", binary_name.as_ref(), bin)
    );
    bin
}

impl TestSup {
    /// Create a new `TestSup` that will listen on randomly-selected
    /// ports for both gossip and HTTP requests so tests run in
    /// parallel don't step on each other.
    ///
    /// See also `new`.
    pub fn new_with_random_ports<R, O, P, S>(
        fs_root: R,
        origin: O,
        pkg_name: P,
        service_group: S,
    ) -> TestSup
    where
        R: AsRef<Path>,
        O: ToString,
        P: ToString,
        S: ToString,
    {
        // We'll give 10 tries to find a free port number
        let http_port = unclaimed_port(10);
        let butterfly_port = unclaimed_port(10);

        TestSup::new(
            fs_root,
            origin,
            pkg_name,
            service_group,
            http_port,
            butterfly_port,
        )
    }

    /// Bundle up a Habitat supervisor process along with an
    /// associated Butterfly client for injecting new configuration
    /// values. The supervisor executable is the one that has been
    /// compiled for the current `cargo test` invocation.
    ///
    /// The supervisor is configured to run a single package for a
    /// test. This package is assumed to have already been installed
    /// relative to `fs_root` (i.e., the `FS_ROOT` environment
    /// variable, which in our tests will be a randomly-named
    /// temporary directory that this supervisor will view as `/`.).
    ///
    /// A Butterfly client is also created for interacting with this
    /// supervisor and package. It is properly configured according to
    /// the value provided for `butterfly_port`. To use it, see the
    /// `apply_config` function.
    ///
    /// (No HTTP interaction with the supervisor is currently called
    /// for, so we don't have a HTTP client.)
    pub fn new<R, O, P, S>(
        fs_root: R,
        origin: O,
        pkg_name: P,
        service_group: S,
        http_port: u16,
        butterfly_port: u16,
    ) -> TestSup
    where
        R: AsRef<Path>,
        O: ToString,
        P: ToString,
        S: ToString,
    {
        let sup_exe = find_exe("hab-sup");
        let launcher_exe = find_exe("hab-launch");

        let mut cmd = Command::new(&launcher_exe);
        let listen_host = "0.0.0.0";

        let origin = origin.to_string();
        let pkg_name = pkg_name.to_string();
        let service_group = service_group.to_string();

        cmd.env("FS_ROOT", fs_root.as_ref().to_string_lossy().as_ref())
            .env("HAB_SUP_BINARY", &sup_exe)
            .env("HAB_DEPOT_URL", "http://hab.sup.test/v1/depot")
            .arg("start")
            .arg("--listen-gossip")
            .arg(format!("{}:{}", listen_host, butterfly_port))
            .arg("--listen-http")
            .arg(format!("{}:{}", listen_host, http_port))
            .arg(format!("{}/{}", origin, pkg_name))
            .stdin(Stdio::null())
            .stdout(Stdio::piped())
            .stderr(Stdio::piped());

        let bc = test_butterfly::Client::new(&pkg_name, &service_group, butterfly_port);

        TestSup {
            hab_root: fs_root.as_ref().to_path_buf(),
            origin_name: origin,
            package_name: pkg_name,
            service_group: service_group.to_string(),
            http_port: http_port,
            butterfly_port: butterfly_port,
            butterfly_client: bc,
            cmd: cmd,
            process: None,
        }
    }

    /// Spawn a process actually running the supervisor.
    pub fn start(&mut self) {
        let child = self.cmd.spawn().expect("Couldn't start the supervisor!");
        self.process = Some(child);
    }

    /// The equivalent of performing `hab apply` with the given
    /// configuration.
    pub fn apply_config<T>(&mut self, toml_config: T)
    where
        T: ToString,
    {
        self.butterfly_client.apply(toml_config.to_string())
    }
}

// We kill the supervisor so you don't have to! We also free up the
// ports used by this supervisor so other tests can use them.
impl Drop for TestSup {
    fn drop(&mut self) {
        let mut ports = CLAIMED_PORTS.lock().unwrap();
        ports.remove(&self.http_port);
        ports.remove(&self.butterfly_port);
        self.process
            .take()
            .expect("No process to kill!")
            .kill()
            .expect("Tried to kill supervisor!");
    }
}
<|endoftext|>


<commit_before>use anyhow::Context as _;
use cpal::{
    traits::{DeviceTrait as _, HostTrait as _, StreamTrait as _},
    Stream,
};
use crossbeam::queue::SegQueue;
use gba::{Command, GbaAudioSampler};
use pyrite::GbaHandle;
use std::sync::Arc;

const COMMANDS_CHUNK_SIZE: usize = 64;

pub fn run(gba: GbaHandle) -> anyhow::Result<Stream> {
    let host = cpal::default_host();
    let device = host
        .default_output_device()
        .ok_or_else(|| anyhow::Error::msg("no default output device"))?;
    let config = device
        .default_output_config()
        .context("error retrieving default output configuration")?;
    let commands_buffer_queue: Arc<SegQueue<[Command; COMMANDS_CHUNK_SIZE]>> =
        Arc::new(SegQueue::new());

    log::debug!("audio sample rate: {}", config.sample_rate().0);
    log::debug!("audio channels: {}", config.channels());
    log::debug!("audio sample format: {:?}", config.sample_format());
    log::debug!("audio buffer size: {:?}", config.buffer_size());

    let mut sound_source =
        GbaSoundSource::new(config.sample_rate().0, Arc::clone(&commands_buffer_queue));
    let channels = config.channels() as usize;
    let stream = device
        .build_output_stream(
            &config.into(),
            move |data: &mut [f32], _| sound_source.output(channels, data),
            |err| {
                log::error!("audio stream error: {err}");
            },
        )
        .context("failed to build output stream")?;
    stream.play().context("failed to play audio stream")?;

    let mut last_chunk_count = 0usize;
    gba.on_frame(move |gba, _| {
        let gba_audio_commands = gba.audio().commands();

        // Check to make sure that we have at most 2 frames worth of commands
        // waiting to be processed. If there are already two, then we just miss this
        // frame of audio commands.
        if commands_buffer_queue.len() <= last_chunk_count {
            last_chunk_count = 0;
            gba_audio_commands
                .chunks(COMMANDS_CHUNK_SIZE)
                .for_each(|src_chunk| {
                    let mut chunk = [Command::Wait(0); COMMANDS_CHUNK_SIZE];
                    (&mut chunk[..src_chunk.len()]).copy_from_slice(src_chunk);
                    commands_buffer_queue.push(chunk);
                    last_chunk_count += 1;
                });
        } else {
            log::debug!("missed frame audio command queue");
        }
    });
    Ok(stream)
}

struct GbaSoundSource {
    sampler: GbaAudioSampler,
    commands: Box<[Command; COMMANDS_CHUNK_SIZE]>,
    commands_idx: usize,
    commands_buffer: Arc<SegQueue<[Command; COMMANDS_CHUNK_SIZE]>>,
}

impl GbaSoundSource {
    fn new(frequency: u32, commands_buffer: Arc<SegQueue<[Command; COMMANDS_CHUNK_SIZE]>>) -> Self {
        GbaSoundSource {
            sampler: GbaAudioSampler::new(frequency),
            commands: Box::new([Command::Wait(0); COMMANDS_CHUNK_SIZE]),
            commands_idx: 0,
            commands_buffer,
        }
    }

    fn try_refill_buffer(&mut self) {
        if let Some(chunk) = self.commands_buffer.pop() {
            *self.commands = chunk;
            self.commands_idx = 0;
        }
    }

    fn next_command(&mut self) -> Option<Command> {
        if self.commands_idx >= COMMANDS_CHUNK_SIZE {
            self.try_refill_buffer();
        }

        if self.commands_idx >= COMMANDS_CHUNK_SIZE {
            None
        } else {
            let idx = self.commands_idx;
            self.commands_idx += 1;
            Some(self.commands[idx])
        }
    }

    fn output(&mut self, channels: usize, samples: &mut [f32]) {
        samples.chunks_exact_mut(channels).for_each(|frame| {
            while self.sampler.needs_commands() {
                if let Some(command) = self.next_command() {
                    self.sampler.command(command);
                } else {
                    break;
                }
            }

            if channels >= 2 {
                (frame[0], frame[1]) = self.sampler.frame(0.15);
            } else {
                let (left, right) = self.sampler.frame(0.15);
                frame[0] = (left + right) / 2.0;
            }

            if channels > 2 {
                frame[2..].fill(0.0);
            }
        });
    }
}
<commit_msg>Remove missed audio debug message.<commit_after>use anyhow::Context as _;
use cpal::{
    traits::{DeviceTrait as _, HostTrait as _, StreamTrait as _},
    Stream,
};
use crossbeam::queue::SegQueue;
use gba::{Command, GbaAudioSampler};
use pyrite::GbaHandle;
use std::sync::Arc;

const COMMANDS_CHUNK_SIZE: usize = 64;

pub fn run(gba: GbaHandle) -> anyhow::Result<Stream> {
    let host = cpal::default_host();
    let device = host
        .default_output_device()
        .ok_or_else(|| anyhow::Error::msg("no default output device"))?;
    let config = device
        .default_output_config()
        .context("error retrieving default output configuration")?;
    let commands_buffer_queue: Arc<SegQueue<[Command; COMMANDS_CHUNK_SIZE]>> =
        Arc::new(SegQueue::new());

    log::debug!("audio sample rate: {}", config.sample_rate().0);
    log::debug!("audio channels: {}", config.channels());
    log::debug!("audio sample format: {:?}", config.sample_format());
    log::debug!("audio buffer size: {:?}", config.buffer_size());

    let mut sound_source =
        GbaSoundSource::new(config.sample_rate().0, Arc::clone(&commands_buffer_queue));
    let channels = config.channels() as usize;
    let stream = device
        .build_output_stream(
            &config.into(),
            move |data: &mut [f32], _| sound_source.output(channels, data),
            |err| {
                log::error!("audio stream error: {err}");
            },
        )
        .context("failed to build output stream")?;
    stream.play().context("failed to play audio stream")?;

    let mut last_chunk_count = 0usize;
    gba.on_frame(move |gba, _| {
        let gba_audio_commands = gba.audio().commands();

        // Check to make sure that we have at most 2 frames worth of commands
        // waiting to be processed. If there are already two, then we just miss this
        // frame of audio commands.
        if commands_buffer_queue.len() <= last_chunk_count {
            last_chunk_count = 0;
            gba_audio_commands
                .chunks(COMMANDS_CHUNK_SIZE)
                .for_each(|src_chunk| {
                    let mut chunk = [Command::Wait(0); COMMANDS_CHUNK_SIZE];
                    (&mut chunk[..src_chunk.len()]).copy_from_slice(src_chunk);
                    commands_buffer_queue.push(chunk);
                    last_chunk_count += 1;
                });
        }
    });
    Ok(stream)
}

struct GbaSoundSource {
    sampler: GbaAudioSampler,
    commands: Box<[Command; COMMANDS_CHUNK_SIZE]>,
    commands_idx: usize,
    commands_buffer: Arc<SegQueue<[Command; COMMANDS_CHUNK_SIZE]>>,
}

impl GbaSoundSource {
    fn new(frequency: u32, commands_buffer: Arc<SegQueue<[Command; COMMANDS_CHUNK_SIZE]>>) -> Self {
        GbaSoundSource {
            sampler: GbaAudioSampler::new(frequency),
            commands: Box::new([Command::Wait(0); COMMANDS_CHUNK_SIZE]),
            commands_idx: 0,
            commands_buffer,
        }
    }

    fn try_refill_buffer(&mut self) {
        if let Some(chunk) = self.commands_buffer.pop() {
            *self.commands = chunk;
            self.commands_idx = 0;
        }
    }

    fn next_command(&mut self) -> Option<Command> {
        if self.commands_idx >= COMMANDS_CHUNK_SIZE {
            self.try_refill_buffer();
        }

        if self.commands_idx >= COMMANDS_CHUNK_SIZE {
            None
        } else {
            let idx = self.commands_idx;
            self.commands_idx += 1;
            Some(self.commands[idx])
        }
    }

    fn output(&mut self, channels: usize, samples: &mut [f32]) {
        samples.chunks_exact_mut(channels).for_each(|frame| {
            while self.sampler.needs_commands() {
                if let Some(command) = self.next_command() {
                    self.sampler.command(command);
                } else {
                    break;
                }
            }

            if channels >= 2 {
                (frame[0], frame[1]) = self.sampler.frame(0.15);
            } else {
                let (left, right) = self.sampler.frame(0.15);
                frame[0] = (left + right) / 2.0;
            }

            if channels > 2 {
                frame[2..].fill(0.0);
            }
        });
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::Read;
use command::Command;

type Cell = u8;

pub struct VM {
    pub cells: [Cell; 30_000],
    pub data_pointer: usize,
}

impl VM {
    pub fn new() -> VM {
        VM { cells: [0; 30_000], data_pointer: 0 }
    }

    pub fn output(&self) {
        print!("{}", self.cells[self.data_pointer] as char);
    }

    pub fn input(&mut self) {
        match io::stdin().bytes().next() {
            Some(res) => match res {
                Ok(value) => self.cells[self.data_pointer] = value,
                Err(error) => panic!(error),
            },
            None => {}
        }
        println!("");
    }

    pub fn increment(&mut self) {
        let new_value = match self.cells[self.data_pointer].checked_add(1) {
            None => 0,
            Some(x) => x,
        };
        self.cells[self.data_pointer] = new_value;
    }

    pub fn decrement(&mut self) {
        self.cells[self.data_pointer] -= 1;
    }

    pub fn right_shift(&mut self) {
        self.data_pointer += 1;
    }

    pub fn left_shift(&mut self) {
        self.data_pointer += 1;
    }

    pub fn apply(&mut self, command: Command) {
        match command {
            Command::Output => self.output(),
            Command::Input => self.input(),
            Command::Increment => self.increment(),
            Command::Decrement => self.decrement(),
            Command::RightShift => self.right_shift(),
            Command::LeftShift => self.left_shift(),
            _ => {},
        }
    }
}
<commit_msg>Simplify increment definition<commit_after>use std::io;
use std::io::Read;
use command::Command;

type Cell = u8;

pub struct VM {
    pub cells: [Cell; 30_000],
    pub data_pointer: usize,
}

impl VM {
    pub fn new() -> VM {
        VM { cells: [0; 30_000], data_pointer: 0 }
    }

    pub fn output(&self) {
        print!("{}", self.cells[self.data_pointer] as char);
    }

    pub fn input(&mut self) {
        match io::stdin().bytes().next() {
            Some(res) => match res {
                Ok(value) => self.cells[self.data_pointer] = value,
                Err(error) => panic!(error),
            },
            None => {}
        }
        println!("");
    }

    pub fn increment(&mut self) {
        self.cells[self.data_pointer] = self.cells[self.data_pointer].checked_add(1).unwrap_or(0);
    }

    pub fn decrement(&mut self) {
        self.cells[self.data_pointer] -= 1;
    }

    pub fn right_shift(&mut self) {
        self.data_pointer += 1;
    }

    pub fn left_shift(&mut self) {
        self.data_pointer += 1;
    }

    pub fn apply(&mut self, command: Command) {
        match command {
            Command::Output => self.output(),
            Command::Input => self.input(),
            Command::Increment => self.increment(),
            Command::Decrement => self.decrement(),
            Command::RightShift => self.right_shift(),
            Command::LeftShift => self.left_shift(),
            _ => {},
        }
    }
}
<|endoftext|>


<commit_before>use Cursive;
use Printer;
use With;
use direction::Direction;
use event::{Event, EventResult, Key};

use std::rc::Rc;
use theme::ColorStyle;
use vec::Vec2;
use view::View;

/// Checkable box.
pub struct Checkbox {
    checked: bool,
    enabled: bool,

    on_change: Option<Rc<Fn(&mut Cursive, bool)>>,
}

new_default!(Checkbox);

impl Checkbox {
    impl_enabled!(self.enabled);

    /// Creates a new, unchecked checkbox.
    pub fn new() -> Self {
        Checkbox {
            checked: false,
            enabled: true,
            on_change: None,
        }
    }

    /// Sets a callback to be used when the state changes.
    pub fn set_on_change<F: 'static + Fn(&mut Cursive, bool)>(&mut self,
                                                              on_change: F) {
        self.on_change = Some(Rc::new(on_change));
    }

    /// Sets a callback to be used when the state changes.
    ///
    /// Chainable variant.
    pub fn on_change<F: 'static + Fn(&mut Cursive, bool)>(self, on_change: F)
                                                          -> Self {
        self.with(|s| s.set_on_change(on_change))
    }

    /// Toggles the checkbox state.
    pub fn toggle(&mut self) -> EventResult {
        let checked = !self.checked;
        self.set_checked(checked)
    }

    /// Check the checkbox.
    pub fn check(&mut self) -> EventResult {
        self.set_checked(true)
    }

    /// Check the checkbox.
    ///
    /// Chainable variant.
    pub fn checked(self) -> Self {
        self.with(|s| { s.check(); })
    }

    /// Returns `true` if the checkbox is checked.
    pub fn is_checked(&self) -> bool {
        self.checked
    }

    /// Uncheck the checkbox.
    pub fn uncheck(&mut self) -> EventResult {
        self.set_checked(false)
    }

    /// Uncheck the checkbox.
    ///
    /// Chainable variant.
    pub fn unchecked(self) -> Self {
        self.with(|s| { s.uncheck(); })
    }

    /// Sets the checkbox state.
    pub fn set_checked(&mut self, checked: bool) -> EventResult {
        self.checked = checked;
        if let Some(ref on_change) = self.on_change {
            let on_change = on_change.clone();
            EventResult::with_cb(move |s| on_change(s, checked))
        } else {
            EventResult::Consumed(None)
        }
    }

    fn draw_internal(&self, printer: &Printer) {
        printer.print((0, 0), "[ ]");
        if self.checked {
            printer.print((1, 0), "X");
        }
    }
}

impl View for Checkbox {
    fn required_size(&mut self, _: Vec2) -> Vec2 {
        Vec2::new(3, 1)
    }

    fn take_focus(&mut self, _: Direction) -> bool {
        self.enabled
    }

    fn draw(&self, printer: &Printer) {
        if self.enabled {
            printer.with_selection(printer.focused,
                                   |printer| self.draw_internal(printer));
        } else {
            printer.with_color(ColorStyle::Secondary,
                               |printer| self.draw_internal(printer));
        }

    }

    fn on_event(&mut self, event: Event) -> EventResult {
        match event {
            Event::Key(Key::Enter) |
            Event::Char(' ') => self.toggle(),
            _ => EventResult::Ignored,
        }
    }
}
<commit_msg>Add mouse support to checkbox<commit_after>use Cursive;
use Printer;
use With;
use direction::Direction;
use event::{Event, EventResult, Key, MouseButton, MouseEvent};
use std::rc::Rc;
use theme::ColorStyle;
use vec::Vec2;
use view::View;

/// Checkable box.
pub struct Checkbox {
    checked: bool,
    enabled: bool,

    on_change: Option<Rc<Fn(&mut Cursive, bool)>>,
}

new_default!(Checkbox);

impl Checkbox {
    impl_enabled!(self.enabled);

    /// Creates a new, unchecked checkbox.
    pub fn new() -> Self {
        Checkbox {
            checked: false,
            enabled: true,
            on_change: None,
        }
    }

    /// Sets a callback to be used when the state changes.
    pub fn set_on_change<F: 'static + Fn(&mut Cursive, bool)>(
        &mut self, on_change: F
    ) {
        self.on_change = Some(Rc::new(on_change));
    }

    /// Sets a callback to be used when the state changes.
    ///
    /// Chainable variant.
    pub fn on_change<F: 'static + Fn(&mut Cursive, bool)>(
        self, on_change: F
    ) -> Self {
        self.with(|s| s.set_on_change(on_change))
    }

    /// Toggles the checkbox state.
    pub fn toggle(&mut self) -> EventResult {
        let checked = !self.checked;
        self.set_checked(checked)
    }

    /// Check the checkbox.
    pub fn check(&mut self) -> EventResult {
        self.set_checked(true)
    }

    /// Check the checkbox.
    ///
    /// Chainable variant.
    pub fn checked(self) -> Self {
        self.with(|s| {
            s.check();
        })
    }

    /// Returns `true` if the checkbox is checked.
    pub fn is_checked(&self) -> bool {
        self.checked
    }

    /// Uncheck the checkbox.
    pub fn uncheck(&mut self) -> EventResult {
        self.set_checked(false)
    }

    /// Uncheck the checkbox.
    ///
    /// Chainable variant.
    pub fn unchecked(self) -> Self {
        self.with(|s| {
            s.uncheck();
        })
    }

    /// Sets the checkbox state.
    pub fn set_checked(&mut self, checked: bool) -> EventResult {
        self.checked = checked;
        if let Some(ref on_change) = self.on_change {
            let on_change = on_change.clone();
            EventResult::with_cb(move |s| on_change(s, checked))
        } else {
            EventResult::Consumed(None)
        }
    }

    fn draw_internal(&self, printer: &Printer) {
        printer.print((0, 0), "[ ]");
        if self.checked {
            printer.print((1, 0), "X");
        }
    }
}

impl View for Checkbox {
    fn required_size(&mut self, _: Vec2) -> Vec2 {
        Vec2::new(3, 1)
    }

    fn take_focus(&mut self, _: Direction) -> bool {
        self.enabled
    }

    fn draw(&self, printer: &Printer) {
        if self.enabled {
            printer.with_selection(
                printer.focused,
                |printer| self.draw_internal(printer),
            );
        } else {
            printer.with_color(
                ColorStyle::Secondary,
                |printer| self.draw_internal(printer),
            );
        }
    }

    fn on_event(&mut self, event: Event) -> EventResult {
        match event {
            Event::Key(Key::Enter) | Event::Char(' ') => self.toggle(),
            Event::Mouse {
                event: MouseEvent::Release(MouseButton::Left),
                position,
                offset,
            } if position.fits_in_rect(offset, (3, 1)) =>
            {
                self.toggle()
            }
            _ => EventResult::Ignored,
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use serde::{Deserialize, Serialize};

// The maximum message size per state sync message
pub const MAX_MESSAGE_SIZE: usize = 16 * 1024 * 1024; /* 16 MiB */

#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct StateSyncConfig {
    pub data_streaming_service: DataStreamingServiceConfig,
    pub aptos_data_client: AptosDataClientConfig,
    pub state_sync_driver: StateSyncDriverConfig,
    pub storage_service: StorageServiceConfig,
}

/// The bootstrapping mode determines how the node will bootstrap to the latest
/// blockchain state, e.g., directly download the latest states.
#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub enum BootstrappingMode {
    ApplyTransactionOutputsFromGenesis, // Applies transaction outputs (starting at genesis)
    DownloadLatestStates, // Downloads the state keys and values (at the latest version)
    ExecuteTransactionsFromGenesis, // Executes transactions (starting at genesis)
}

impl BootstrappingMode {
    pub fn to_label(&self) -> &'static str {
        match self {
            BootstrappingMode::ApplyTransactionOutputsFromGenesis => {
                "apply_transaction_outputs_from_genesis"
            }
            BootstrappingMode::DownloadLatestStates => "download_latest_states",
            BootstrappingMode::ExecuteTransactionsFromGenesis => {
                "execute_transactions_from_genesis"
            }
        }
    }
}

/// The continuous syncing mode determines how the node will stay up-to-date
/// once it has bootstrapped and the blockchain continues to grow, e.g.,
/// continuously executing all transactions.
#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub enum ContinuousSyncingMode {
    ApplyTransactionOutputs, // Applies transaction outputs to stay up-to-date
    ExecuteTransactions,     // Executes transactions to stay up-to-date
}

impl ContinuousSyncingMode {
    pub fn to_label(&self) -> &'static str {
        match self {
            ContinuousSyncingMode::ApplyTransactionOutputs => "apply_transaction_outputs",
            ContinuousSyncingMode::ExecuteTransactions => "execute_transactions",
        }
    }
}

#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct StateSyncDriverConfig {
    pub bootstrapping_mode: BootstrappingMode, // The mode by which to bootstrap
    pub commit_notification_timeout_ms: u64, // The max time taken to process a commit notification
    pub continuous_syncing_mode: ContinuousSyncingMode, // The mode by which to sync after bootstrapping
    pub progress_check_interval_ms: u64, // The interval (ms) at which to check state sync progress
    pub max_connection_deadline_secs: u64, // The max time (secs) to wait for connections from peers
    pub max_consecutive_stream_notifications: u64, // The max number of notifications to process per driver loop
    pub max_pending_data_chunks: u64, // The max number of data chunks pending execution or commit
    pub max_stream_wait_time_ms: u64, // The max time (ms) to wait for a data stream notification
    pub num_versions_to_skip_snapshot_sync: u64, // The version lag we'll tolerate before snapshot syncing
}

/// The default state sync driver config will be the one that gets (and keeps)
/// the node up-to-date as quickly and cheaply as possible.
impl Default for StateSyncDriverConfig {
    fn default() -> Self {
        Self {
            bootstrapping_mode: BootstrappingMode::ApplyTransactionOutputsFromGenesis,
            commit_notification_timeout_ms: 5000,
            continuous_syncing_mode: ContinuousSyncingMode::ApplyTransactionOutputs,
            progress_check_interval_ms: 100,
            max_connection_deadline_secs: 10,
            max_consecutive_stream_notifications: 10,
            max_pending_data_chunks: 100,
            max_stream_wait_time_ms: 5000,
            num_versions_to_skip_snapshot_sync: 100_000_000, // At 5k TPS, this allows a node to fail for about 6 hours.
        }
    }
}

#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct StorageServiceConfig {
    pub max_concurrent_requests: u64, // Max num of concurrent storage server tasks
    pub max_epoch_chunk_size: u64,    // Max num of epoch ending ledger infos per chunk
    pub max_lru_cache_size: u64,      // Max num of items in the lru cache before eviction
    pub max_network_channel_size: u64, // Max num of pending network messages
    pub max_network_chunk_bytes: u64, // Max num of bytes to send per network message
    pub max_state_chunk_size: u64,    // Max num of state keys and values per chunk
    pub max_subscription_period_ms: u64, // Max period (ms) of pending subscription requests
    pub max_transaction_chunk_size: u64, // Max num of transactions per chunk
    pub max_transaction_output_chunk_size: u64, // Max num of transaction outputs per chunk
    pub storage_summary_refresh_interval_ms: u64, // The interval (ms) to refresh the storage summary
}

impl Default for StorageServiceConfig {
    fn default() -> Self {
        Self {
            max_concurrent_requests: 4000,
            max_epoch_chunk_size: 100,
            max_lru_cache_size: 500, // At ~0.6MiB per chunk, this should take no more than 0.5GiB
            max_network_channel_size: 4000,
            max_network_chunk_bytes: MAX_MESSAGE_SIZE as u64,
            max_state_chunk_size: 2000,
            max_subscription_period_ms: 5000,
            max_transaction_chunk_size: 2000,
            max_transaction_output_chunk_size: 2000,
            storage_summary_refresh_interval_ms: 50,
        }
    }
}

#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct DataStreamingServiceConfig {
    // The interval (milliseconds) at which to refresh the global data summary.
    pub global_summary_refresh_interval_ms: u64,

    // Maximum number of concurrent data client requests (per stream).
    pub max_concurrent_requests: u64,

    // Maximum number of concurrent data client requests (per stream) for state keys/values.
    pub max_concurrent_state_requests: u64,

    // Maximum channel sizes for each data stream listener. If messages are not
    // consumed, they will be dropped (oldest messages first). The remaining
    // messages will be retrieved using FIFO ordering.
    pub max_data_stream_channel_sizes: u64,

    // Maximum number of retries for a single client request before a data
    // stream will terminate.
    pub max_request_retry: u64,

    // Maximum number of notification ID to response context mappings held in
    // memory. Once the number grows beyond this value, garbage collection occurs.
    pub max_notification_id_mappings: u64,

    // The interval (milliseconds) at which to check the progress of each stream.
    pub progress_check_interval_ms: u64,
}

impl Default for DataStreamingServiceConfig {
    fn default() -> Self {
        Self {
            global_summary_refresh_interval_ms: 50,
            max_concurrent_requests: 3,
            max_concurrent_state_requests: 6,
            max_data_stream_channel_sizes: 300,
            max_request_retry: 5,
            max_notification_id_mappings: 300,
            progress_check_interval_ms: 100,
        }
    }
}

#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct AptosDataClientConfig {
    pub max_num_in_flight_priority_polls: u64, // Max num of in-flight polls for priority peers
    pub max_num_in_flight_regular_polls: u64,  // Max num of in-flight polls for regular peers
    pub response_timeout_ms: u64, // Timeout (in milliseconds) when waiting for a response
    pub summary_poll_interval_ms: u64, // Interval (in milliseconds) between data summary polls
    pub use_compression: bool,    // Whether or not to request compression for incoming data
}

impl Default for AptosDataClientConfig {
    fn default() -> Self {
        Self {
            max_num_in_flight_priority_polls: 10,
            max_num_in_flight_regular_polls: 10,
            response_timeout_ms: 10000,
            summary_poll_interval_ms: 200,
            use_compression: true,
        }
    }
}
<commit_msg>[State Sync] Default to execution mode.<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use serde::{Deserialize, Serialize};

// The maximum message size per state sync message
pub const MAX_MESSAGE_SIZE: usize = 16 * 1024 * 1024; /* 16 MiB */

#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct StateSyncConfig {
    pub data_streaming_service: DataStreamingServiceConfig,
    pub aptos_data_client: AptosDataClientConfig,
    pub state_sync_driver: StateSyncDriverConfig,
    pub storage_service: StorageServiceConfig,
}

/// The bootstrapping mode determines how the node will bootstrap to the latest
/// blockchain state, e.g., directly download the latest states.
#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub enum BootstrappingMode {
    ApplyTransactionOutputsFromGenesis, // Applies transaction outputs (starting at genesis)
    DownloadLatestStates, // Downloads the state keys and values (at the latest version)
    ExecuteTransactionsFromGenesis, // Executes transactions (starting at genesis)
}

impl BootstrappingMode {
    pub fn to_label(&self) -> &'static str {
        match self {
            BootstrappingMode::ApplyTransactionOutputsFromGenesis => {
                "apply_transaction_outputs_from_genesis"
            }
            BootstrappingMode::DownloadLatestStates => "download_latest_states",
            BootstrappingMode::ExecuteTransactionsFromGenesis => {
                "execute_transactions_from_genesis"
            }
        }
    }
}

/// The continuous syncing mode determines how the node will stay up-to-date
/// once it has bootstrapped and the blockchain continues to grow, e.g.,
/// continuously executing all transactions.
#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub enum ContinuousSyncingMode {
    ApplyTransactionOutputs, // Applies transaction outputs to stay up-to-date
    ExecuteTransactions,     // Executes transactions to stay up-to-date
}

impl ContinuousSyncingMode {
    pub fn to_label(&self) -> &'static str {
        match self {
            ContinuousSyncingMode::ApplyTransactionOutputs => "apply_transaction_outputs",
            ContinuousSyncingMode::ExecuteTransactions => "execute_transactions",
        }
    }
}

#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct StateSyncDriverConfig {
    pub bootstrapping_mode: BootstrappingMode, // The mode by which to bootstrap
    pub commit_notification_timeout_ms: u64, // The max time taken to process a commit notification
    pub continuous_syncing_mode: ContinuousSyncingMode, // The mode by which to sync after bootstrapping
    pub progress_check_interval_ms: u64, // The interval (ms) at which to check state sync progress
    pub max_connection_deadline_secs: u64, // The max time (secs) to wait for connections from peers
    pub max_consecutive_stream_notifications: u64, // The max number of notifications to process per driver loop
    pub max_pending_data_chunks: u64, // The max number of data chunks pending execution or commit
    pub max_stream_wait_time_ms: u64, // The max time (ms) to wait for a data stream notification
    pub num_versions_to_skip_snapshot_sync: u64, // The version lag we'll tolerate before snapshot syncing
}

/// The default state sync driver config will be the one that gets (and keeps)
/// the node up-to-date as quickly and cheaply as possible.
impl Default for StateSyncDriverConfig {
    fn default() -> Self {
        Self {
            bootstrapping_mode: BootstrappingMode::ExecuteTransactionsFromGenesis,
            commit_notification_timeout_ms: 5000,
            continuous_syncing_mode: ContinuousSyncingMode::ExecuteTransactions,
            progress_check_interval_ms: 100,
            max_connection_deadline_secs: 10,
            max_consecutive_stream_notifications: 10,
            max_pending_data_chunks: 100,
            max_stream_wait_time_ms: 5000,
            num_versions_to_skip_snapshot_sync: 100_000_000, // At 5k TPS, this allows a node to fail for about 6 hours.
        }
    }
}

#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct StorageServiceConfig {
    pub max_concurrent_requests: u64, // Max num of concurrent storage server tasks
    pub max_epoch_chunk_size: u64,    // Max num of epoch ending ledger infos per chunk
    pub max_lru_cache_size: u64,      // Max num of items in the lru cache before eviction
    pub max_network_channel_size: u64, // Max num of pending network messages
    pub max_network_chunk_bytes: u64, // Max num of bytes to send per network message
    pub max_state_chunk_size: u64,    // Max num of state keys and values per chunk
    pub max_subscription_period_ms: u64, // Max period (ms) of pending subscription requests
    pub max_transaction_chunk_size: u64, // Max num of transactions per chunk
    pub max_transaction_output_chunk_size: u64, // Max num of transaction outputs per chunk
    pub storage_summary_refresh_interval_ms: u64, // The interval (ms) to refresh the storage summary
}

impl Default for StorageServiceConfig {
    fn default() -> Self {
        Self {
            max_concurrent_requests: 4000,
            max_epoch_chunk_size: 100,
            max_lru_cache_size: 500, // At ~0.6MiB per chunk, this should take no more than 0.5GiB
            max_network_channel_size: 4000,
            max_network_chunk_bytes: MAX_MESSAGE_SIZE as u64,
            max_state_chunk_size: 2000,
            max_subscription_period_ms: 5000,
            max_transaction_chunk_size: 2000,
            max_transaction_output_chunk_size: 2000,
            storage_summary_refresh_interval_ms: 50,
        }
    }
}

#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct DataStreamingServiceConfig {
    // The interval (milliseconds) at which to refresh the global data summary.
    pub global_summary_refresh_interval_ms: u64,

    // Maximum number of concurrent data client requests (per stream).
    pub max_concurrent_requests: u64,

    // Maximum number of concurrent data client requests (per stream) for state keys/values.
    pub max_concurrent_state_requests: u64,

    // Maximum channel sizes for each data stream listener. If messages are not
    // consumed, they will be dropped (oldest messages first). The remaining
    // messages will be retrieved using FIFO ordering.
    pub max_data_stream_channel_sizes: u64,

    // Maximum number of retries for a single client request before a data
    // stream will terminate.
    pub max_request_retry: u64,

    // Maximum number of notification ID to response context mappings held in
    // memory. Once the number grows beyond this value, garbage collection occurs.
    pub max_notification_id_mappings: u64,

    // The interval (milliseconds) at which to check the progress of each stream.
    pub progress_check_interval_ms: u64,
}

impl Default for DataStreamingServiceConfig {
    fn default() -> Self {
        Self {
            global_summary_refresh_interval_ms: 50,
            max_concurrent_requests: 3,
            max_concurrent_state_requests: 6,
            max_data_stream_channel_sizes: 300,
            max_request_retry: 5,
            max_notification_id_mappings: 300,
            progress_check_interval_ms: 100,
        }
    }
}

#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct AptosDataClientConfig {
    pub max_num_in_flight_priority_polls: u64, // Max num of in-flight polls for priority peers
    pub max_num_in_flight_regular_polls: u64,  // Max num of in-flight polls for regular peers
    pub response_timeout_ms: u64, // Timeout (in milliseconds) when waiting for a response
    pub summary_poll_interval_ms: u64, // Interval (in milliseconds) between data summary polls
    pub use_compression: bool,    // Whether or not to request compression for incoming data
}

impl Default for AptosDataClientConfig {
    fn default() -> Self {
        Self {
            max_num_in_flight_priority_polls: 10,
            max_num_in_flight_regular_polls: 10,
            response_timeout_ms: 10000,
            summary_poll_interval_ms: 200,
            use_compression: true,
        }
    }
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2016-2017, Robert Ou <rqou@robertou.com> and contributors
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

//! # xc2bit: A library for working with Xilinx Coolrunner-II bitstreams
//!
//! xc2bit is a library for reading and writing bitstreams for the Xilinx Coolrunner-II family of CPLD devices.
//!
//! This project is the result of a reverse-engineering effort involving a combination of [imaging physical
//! CPLD devices](http://siliconexposed.blogspot.com/2014/03/getting-my-feet-wet-with-invasive.html) and black-box
//! reverse-engineering of generated .jed files. It is not an official project of Xilinx, Inc. and is not
//! affiliated or endorsed by Xilinx, Inc.
//!
//! Logically, a Coolrunner-II CPLD contains the following major blocks: function blocks (occasionally abbreviated
//! to FBs), a global interconnect (occasionally referred to as the ZIA or the AIM), and input/output blocks
//! (occasionally abbreviated to IOBs). Function blocks are further divided into the PLA (programmable logic array,
//! a matrix of AND and OR gates) and macrocells. In the Coolrunner-II architecture, macrocells also contain
//! an XOR gate and a register. The global interconnect accepts inputs from IOBs and function blocks and connects these
//! inputs into the PLA of each function block. IOBs also have direct connections to a corresponding macrocell in
//! a function block. (The reverse is not always true - on larger devices, there are macrocells that are not connected
//! to IOBs.) As a special exception, the smallest 32-macrocell devices also have one single input-only pin that is
//! connected directly into the global interconnect and does not have a corresponding macrocell.

use bittwiddler::*;
use serde_derive::{Deserialize, Serialize};

/// The number of inputs from the ZIA interconnect into the AND gate section of each PLA.
/// This is an unchangeable property of the architecture of the CPLD.
pub const INPUTS_PER_ANDTERM: usize = 40;
/// The number of AND gates in each PLA. This is also the number of inputs into each OR gate in the PLA.
/// This is an unchangeable property of the architecture of the CPLD.
pub const ANDTERMS_PER_FB: usize = 56;
/// The number of macrocells in each function block. This is also the number of OR gates in each PLA.
/// This is an unchangeable property of the architecture of the CPLD.
pub const MCS_PER_FB: usize = 16;

/// The number of BUFG sites for clock signals in the device.
/// This is an unchangeable property of the architecture of the CPLD.
pub const NUM_BUFG_CLK: usize = 3;
/// The number of BUFG sites for tristate signals in the device.
/// This is an unchangeable property of the architecture of the CPLD.
pub const NUM_BUFG_GTS: usize = 4;
/// The number of BUFG sites for set/reset signals in the device.
/// This is an unchangeable property of the architecture of the CPLD.
pub const NUM_BUFG_GSR: usize = 1;

mod bitstream;
pub use crate::bitstream::{XC2Bitstream, XC2BitstreamBits, XC2BitsXC2C32, XC2BitsXC2C32A};

mod crbit;
pub use crate::crbit::{FuseArray};

mod errors;
pub use crate::errors::{XC2BitError};

mod fb;
pub use crate::fb::{XC2BitstreamFB, CTC, CTR, CTS, CTE, get_pta, get_ptb, get_ptc};

mod fusemap_logical;
mod fusemap_physical;

mod globalbits;
pub use crate::globalbits::{XC2GlobalNets, XC2ClockDivRatio, XC2ClockDiv};

mod iob;
pub use crate::iob::{XC2MCSmallIOB, XC2IOBZIAMode, XC2IOBOBufMode, XC2ExtraIBuf, XC2IOBIbufMode, XC2MCLargeIOB,
                     iob_num_to_fb_mc_num, fb_mc_num_to_iob_num};

mod mc;
pub use crate::mc::{XC2Macrocell, XC2MCRegClkSrc, XC2MCRegResetSrc, XC2MCRegSetSrc, XC2MCRegMode, XC2MCFeedbackMode,
                    XC2MCXorMode};

mod partdb;
pub use crate::partdb::{XC2Device, XC2Speed, XC2Package, XC2DeviceSpeedPackage};

mod pla;
pub use crate::pla::{XC2PLAAndTerm, XC2PLAOrTerm};

mod structure;
pub use crate::structure::{get_gck, get_gts, get_gsr, get_cdrst, get_dge, get_device_structure};

mod zia;
pub use crate::zia::{XC2ZIAInput, zia_table_get_row, ZIA_MAP_32, ZIA_MAP_64, ZIA_MAP_128, ZIA_MAP_256,
                     ZIA_MAP_384, ZIA_MAP_512};

mod util;

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

    use std::fs::File;
    use std::io::Read;

    use jedec::*;

    fn run_one_reftest(jed_filename: &'static str) {
        let jed_path = std::path::Path::new(jed_filename);
        let mut txt_path = jed_path.to_path_buf();
        txt_path.set_extension("txt");

        let mut jed_data = Vec::new();
        let mut txt_data = Vec::new();

        File::open(&jed_path).expect("failed to open jed file")
            .read_to_end(&mut jed_data).expect("failed to read jed file");
        File::open(&txt_path).expect("failed to open txt file")
            .read_to_end(&mut txt_data).expect("failed to read txt file");

        // Read original JED
        let jed = JEDECFile::from_bytes(&jed_data).expect("failed to read jed");
        let parsed_bitstream_data = XC2Bitstream::from_jed(&jed).expect("failed to process jed");

        // Write to crbit
        let mut crbit = Vec::new();
        let write_fuse_array = parsed_bitstream_data.to_crbit();
        write_fuse_array.write_to_writer(&mut crbit).expect("failed to write crbit");

        // Read back from crbit
        let read_fuse_array = FuseArray::from_file_contents(&crbit).expect("failed to read crbit");
        let parsed_bitstream_data = XC2Bitstream::from_crbit(&read_fuse_array).expect("failed to process crbit");

        // FIXME: This is quite hacky
        let mut new_jed = Vec::new();
        parsed_bitstream_data.to_jed(&mut new_jed).expect("failed to write jed");
        assert_eq!(jed_data, new_jed);

        let mut human_readable_data = Vec::new();
        parsed_bitstream_data.dump_human_readable(&mut human_readable_data)
            .expect("failed to get human readable");
        assert_eq!(txt_data, human_readable_data);
    }

    // Include list of actual tests to run
    include!(concat!(env!("OUT_DIR"), "/reftests.rs"));
}
<commit_msg>xc2bit: make types public<commit_after>/*
Copyright (c) 2016-2017, Robert Ou <rqou@robertou.com> and contributors
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

//! # xc2bit: A library for working with Xilinx Coolrunner-II bitstreams
//!
//! xc2bit is a library for reading and writing bitstreams for the Xilinx Coolrunner-II family of CPLD devices.
//!
//! This project is the result of a reverse-engineering effort involving a combination of [imaging physical
//! CPLD devices](http://siliconexposed.blogspot.com/2014/03/getting-my-feet-wet-with-invasive.html) and black-box
//! reverse-engineering of generated .jed files. It is not an official project of Xilinx, Inc. and is not
//! affiliated or endorsed by Xilinx, Inc.
//!
//! Logically, a Coolrunner-II CPLD contains the following major blocks: function blocks (occasionally abbreviated
//! to FBs), a global interconnect (occasionally referred to as the ZIA or the AIM), and input/output blocks
//! (occasionally abbreviated to IOBs). Function blocks are further divided into the PLA (programmable logic array,
//! a matrix of AND and OR gates) and macrocells. In the Coolrunner-II architecture, macrocells also contain
//! an XOR gate and a register. The global interconnect accepts inputs from IOBs and function blocks and connects these
//! inputs into the PLA of each function block. IOBs also have direct connections to a corresponding macrocell in
//! a function block. (The reverse is not always true - on larger devices, there are macrocells that are not connected
//! to IOBs.) As a special exception, the smallest 32-macrocell devices also have one single input-only pin that is
//! connected directly into the global interconnect and does not have a corresponding macrocell.

use bittwiddler::*;
use serde_derive::{Deserialize, Serialize};

/// The number of inputs from the ZIA interconnect into the AND gate section of each PLA.
/// This is an unchangeable property of the architecture of the CPLD.
pub const INPUTS_PER_ANDTERM: usize = 40;
/// The number of AND gates in each PLA. This is also the number of inputs into each OR gate in the PLA.
/// This is an unchangeable property of the architecture of the CPLD.
pub const ANDTERMS_PER_FB: usize = 56;
/// The number of macrocells in each function block. This is also the number of OR gates in each PLA.
/// This is an unchangeable property of the architecture of the CPLD.
pub const MCS_PER_FB: usize = 16;

/// The number of BUFG sites for clock signals in the device.
/// This is an unchangeable property of the architecture of the CPLD.
pub const NUM_BUFG_CLK: usize = 3;
/// The number of BUFG sites for tristate signals in the device.
/// This is an unchangeable property of the architecture of the CPLD.
pub const NUM_BUFG_GTS: usize = 4;
/// The number of BUFG sites for set/reset signals in the device.
/// This is an unchangeable property of the architecture of the CPLD.
pub const NUM_BUFG_GSR: usize = 1;

mod bitstream;
pub use crate::bitstream::{XC2Bitstream, XC2BitstreamBits,
    XC2BitsXC2C32, XC2BitsXC2C32A,
    XC2BitsXC2C64, XC2BitsXC2C64A,
    XC2BitsXC2C128,
    XC2BitsXC2C256,
    XC2BitsXC2C384,
    XC2BitsXC2C512};

mod crbit;
pub use crate::crbit::{FuseArray};

mod errors;
pub use crate::errors::{XC2BitError};

mod fb;
pub use crate::fb::{XC2BitstreamFB, CTC, CTR, CTS, CTE, get_pta, get_ptb, get_ptc};

mod fusemap_logical;
mod fusemap_physical;

mod globalbits;
pub use crate::globalbits::{XC2GlobalNets, XC2ClockDivRatio, XC2ClockDiv};

mod iob;
pub use crate::iob::{XC2MCSmallIOB, XC2IOBZIAMode, XC2IOBOBufMode, XC2ExtraIBuf, XC2IOBIbufMode, XC2MCLargeIOB,
                     iob_num_to_fb_mc_num, fb_mc_num_to_iob_num};

mod mc;
pub use crate::mc::{XC2Macrocell, XC2MCRegClkSrc, XC2MCRegResetSrc, XC2MCRegSetSrc, XC2MCRegMode, XC2MCFeedbackMode,
                    XC2MCXorMode};

mod partdb;
pub use crate::partdb::{XC2Device, XC2Speed, XC2Package, XC2DeviceSpeedPackage};

mod pla;
pub use crate::pla::{XC2PLAAndTerm, XC2PLAOrTerm};

mod structure;
pub use crate::structure::{get_gck, get_gts, get_gsr, get_cdrst, get_dge, get_device_structure};

mod zia;
pub use crate::zia::{XC2ZIAInput, zia_table_get_row, ZIA_MAP_32, ZIA_MAP_64, ZIA_MAP_128, ZIA_MAP_256,
                     ZIA_MAP_384, ZIA_MAP_512};

mod util;

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

    use std::fs::File;
    use std::io::Read;

    use jedec::*;

    fn run_one_reftest(jed_filename: &'static str) {
        let jed_path = std::path::Path::new(jed_filename);
        let mut txt_path = jed_path.to_path_buf();
        txt_path.set_extension("txt");

        let mut jed_data = Vec::new();
        let mut txt_data = Vec::new();

        File::open(&jed_path).expect("failed to open jed file")
            .read_to_end(&mut jed_data).expect("failed to read jed file");
        File::open(&txt_path).expect("failed to open txt file")
            .read_to_end(&mut txt_data).expect("failed to read txt file");

        // Read original JED
        let jed = JEDECFile::from_bytes(&jed_data).expect("failed to read jed");
        let parsed_bitstream_data = XC2Bitstream::from_jed(&jed).expect("failed to process jed");

        // Write to crbit
        let mut crbit = Vec::new();
        let write_fuse_array = parsed_bitstream_data.to_crbit();
        write_fuse_array.write_to_writer(&mut crbit).expect("failed to write crbit");

        // Read back from crbit
        let read_fuse_array = FuseArray::from_file_contents(&crbit).expect("failed to read crbit");
        let parsed_bitstream_data = XC2Bitstream::from_crbit(&read_fuse_array).expect("failed to process crbit");

        // FIXME: This is quite hacky
        let mut new_jed = Vec::new();
        parsed_bitstream_data.to_jed(&mut new_jed).expect("failed to write jed");
        assert_eq!(jed_data, new_jed);

        let mut human_readable_data = Vec::new();
        parsed_bitstream_data.dump_human_readable(&mut human_readable_data)
            .expect("failed to get human readable");
        assert_eq!(txt_data, human_readable_data);
    }

    // Include list of actual tests to run
    include!(concat!(env!("OUT_DIR"), "/reftests.rs"));
}
<|endoftext|>


<commit_before>use shaders::Position;
use specs;
use zombie::ZombieDrawable;

#[derive(Debug, Clone)]
pub struct Zombies {
  pub zombies: Vec<ZombieDrawable>,
}

impl Zombies {
  pub fn new() -> Zombies {
    Zombies {
      zombies: vec![
        // 1
        ZombieDrawable::new(Position::new(200.0, 10.0)),
        ZombieDrawable::new(Position::new(-200.0, 10.0)),
        ZombieDrawable::new(Position::new(10.0, 200.0)),
        ZombieDrawable::new(Position::new(10.0, -200.0)),
        // 2
        ZombieDrawable::new(Position::new(500.0, 40.0)),
        ZombieDrawable::new(Position::new(-500.0, 40.0)),
        ZombieDrawable::new(Position::new(40.0, 500.0)),
        ZombieDrawable::new(Position::new(40.0, -500.0)),
        // 3
        ZombieDrawable::new(Position::new(700.0, 60.0)),
        ZombieDrawable::new(Position::new(-900.0, 60.0)),
        ZombieDrawable::new(Position::new(60.0, 700.0)),
        ZombieDrawable::new(Position::new(60.0, -700.0)),
        // 4
        ZombieDrawable::new(Position::new(800.0, 160.0)),
        ZombieDrawable::new(Position::new(-1000.0, 160.0)),
        ZombieDrawable::new(Position::new(160.0, 800.0)),
        ZombieDrawable::new(Position::new(160.0, -800.0)),
      ]
    }
  }
}

impl specs::prelude::Component for Zombies {
  type Storage = specs::storage::VecStorage<Zombies>;
}
<commit_msg>Add lot of zombies<commit_after>use shaders::Position;
use specs;
use zombie::ZombieDrawable;

#[derive(Debug, Clone)]
pub struct Zombies {
  pub zombies: Vec<ZombieDrawable>,
}

impl Zombies {
  pub fn new() -> Zombies {
    Zombies {
      zombies: vec![
        // 1
        ZombieDrawable::new(Position::new(500.0, 40.0)),
        ZombieDrawable::new(Position::new(-500.0, 40.0)),
        ZombieDrawable::new(Position::new(40.0, 500.0)),
        ZombieDrawable::new(Position::new(40.0, -500.0)),
        ZombieDrawable::new(Position::new(300.0, -300.0)),
        ZombieDrawable::new(Position::new(-300.0, -300.0)),
        ZombieDrawable::new(Position::new(300.0, 300.0)),
        ZombieDrawable::new(Position::new(-300.0, 300.0)),
        ZombieDrawable::new(Position::new(500.0, -500.0)),
        ZombieDrawable::new(Position::new(-500.0, -500.0)),
        ZombieDrawable::new(Position::new(-500.0, 500.0)),
        ZombieDrawable::new(Position::new(500.0, 500.0)),
        ZombieDrawable::new(Position::new(600.0, -600.0)),
        ZombieDrawable::new(Position::new(-600.0, -600.0)),
        ZombieDrawable::new(Position::new(-600.0, 600.0)),
        ZombieDrawable::new(Position::new(600.0, 600.0)),
        ZombieDrawable::new(Position::new(650.0, -650.0)),
        ZombieDrawable::new(Position::new(-650.0, -650.0)),
        ZombieDrawable::new(Position::new(-650.0, 650.0)),
        ZombieDrawable::new(Position::new(650.0, 650.0)),
        // 2
        ZombieDrawable::new(Position::new(700.0, 60.0)),
        ZombieDrawable::new(Position::new(-900.0, 60.0)),
        ZombieDrawable::new(Position::new(60.0, 700.0)),
        ZombieDrawable::new(Position::new(60.0, -700.0)),
        // 3
        ZombieDrawable::new(Position::new(750.0, 60.0)),
        ZombieDrawable::new(Position::new(-750.0, 60.0)),
        ZombieDrawable::new(Position::new(60.0, 750.0)),
        ZombieDrawable::new(Position::new(60.0, -750.0)),
        // 4
        ZombieDrawable::new(Position::new(800.0, 160.0)),
        ZombieDrawable::new(Position::new(-1000.0, 160.0)),
        ZombieDrawable::new(Position::new(160.0, 800.0)),
        ZombieDrawable::new(Position::new(160.0, -800.0)),
        // 5
        ZombieDrawable::new(Position::new(900.0, 10.0)),
        ZombieDrawable::new(Position::new(-900.0, 10.0)),
        ZombieDrawable::new(Position::new(10.0, 900.0)),
        ZombieDrawable::new(Position::new(10.0, -900.0)),

        // 6
        ZombieDrawable::new(Position::new(1000.0, 10.0)),
        ZombieDrawable::new(Position::new(-1000.0, 10.0)),
        ZombieDrawable::new(Position::new(10.0, 1000.0)),
        ZombieDrawable::new(Position::new(10.0, -1000.0)),
        // 7
        ZombieDrawable::new(Position::new(1100.0, 10.0)),
        ZombieDrawable::new(Position::new(-1100.0, 10.0)),
        ZombieDrawable::new(Position::new(10.0, 1100.0)),
        ZombieDrawable::new(Position::new(10.0, -1100.0)),
        // 8
        ZombieDrawable::new(Position::new(1200.0, 10.0)),
        ZombieDrawable::new(Position::new(-1200.0, 10.0)),
        ZombieDrawable::new(Position::new(10.0, 1200.0)),
        ZombieDrawable::new(Position::new(10.0, -1200.0)),
      ]
    }
  }
}

impl specs::prelude::Component for Zombies {
  type Storage = specs::storage::VecStorage<Zombies>;
}
<|endoftext|>


<commit_before>//! A simple wait-free, grow-only pagetable, assumes a dense keyspace.

use std::sync::atomic::Ordering::{Relaxed, SeqCst};

use super::*;

const FANFACTOR: u64 = 18;
const FANOUT: u64 = 1 << FANFACTOR;
const FAN_MASK: u64 = FANOUT - 1;

pub type PageId = u64;

#[inline(always)]
fn split_fanout(i: u64) -> (u64, u64) {
    // right shift 32 on 32-bit pointer systems panics
    #[cfg(target_pointer_width = "64")]
    assert!(
        i <= 1 << (FANFACTOR * 2),
        "trying to access key of {}, which is \
         higher than 2 ^ {}",
        i,
        (FANFACTOR * 2)
    );

    let left = i >> FANFACTOR;
    let right = i & FAN_MASK;
    (left, right)
}

struct Node1<T: Send + 'static> {
    children: [Atomic<Node2<T>>; FANOUT as usize],
}

struct Node2<T: Send + 'static> {
    children: [Atomic<T>; FANOUT as usize],
}

impl<T: Send + 'static> Node1<T> {
    fn new() -> Box<Node1<T>> {
        let mut node: Box<Node1<T>> =
            unsafe { Box::new(std::mem::uninitialized()) };
        for i in 0..FANOUT as usize {
            node.children[i] = Atomic::null();
        }
        node
    }
}

impl<T: Send + 'static> Node2<T> {
    fn new() -> Owned<Node2<T>> {
        let mut node: Box<Node2<T>> =
            unsafe { Box::new(std::mem::uninitialized()) };
        for i in 0..FANOUT as usize {
            node.children[i] = Atomic::null();
        }
        Owned::from(node)
    }
}

/// A simple lock-free radix tree.
pub struct PageTable<T>
where
    T: 'static + Send + Sync,
{
    head: Atomic<Node1<T>>,
}

impl<T> Default for PageTable<T>
where
    T: 'static + Send + Sync,
{
    fn default() -> PageTable<T> {
        let head = Node1::new();
        PageTable {
            head: Atomic::from(head),
        }
    }
}

impl<T> PageTable<T>
where
    T: 'static + Send + Sync,
{
    /// Atomically swap the previous value in a tree with a new one.
    pub fn swap<'g>(
        &self,
        pid: PageId,
        new: Shared<'g, T>,
        guard: &'g Guard,
    ) -> Shared<'g, T> {
        let tip = traverse(self.head.load(SeqCst, guard), pid, guard);
        debug_delay();
        tip.swap(new, SeqCst, guard)
    }

    /// Compare and swap an old value to a new one.
    pub fn cas<'g>(
        &self,
        pid: PageId,
        old: Shared<'g, T>,
        new: Shared<'g, T>,
        guard: &'g Guard,
    ) -> std::result::Result<Shared<'g, T>, Shared<'g, T>> {
        debug_delay();
        let tip = traverse(self.head.load(SeqCst, guard), pid, guard);

        debug_delay();

        let _ = tip
            .compare_and_set(old, new, SeqCst, guard)
            .map_err(|e| e.current)?;

        if !old.is_null() {
            unsafe {
                guard.defer_destroy(old);
            }
        }
        Ok(new)
    }

    /// Try to get a value from the tree.
    pub fn get<'g>(
        &self,
        pid: PageId,
        guard: &'g Guard,
    ) -> Option<Shared<'g, T>> {
        debug_delay();
        let tip = traverse(self.head.load(SeqCst, guard), pid, guard);

        let res = tip.load(SeqCst, guard);
        if res.is_null() {
            None
        } else {
            Some(res)
        }
    }

    /// Delete a value from the tree, returning the old value if it was set.
    pub fn del<'g>(
        &self,
        pid: PageId,
        guard: &'g Guard,
    ) -> Option<Shared<'g, T>> {
        debug_delay();
        let old = self.swap(pid, Shared::null(), guard);
        if !old.is_null() {
            unsafe {
                guard.defer_destroy(old);
            }
            Some(old)
        } else {
            None
        }
    }
}

fn traverse<'g, T: 'static + Send>(
    head: Shared<'g, Node1<T>>,
    k: PageId,
    guard: &'g Guard,
) -> &'g Atomic<T> {
    let (l1k, l2k) = split_fanout(k);

    debug_delay();
    let l1 = unsafe { &head.deref().children };

    debug_delay();
    let mut l2_ptr = l1[usize::try_from(l1k).unwrap()].load(SeqCst, guard);

    if l2_ptr.is_null() {
        let next_child = Node2::new().into_shared(guard);

        debug_delay();
        let ret = l1[usize::try_from(l1k).unwrap()]
            .compare_and_set(l2_ptr, next_child, SeqCst, guard);

        match ret {
            Ok(_) => {
                // CAS worked
                l2_ptr = next_child;
            }
            Err(e) => {
                // another thread beat us, drop unused created
                // child and use what is already set
                l2_ptr = e.current;
            }
        }
    }

    debug_delay();
    let l2 = unsafe { &l2_ptr.deref().children };

    &l2[usize::try_from(l2k).unwrap()]
}

impl<T> Drop for PageTable<T>
where
    T: 'static + Send + Sync,
{
    fn drop(&mut self) {
        unsafe {
            let head = self.head.load(Relaxed, &unprotected()).into_owned();
            drop(head);
        }
    }
}

impl<T: Send + 'static> Drop for Node1<T> {
    fn drop(&mut self) {
        unsafe {
            let children: Vec<*const Node2<T>> = self
                .children
                .iter()
                .map(|c| c.load(Relaxed, &unprotected()).as_raw())
                .filter(|c| !c.is_null())
                .collect();

            for child in children {
                drop(Box::from_raw(child as *mut Node2<T>));
            }
        }
    }
}

impl<T: Send + 'static> Drop for Node2<T> {
    fn drop(&mut self) {
        unsafe {
            let children: Vec<*const T> = self
                .children
                .iter()
                .map(|c| c.load(Relaxed, &unprotected()).as_raw())
                .filter(|c| !c.is_null())
                .collect();

            for child in children {
                drop(Box::from_raw(child as *mut T));
            }
        }
    }
}

#[test]
fn test_split_fanout() {
    assert_eq!(
        split_fanout(0b11_1111_1111_1111_1111),
        (0, 0b11_1111_1111_1111_1111)
    );
    assert_eq!(
        split_fanout(0b111_1111_1111_1111_1111),
        (0b1, 0b11_1111_1111_1111_1111)
    );
}

#[test]
fn basic_functionality() {
    unsafe {
        let guard = pin();
        let rt = PageTable::default();
        let v1 = Owned::new(5).into_shared(&guard);
        rt.cas(0, Shared::null(), v1, &guard).unwrap();
        let ptr = rt.get(0, &guard).unwrap();
        assert_eq!(ptr.deref(), &5);
        rt.cas(0, ptr, Owned::new(6).into_shared(&guard), &guard)
            .unwrap();
        assert_eq!(rt.get(0, &guard).unwrap().deref(), &6);
        rt.del(0, &guard);
        assert!(rt.get(0, &guard).is_none());

        let k2 = 321 << FANFACTOR;
        let k3 = k2 + 1;

        let v2 = Owned::new(2).into_shared(&guard);
        rt.cas(k2, Shared::null(), v2, &guard).unwrap();
        assert_eq!(rt.get(k2, &guard).unwrap().deref(), &2);
        assert!(rt.get(k3, &guard).is_none());
        let v3 = Owned::new(3).into_shared(&guard);
        rt.cas(k3, Shared::null(), v3, &guard).unwrap();
        assert_eq!(rt.get(k3, &guard).unwrap().deref(), &3);
        assert_eq!(rt.get(k2, &guard).unwrap().deref(), &2);
    }
}

#[test]
#[ignore]
fn test_model() {
    use self::Shared as EpochShared;
    use model::{model, prop_oneof};

    model! {
        Model => let mut m = std::collections::HashMap::new(),
        Implementation => let i = PageTable::default(),
        Insert((u64, u64))((k, new) in (0u64..4, 0u64..4)) => {
            if !m.contains_key(&k) {
                m.insert(k, new);

                let guard = pin();
                let v = Owned::new(new).into_shared(&guard);
                i.cas(k, EpochShared::null(), v, &guard ).expect("should be able to insert a value");
            }
        },
        Get(u64)(k in 0u64..4) => {
            let guard = pin();
            let expected = m.get(&k);
            let actual = i.get(k, &guard).map(|s| unsafe { s.deref() });
            assert_eq!(expected, actual);
        },
        Cas((u64, u64, u64))((k, old, new) in (0u64..4, 0u64..4, 0u64..4)) => {
            let guard = pin();
            let expected_current = m.get(&k).cloned();
            let actual_current = i.get(k, &guard);
            assert_eq!(expected_current, actual_current.map(|s| unsafe { *s.deref() }));
            if expected_current.is_none() {
                continue;
            }

            let new_v = Owned::new(new).into_shared(&guard);

            if expected_current == Some(old) {
                m.insert(k, new);
                let cas_res = i.cas(k, actual_current.unwrap(), new_v, &guard);
                assert!(cas_res.is_ok());
            };
        }
    }
}

#[test]
#[ignore]
fn test_linearizability() {
    use self::Shared as EpochShared;
    use model::{linearizable, prop_oneof, Shared};

    linearizable! {
        Implementation => let i = Shared::new(PageTable::default()),
        Get(u64)(k in 0u64..4) -> Option<u64> {
            let guard = pin();
            unsafe {
                i.get(k, &guard).map(|s| *s.deref())
            }
        },
        Insert((u64, u64))((k, new) in (0u64..4, 0u64..4)) -> bool {
            let guard = pin();
            let v = Owned::new(new).into_shared(&guard);
            i.cas(k, EpochShared::null(), v, &guard).is_err()
        },
        Cas((u64, u64, u64))((k, old, new)
            in (0u64..4, 0u64..4, 0u64..4))
            -> std::result::Result<(), u64> {
            let guard = pin();
            i.cas(k, Owned::new(old).into_shared(&guard), Owned::new(new).into_shared(&guard), &guard)
                .map(|_| ())
                .map_err(|s| if s.is_null() {
                    0
                } else {
                    unsafe { *s.deref() }
                })
        }
    }
}
<commit_msg>Directly allocate nodes on the heap<commit_after>//! A simple wait-free, grow-only pagetable, assumes a dense keyspace.

use std::{
    alloc::{alloc, Layout},
    mem::{align_of, size_of},
    sync::atomic::Ordering::{Relaxed, SeqCst},
};

use super::*;

const FANFACTOR: u64 = 18;
const FANOUT: u64 = 1 << FANFACTOR;
const FAN_MASK: u64 = FANOUT - 1;

pub type PageId = u64;

#[inline(always)]
fn split_fanout(i: u64) -> (u64, u64) {
    // right shift 32 on 32-bit pointer systems panics
    #[cfg(target_pointer_width = "64")]
    assert!(
        i <= 1 << (FANFACTOR * 2),
        "trying to access key of {}, which is \
         higher than 2 ^ {}",
        i,
        (FANFACTOR * 2)
    );

    let left = i >> FANFACTOR;
    let right = i & FAN_MASK;
    (left, right)
}

struct Node1<T: Send + 'static> {
    children: [Atomic<Node2<T>>; FANOUT as usize],
}

struct Node2<T: Send + 'static> {
    children: [Atomic<T>; FANOUT as usize],
}

impl<T: Send + 'static> Node1<T> {
    fn new() -> Box<Node1<T>> {
        let size = size_of::<Node1<T>>();
        let align = align_of::<Node1<T>>();
        let mut node = unsafe {
            let layout = Layout::from_size_align_unchecked(size, align);
            let ptr = alloc(layout) as *mut Node1<T>;
            Box::from_raw(ptr)
        };

        for i in 0..FANOUT as usize {
            node.children[i] = Atomic::null();
        }
        node
    }
}

impl<T: Send + 'static> Node2<T> {
    fn new() -> Owned<Node2<T>> {
        let size = size_of::<Node2<T>>();
        let align = align_of::<Node2<T>>();
        let mut node = unsafe {
            let layout = Layout::from_size_align_unchecked(size, align);
            let ptr = alloc(layout) as *mut Node2<T>;
            Box::from_raw(ptr)
        };
        for i in 0..FANOUT as usize {
            node.children[i] = Atomic::null();
        }
        Owned::from(node)
    }
}

/// A simple lock-free radix tree.
pub struct PageTable<T>
where
    T: 'static + Send + Sync,
{
    head: Atomic<Node1<T>>,
}

impl<T> Default for PageTable<T>
where
    T: 'static + Send + Sync,
{
    fn default() -> PageTable<T> {
        let head = Node1::new();
        PageTable {
            head: Atomic::from(head),
        }
    }
}

impl<T> PageTable<T>
where
    T: 'static + Send + Sync,
{
    /// Atomically swap the previous value in a tree with a new one.
    pub fn swap<'g>(
        &self,
        pid: PageId,
        new: Shared<'g, T>,
        guard: &'g Guard,
    ) -> Shared<'g, T> {
        let tip = traverse(self.head.load(SeqCst, guard), pid, guard);
        debug_delay();
        tip.swap(new, SeqCst, guard)
    }

    /// Compare and swap an old value to a new one.
    pub fn cas<'g>(
        &self,
        pid: PageId,
        old: Shared<'g, T>,
        new: Shared<'g, T>,
        guard: &'g Guard,
    ) -> std::result::Result<Shared<'g, T>, Shared<'g, T>> {
        debug_delay();
        let tip = traverse(self.head.load(SeqCst, guard), pid, guard);

        debug_delay();

        let _ = tip
            .compare_and_set(old, new, SeqCst, guard)
            .map_err(|e| e.current)?;

        if !old.is_null() {
            unsafe {
                guard.defer_destroy(old);
            }
        }
        Ok(new)
    }

    /// Try to get a value from the tree.
    pub fn get<'g>(
        &self,
        pid: PageId,
        guard: &'g Guard,
    ) -> Option<Shared<'g, T>> {
        debug_delay();
        let tip = traverse(self.head.load(SeqCst, guard), pid, guard);

        let res = tip.load(SeqCst, guard);
        if res.is_null() {
            None
        } else {
            Some(res)
        }
    }

    /// Delete a value from the tree, returning the old value if it was set.
    pub fn del<'g>(
        &self,
        pid: PageId,
        guard: &'g Guard,
    ) -> Option<Shared<'g, T>> {
        debug_delay();
        let old = self.swap(pid, Shared::null(), guard);
        if !old.is_null() {
            unsafe {
                guard.defer_destroy(old);
            }
            Some(old)
        } else {
            None
        }
    }
}

fn traverse<'g, T: 'static + Send>(
    head: Shared<'g, Node1<T>>,
    k: PageId,
    guard: &'g Guard,
) -> &'g Atomic<T> {
    let (l1k, l2k) = split_fanout(k);

    debug_delay();
    let l1 = unsafe { &head.deref().children };

    debug_delay();
    let mut l2_ptr = l1[usize::try_from(l1k).unwrap()].load(SeqCst, guard);

    if l2_ptr.is_null() {
        let next_child = Node2::new().into_shared(guard);

        debug_delay();
        let ret = l1[usize::try_from(l1k).unwrap()]
            .compare_and_set(l2_ptr, next_child, SeqCst, guard);

        match ret {
            Ok(_) => {
                // CAS worked
                l2_ptr = next_child;
            }
            Err(e) => {
                // another thread beat us, drop unused created
                // child and use what is already set
                l2_ptr = e.current;
            }
        }
    }

    debug_delay();
    let l2 = unsafe { &l2_ptr.deref().children };

    &l2[usize::try_from(l2k).unwrap()]
}

impl<T> Drop for PageTable<T>
where
    T: 'static + Send + Sync,
{
    fn drop(&mut self) {
        unsafe {
            let head = self.head.load(Relaxed, &unprotected()).into_owned();
            drop(head);
        }
    }
}

impl<T: Send + 'static> Drop for Node1<T> {
    fn drop(&mut self) {
        unsafe {
            let children: Vec<*const Node2<T>> = self
                .children
                .iter()
                .map(|c| c.load(Relaxed, &unprotected()).as_raw())
                .filter(|c| !c.is_null())
                .collect();

            for child in children {
                drop(Box::from_raw(child as *mut Node2<T>));
            }
        }
    }
}

impl<T: Send + 'static> Drop for Node2<T> {
    fn drop(&mut self) {
        unsafe {
            let children: Vec<*const T> = self
                .children
                .iter()
                .map(|c| c.load(Relaxed, &unprotected()).as_raw())
                .filter(|c| !c.is_null())
                .collect();

            for child in children {
                drop(Box::from_raw(child as *mut T));
            }
        }
    }
}

#[test]
fn test_split_fanout() {
    assert_eq!(
        split_fanout(0b11_1111_1111_1111_1111),
        (0, 0b11_1111_1111_1111_1111)
    );
    assert_eq!(
        split_fanout(0b111_1111_1111_1111_1111),
        (0b1, 0b11_1111_1111_1111_1111)
    );
}

#[test]
fn basic_functionality() {
    unsafe {
        let guard = pin();
        let rt = PageTable::default();
        let v1 = Owned::new(5).into_shared(&guard);
        rt.cas(0, Shared::null(), v1, &guard).unwrap();
        let ptr = rt.get(0, &guard).unwrap();
        assert_eq!(ptr.deref(), &5);
        rt.cas(0, ptr, Owned::new(6).into_shared(&guard), &guard)
            .unwrap();
        assert_eq!(rt.get(0, &guard).unwrap().deref(), &6);
        rt.del(0, &guard);
        assert!(rt.get(0, &guard).is_none());

        let k2 = 321 << FANFACTOR;
        let k3 = k2 + 1;

        let v2 = Owned::new(2).into_shared(&guard);
        rt.cas(k2, Shared::null(), v2, &guard).unwrap();
        assert_eq!(rt.get(k2, &guard).unwrap().deref(), &2);
        assert!(rt.get(k3, &guard).is_none());
        let v3 = Owned::new(3).into_shared(&guard);
        rt.cas(k3, Shared::null(), v3, &guard).unwrap();
        assert_eq!(rt.get(k3, &guard).unwrap().deref(), &3);
        assert_eq!(rt.get(k2, &guard).unwrap().deref(), &2);
    }
}

#[test]
#[ignore]
fn test_model() {
    use self::Shared as EpochShared;
    use model::{model, prop_oneof};

    model! {
        Model => let mut m = std::collections::HashMap::new(),
        Implementation => let i = PageTable::default(),
        Insert((u64, u64))((k, new) in (0u64..4, 0u64..4)) => {
            if !m.contains_key(&k) {
                m.insert(k, new);

                let guard = pin();
                let v = Owned::new(new).into_shared(&guard);
                i.cas(k, EpochShared::null(), v, &guard ).expect("should be able to insert a value");
            }
        },
        Get(u64)(k in 0u64..4) => {
            let guard = pin();
            let expected = m.get(&k);
            let actual = i.get(k, &guard).map(|s| unsafe { s.deref() });
            assert_eq!(expected, actual);
        },
        Cas((u64, u64, u64))((k, old, new) in (0u64..4, 0u64..4, 0u64..4)) => {
            let guard = pin();
            let expected_current = m.get(&k).cloned();
            let actual_current = i.get(k, &guard);
            assert_eq!(expected_current, actual_current.map(|s| unsafe { *s.deref() }));
            if expected_current.is_none() {
                continue;
            }

            let new_v = Owned::new(new).into_shared(&guard);

            if expected_current == Some(old) {
                m.insert(k, new);
                let cas_res = i.cas(k, actual_current.unwrap(), new_v, &guard);
                assert!(cas_res.is_ok());
            };
        }
    }
}

#[test]
#[ignore]
fn test_linearizability() {
    use self::Shared as EpochShared;
    use model::{linearizable, prop_oneof, Shared};

    linearizable! {
        Implementation => let i = Shared::new(PageTable::default()),
        Get(u64)(k in 0u64..4) -> Option<u64> {
            let guard = pin();
            unsafe {
                i.get(k, &guard).map(|s| *s.deref())
            }
        },
        Insert((u64, u64))((k, new) in (0u64..4, 0u64..4)) -> bool {
            let guard = pin();
            let v = Owned::new(new).into_shared(&guard);
            i.cas(k, EpochShared::null(), v, &guard).is_err()
        },
        Cas((u64, u64, u64))((k, old, new)
            in (0u64..4, 0u64..4, 0u64..4))
            -> std::result::Result<(), u64> {
            let guard = pin();
            i.cas(k, Owned::new(old).into_shared(&guard), Owned::new(new).into_shared(&guard), &guard)
                .map(|_| ())
                .map_err(|s| if s.is_null() {
                    0
                } else {
                    unsafe { *s.deref() }
                })
        }
    }
}
<|endoftext|>


<commit_before>//! This module contains an import search funcionality that is provided to the ra_assists module.
//! Later, this should be moved away to a separate crate that is accessible from the ra_assists module.

use hir::{db::HirDatabase, ModuleDef, SourceBinder};
use ra_assists::ImportsLocator;
use ra_ide_db::{
    symbol_index::{self, FileSymbol},
    RootDatabase,
};
use ra_prof::profile;
use ra_syntax::{ast, AstNode, SyntaxKind::NAME};

use crate::{
    references::{classify_name, NameDefinition, NameKind},
    Query,
};

pub(crate) struct ImportsLocatorIde<'a> {
    source_binder: SourceBinder<'a, RootDatabase>,
}

impl<'a> ImportsLocatorIde<'a> {
    pub(crate) fn new(db: &'a RootDatabase) -> Self {
        Self { source_binder: SourceBinder::new(db) }
    }

    fn get_name_definition(
        &mut self,
        db: &impl HirDatabase,
        import_candidate: &FileSymbol,
    ) -> Option<NameDefinition> {
        let _p = profile("get_name_definition");
        let file_id = import_candidate.file_id.into();
        let candidate_node = import_candidate.ptr.to_node(&db.parse_or_expand(file_id)?);
        let candidate_name_node = if candidate_node.kind() != NAME {
            candidate_node.children().find(|it| it.kind() == NAME)?
        } else {
            candidate_node
        };
        classify_name(
            &mut self.source_binder,
            hir::InFile { file_id, value: &ast::Name::cast(candidate_name_node)? },
        )
    }
}

impl ImportsLocator for ImportsLocatorIde<'_> {
    fn find_imports(&mut self, name_to_import: &str) -> Vec<ModuleDef> {
        let _p = profile("search_for_imports");
        let db = self.source_binder.db;

        let project_results = {
            let mut query = Query::new(name_to_import.to_string());
            query.exact();
            query.limit(40);
            symbol_index::world_symbols(db, query)
        };
        let lib_results = {
            let mut query = Query::new(name_to_import.to_string());
            query.libs();
            query.exact();
            query.limit(40);
            symbol_index::world_symbols(db, query)
        };

        project_results
            .into_iter()
            .chain(lib_results.into_iter())
            .filter_map(|import_candidate| self.get_name_definition(db, &import_candidate))
            .filter_map(|name_definition_to_import| match name_definition_to_import.kind {
                NameKind::Def(module_def) => Some(module_def),
                _ => None,
            })
            .collect()
    }
}
<commit_msg>Simplify<commit_after>//! This module contains an import search funcionality that is provided to the ra_assists module.
//! Later, this should be moved away to a separate crate that is accessible from the ra_assists module.

use hir::{db::HirDatabase, ModuleDef, SourceBinder};
use ra_assists::ImportsLocator;
use ra_ide_db::{
    symbol_index::{self, FileSymbol},
    RootDatabase,
};
use ra_prof::profile;
use ra_syntax::{ast, AstNode, SyntaxKind::NAME};

use crate::{
    references::{classify_name, NameKind},
    Query,
};

pub(crate) struct ImportsLocatorIde<'a> {
    source_binder: SourceBinder<'a, RootDatabase>,
}

impl<'a> ImportsLocatorIde<'a> {
    pub(crate) fn new(db: &'a RootDatabase) -> Self {
        Self { source_binder: SourceBinder::new(db) }
    }

    fn get_name_definition(
        &mut self,
        db: &impl HirDatabase,
        import_candidate: &FileSymbol,
    ) -> Option<NameKind> {
        let _p = profile("get_name_definition");
        let file_id = import_candidate.file_id.into();
        let candidate_node = import_candidate.ptr.to_node(&db.parse_or_expand(file_id)?);
        let candidate_name_node = if candidate_node.kind() != NAME {
            candidate_node.children().find(|it| it.kind() == NAME)?
        } else {
            candidate_node
        };
        classify_name(
            &mut self.source_binder,
            hir::InFile { file_id, value: &ast::Name::cast(candidate_name_node)? },
        )
        .map(|it| it.kind)
    }
}

impl ImportsLocator for ImportsLocatorIde<'_> {
    fn find_imports(&mut self, name_to_import: &str) -> Vec<ModuleDef> {
        let _p = profile("search_for_imports");
        let db = self.source_binder.db;

        let project_results = {
            let mut query = Query::new(name_to_import.to_string());
            query.exact();
            query.limit(40);
            symbol_index::world_symbols(db, query)
        };
        let lib_results = {
            let mut query = Query::new(name_to_import.to_string());
            query.libs();
            query.exact();
            query.limit(40);
            symbol_index::world_symbols(db, query)
        };

        project_results
            .into_iter()
            .chain(lib_results.into_iter())
            .filter_map(|import_candidate| self.get_name_definition(db, &import_candidate))
            .filter_map(|name_definition_to_import| match name_definition_to_import {
                NameKind::Def(module_def) => Some(module_def),
                _ => None,
            })
            .collect()
    }
}
<|endoftext|>