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

/// The `TimerMode` is used to determine what time should the `Timer` return,
/// either a fixed value (in the `Test` mode), or the actual time (in the
/// `Current` mode).
#[derive(Debug, Clone)]
enum TimerMode {
    Test(f64),
    Current,
}

/// A `Timer` struct that takes care of giving the current time for animations.
///
/// This is needed to be allowed to hook the time in the animations' test-mode.
#[derive(Debug, Clone)]
pub struct Timer {
    mode: TimerMode,
}

impl Timer {
    /// Creates a new "normal" timer, i.e., a "Current" mode timer.
    #[inline]
    pub fn new() -> Self {
        Timer {
            mode: TimerMode::Current,
        }
    }

    /// Creates a new "test mode" timer, with initial time 0.
    #[inline]
    pub fn test_mode() -> Self {
        Timer {
            mode: TimerMode::Test(0.),
        }
    }

    /// Returns the current time, at least from the caller's perspective. In
    /// test mode returns whatever the value is.
    pub fn seconds(&self) -> f64 {
        match self.mode {
            TimerMode::Test(test_value) => test_value,
            TimerMode::Current => time::precise_time_s(),
        }
    }

    /// Increments the current clock. Panics if the clock is not on test mode.
    pub fn increment(&mut self, by: f64) {
        match self.mode {
            TimerMode::Test(ref mut val)
                => *val += by,
            TimerMode::Current
                => panic!("Timer::increment called for a non-test mode timer. This is a bug."),
        }
    }
}
<commit_msg>style: Document the timer module.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![deny(missing_docs)]

//! A timer module, used to define a `Timer` type, that is controlled by script.

use time;

/// The `TimerMode` is used to determine what time should the `Timer` return.
#[derive(Debug, Clone)]
enum TimerMode {
    /// The timer should return a fixed value.
    Test(f64),
    /// The timer should return the actual time.
    Current,
}

/// A `Timer` struct that takes care of giving the current time for animations.
///
/// This is needed to be allowed to hook the time in the animations' test-mode.
#[derive(Debug, Clone)]
pub struct Timer {
    mode: TimerMode,
}

impl Timer {
    /// Creates a new "normal" timer, i.e., a "Current" mode timer.
    #[inline]
    pub fn new() -> Self {
        Timer {
            mode: TimerMode::Current,
        }
    }

    /// Creates a new "test mode" timer, with initial time 0.
    #[inline]
    pub fn test_mode() -> Self {
        Timer {
            mode: TimerMode::Test(0.),
        }
    }

    /// Returns the current time, at least from the caller's perspective. In
    /// test mode returns whatever the value is.
    pub fn seconds(&self) -> f64 {
        match self.mode {
            TimerMode::Test(test_value) => test_value,
            TimerMode::Current => time::precise_time_s(),
        }
    }

    /// Increments the current clock. Panics if the clock is not on test mode.
    pub fn increment(&mut self, by: f64) {
        match self.mode {
            TimerMode::Test(ref mut val)
                => *val += by,
            TimerMode::Current
                => panic!("Timer::increment called for a non-test mode timer. This is a bug."),
        }
    }
}
<|endoftext|>


<commit_before>//! A simple X11 status bar for use with simple WMs.
//!
//! Cnx is written to be customisable, simple and fast. Where possible, it
//! prefers to asynchronously wait for changes in the underlying data sources
//! (and uses [`mio`]/[`tokio`] to achieve this), rather than periodically
//! calling out to external programs.
//!
//! # How to use
//!
//! Cnx is a library that allows you to make your own status bar.
//!
//! In normal usage, you will create a new binary project that relies on the
//! `cnx` crate, and customize it through options passed to the main [`Cnx`]
//! object and its widgets. (It's inspired by [`QTile`] and [`dwm`], in that the
//! configuration is done entirely in code, allowing greater extensibility
//! without needing complex configuration handling).
//!
//! An simple example of a binary using Cnx is:
//!
//! ```no_run
//!
//! use cnx::text::*;
//! use cnx::widgets::*;
//! use cnx::{Cnx, Position};
//! use anyhow::Result;
//!
//! fn main() -> Result<()> {
//!     let attr = Attributes {
//!         font: Font::new("Envy Code R 21"),
//!         fg_color: Color::white(),
//!         bg_color: None,
//!         padding: Padding::new(8.0, 8.0, 0.0, 0.0),
//!     };
//!
//!     let mut cnx = Cnx::new(Position::Top);
//!     cnx.add_widget(ActiveWindowTitle::new(attr.clone()));
//!     cnx.add_widget(Clock::new(attr.clone(), None));
//!     cnx.run()?;
//!
//!     Ok(())
//! }
//! ```
//!
//! A more complex example is given in [`src/bin/cnx.rs`] alongside the project.
//! (This is the default `[bin]` target for the crate, so you _could_ use it by
//! either executing `cargo run` from the crate root, or even running `cargo
//! install cnx; cnx`. However, neither of these are recommended as options for
//! customizing Cnx are then limited).
//!
//! Before running Cnx, you'll need to make sure your system has the required
//! dependencies, which are described in the [`README`][readme-deps].
//!
//! # Built-in widgets
//!
//! There are currently these widgets available:
//!
//! - [`crate::widgets::ActiveWindowTitle`] — Shows the title ([`EWMH`]'s `_NET_WM_NAME`) for
//!   the currently focused window ([`EWMH`]'s `_NEW_ACTIVE_WINDOW`).
//! - [`crate::widgets::Pager`] — Shows the WM's workspaces/groups, highlighting whichever is
//!   currently active. (Uses [`EWMH`]'s `_NET_DESKTOP_NAMES`,
//!   `_NET_NUMBER_OF_DESKTOPS` and `_NET_CURRENT_DESKTOP`).
//! - [`crate::widgets::Clock`] — Shows the time.
//!
//! The cnx-contrib crate contains additional widgets:
//!
//! - **Sensors** — Periodically parses and displays the output of the
//!   sensors provided by the system.
//! - **Volume** - Shows the current volume/mute status of the default output
//!   device.
//! - **Battery** - Shows the remaining battery and charge status.
//! - **Wireless** - Shows the wireless strength of your current network.
//! - **CPU** - Shows the current CPU consumption
//! - **Weather** - Shows the Weather information of your location
//! - **Disk Usage** - Show the current usage of your monted filesystem
//!
//! The Sensors, Volume and Battery widgets require platform
//! support. They currently support Linux (see dependencies below) and OpenBSD.
//! Support for additional platforms should be possible.
//!
//! # Dependencies
//!
//! In addition to the Rust dependencies in `Cargo.toml`, Cnx also depends on
//! these system libraries:
//!
//!  - `xcb-util`: `xcb-ewmh` / `xcb-icccm` / `xcb-keysyms`
//!  - `x11-xcb`
//!  - `pango`
//!  - `cairo`
//!  - `pangocairo`
//!
//! Some widgets have additional dependencies on Linux:
//!
//!  - **Volume** widget relies on `alsa-lib`
//!  - **Sensors** widget relies on [`lm_sensors`] being installed.
//!  - **Wireless** widget relies on `libiw-dev`.
//!
//! # Creating new widgets
//!
//! Cnx is designed such that thirdparty widgets can be written in external
//! crates and used with the main [`Cnx`] instance. However, I've never done
//! this.
//!
//! The adventurous may choose to implement the [`Widget`] trait and see how
//! far they can get. The [`Widget`] implementation can assume it's being run
//! from a single-threaded [`tokio`] event-loop, but this is an implementation
//! detail that should not be relied upon.
//!
//! The built-in [`widgets`] should give you some examples on which to base
//! your work.
//!
//! [`mio`]: https://docs.rs/mio
//! [`tokio`]: https://tokio.rs/
//! [`QTile`]: http://www.qtile.org/
//! [`dwm`]: http://dwm.suckless.org/
//! [readme-deps]: https://github.com/mjkillough/cnx/blob/master/README.md#dependencies
//! [`src/bin/cnx.rs`]: https://github.com/mjkillough/cnx/blob/master/src/bin/cnx.rs
//! [`EWMH`]: https://specifications.freedesktop.org/wm-spec/wm-spec-latest.html
//! [`lm_sensors`]: https://wiki.archlinux.org/index.php/lm_sensors

#![recursion_limit = "256"]

mod bar;
pub mod text;
pub mod widgets;
mod xcb;

use anyhow::Result;
use tokio::runtime::Runtime;
use tokio::task;
use tokio_stream::{StreamExt, StreamMap};

use crate::bar::Bar;
use crate::widgets::Widget;
use crate::xcb::XcbEventStream;

pub use bar::Position;

/// The main object, used to instantiate an instance of Cnx.
///
/// Widgets can be added using the [`add_widget()`] method. Once configured,
/// the [`run()`] method will take ownership of the instance and run it until
/// the process is killed or an error occurs.
///
/// [`add_widget()`]: #method.add_widget
/// [`run()`]: #method.run
pub struct Cnx {
    position: Position,
    widgets: Vec<Box<dyn Widget>>,
}

impl Cnx {
    /// Creates a new `Cnx` instance.
    ///
    /// This creates a new `Cnx` instance at either the top or bottom of the
    /// screen, depending on the value of the [`Position`] enum.
    ///
    /// [`Position`]: enum.Position.html
    pub fn new(position: Position) -> Self {
        let widgets = Vec::new();
        Self { position, widgets }
    }

    /// Adds a widget to the `Cnx` instance.
    ///
    /// Takes ownership of the [`Widget`] and adds it to the Cnx instance to
    /// the right of any existing widgets.
    ///
    /// [`Widget`]: widgets/trait.Widget.html
    pub fn add_widget<W>(&mut self, widget: W)
    where
        W: Widget + 'static,
    {
        self.widgets.push(Box::new(widget));
    }

    /// Runs the Cnx instance.
    ///
    /// This method takes ownership of the Cnx instance and runs it until either
    /// the process is terminated, or an internal error is returned.
    pub fn run(self) -> Result<()> {
        // Use a single-threaded event loop. We aren't interested in
        // performance too much, so don't mind if we block the loop
        // occasionally. We are using events to get woken up as
        // infrequently as possible (to save battery).
        let rt = Runtime::new()?;
        let local = task::LocalSet::new();
        local.block_on(&rt, self.run_inner())?;
        Ok(())
    }

    async fn run_inner(self) -> Result<()> {
        let mut bar = Bar::new(self.position)?;

        let mut widgets = StreamMap::with_capacity(self.widgets.len());
        for widget in self.widgets {
            let idx = bar.add_content(Vec::new())?;
            widgets.insert(idx, widget.into_stream()?);
        }

        let mut event_stream = XcbEventStream::new(bar.connection().clone())?;
        task::spawn_local(async move {
            loop {
                tokio::select! {
                    // Pass each XCB event to the Bar.
                    Some(event) = event_stream.next() => {
                        if let Err(err) = bar.process_event(event) {
                            println!("Error processing XCB event: {}", err);
                        }
                    },

                    // Each time a widget yields new values, pass to the bar.
                    // Ignore (but log) any errors from widgets.
                    Some((idx, result)) = widgets.next() => {
                        match result {
                            Err(err) => println!("Error from widget {}: {}", idx, err),
                            Ok(texts) => {
                                if let Err(err) = bar.update_content(idx, texts) {
                                    println!("Error updating widget {}: {}", idx, err);
                                }
                            }
                        }
                    }
                }
            }
        })
        .await?;

        Ok(())
    }
}
<commit_msg>Update documentation<commit_after>//! A simple X11 status bar for use with simple WMs.
//!
//! Cnx is written to be customisable, simple and fast. Where possible, it
//! prefers to asynchronously wait for changes in the underlying data sources
//! (and uses [`mio`]/[`tokio`] to achieve this), rather than periodically
//! calling out to external programs.
//!
//! # How to use
//!
//! Cnx is a library that allows you to make your own status bar.
//!
//! In normal usage, you will create a new binary project that relies on the
//! `cnx` crate, and customize it through options passed to the main [`Cnx`]
//! object and its widgets. (It's inspired by [`QTile`] and [`dwm`], in that the
//! configuration is done entirely in code, allowing greater extensibility
//! without needing complex configuration handling).
//!
//! An simple example of a binary using Cnx is:
//!
//! ```no_run
//!
//! use cnx::text::*;
//! use cnx::widgets::*;
//! use cnx::{Cnx, Position};
//! use anyhow::Result;
//!
//! fn main() -> Result<()> {
//!     let attr = Attributes {
//!         font: Font::new("Envy Code R 21"),
//!         fg_color: Color::white(),
//!         bg_color: None,
//!         padding: Padding::new(8.0, 8.0, 0.0, 0.0),
//!     };
//!
//!     let mut cnx = Cnx::new(Position::Top);
//!     cnx.add_widget(ActiveWindowTitle::new(attr.clone()));
//!     cnx.add_widget(Clock::new(attr.clone(), None));
//!     cnx.run()?;
//!
//!     Ok(())
//! }
//! ```
//!
//! A more complex example is given in [`cnx-bin/src/main.rs`] alongside the project.
//! (This is the default `[bin]` target for the crate, so you _could_ use it by
//! either executing `cargo run` from the crate root, or even running `cargo
//! install cnx; cnx`. However, neither of these are recommended as options for
//! customizing Cnx are then limited).
//!
//! Before running Cnx, you'll need to make sure your system has the required
//! dependencies, which are described in the [`README`][readme-deps].
//!
//! # Built-in widgets
//!
//! There are currently these widgets available:
//!
//! - [`crate::widgets::ActiveWindowTitle`] — Shows the title ([`EWMH`]'s `_NET_WM_NAME`) for
//!   the currently focused window ([`EWMH`]'s `_NEW_ACTIVE_WINDOW`).
//! - [`crate::widgets::Pager`] — Shows the WM's workspaces/groups, highlighting whichever is
//!   currently active. (Uses [`EWMH`]'s `_NET_DESKTOP_NAMES`,
//!   `_NET_NUMBER_OF_DESKTOPS` and `_NET_CURRENT_DESKTOP`).
//! - [`crate::widgets::Clock`] — Shows the time.
//!
//! The cnx-contrib crate contains additional widgets:
//!
//! - **Sensors** — Periodically parses and displays the output of the
//!   sensors provided by the system.
//! - **Volume** - Shows the current volume/mute status of the default output
//!   device.
//! - **Battery** - Shows the remaining battery and charge status.
//! - **Wireless** - Shows the wireless strength of your current network.
//! - **CPU** - Shows the current CPU consumption
//! - **Weather** - Shows the Weather information of your location
//! - **Disk Usage** - Show the current usage of your monted filesystem
//!
//! The Sensors, Volume and Battery widgets require platform
//! support. They currently support Linux (see dependencies below) and OpenBSD.
//! Support for additional platforms should be possible.
//!
//! # Dependencies
//!
//! In addition to the Rust dependencies in `Cargo.toml`, Cnx also depends on
//! these system libraries:
//!
//!  - `xcb-util`: `xcb-ewmh` / `xcb-icccm` / `xcb-keysyms`
//!  - `x11-xcb`
//!  - `pango`
//!  - `cairo`
//!  - `pangocairo`
//!
//! Some widgets have additional dependencies on Linux:
//!
//!  - **Volume** widget relies on `alsa-lib`
//!  - **Sensors** widget relies on [`lm_sensors`] being installed.
//!  - **Wireless** widget relies on `libiw-dev`.
//!
//! # Creating new widgets
//!
//! Cnx is designed such that thirdparty widgets can be written in
//! external crates and used with the main [`Cnx`] instance. We have
//! [`cnx-contrib`] crate which contains various additional
//! widgets. You can also create new crates or add it to the existing
//! [`cnx-contrib`] crate.
//!
//! The built-in [`widgets`] should give you some examples on which to base
//! your work.
//!
//! [`mio`]: https://docs.rs/mio
//! [`tokio`]: https://tokio.rs/
//! [`QTile`]: http://www.qtile.org/
//! [`dwm`]: http://dwm.suckless.org/
//! [readme-deps]: https://github.com/mjkillough/cnx/blob/master/README.md#dependencies
//! [`cnx-bin/src/main.rs`]: https://github.com/mjkillough/cnx/blob/master/cnx-bin/src/main.rs
//! [`EWMH`]: https://specifications.freedesktop.org/wm-spec/wm-spec-latest.html
//! [`lm_sensors`]: https://wiki.archlinux.org/index.php/lm_sensors
//! [`cnx-contrib`]: https://github.com/mjkillough/cnx/tree/master/cnx-contrib

#![recursion_limit = "256"]

mod bar;
pub mod text;
pub mod widgets;
mod xcb;

use anyhow::Result;
use tokio::runtime::Runtime;
use tokio::task;
use tokio_stream::{StreamExt, StreamMap};

use crate::bar::Bar;
use crate::widgets::Widget;
use crate::xcb::XcbEventStream;

pub use bar::Position;

/// The main object, used to instantiate an instance of Cnx.
///
/// Widgets can be added using the [`add_widget()`] method. Once configured,
/// the [`run()`] method will take ownership of the instance and run it until
/// the process is killed or an error occurs.
///
/// [`add_widget()`]: #method.add_widget
/// [`run()`]: #method.run
pub struct Cnx {
    position: Position,
    widgets: Vec<Box<dyn Widget>>,
}

impl Cnx {
    /// Creates a new `Cnx` instance.
    ///
    /// This creates a new `Cnx` instance at either the top or bottom of the
    /// screen, depending on the value of the [`Position`] enum.
    ///
    /// [`Position`]: enum.Position.html
    pub fn new(position: Position) -> Self {
        let widgets = Vec::new();
        Self { position, widgets }
    }

    /// Adds a widget to the `Cnx` instance.
    ///
    /// Takes ownership of the [`Widget`] and adds it to the Cnx instance to
    /// the right of any existing widgets.
    ///
    /// [`Widget`]: widgets/trait.Widget.html
    pub fn add_widget<W>(&mut self, widget: W)
    where
        W: Widget + 'static,
    {
        self.widgets.push(Box::new(widget));
    }

    /// Runs the Cnx instance.
    ///
    /// This method takes ownership of the Cnx instance and runs it until either
    /// the process is terminated, or an internal error is returned.
    pub fn run(self) -> Result<()> {
        // Use a single-threaded event loop. We aren't interested in
        // performance too much, so don't mind if we block the loop
        // occasionally. We are using events to get woken up as
        // infrequently as possible (to save battery).
        let rt = Runtime::new()?;
        let local = task::LocalSet::new();
        local.block_on(&rt, self.run_inner())?;
        Ok(())
    }

    async fn run_inner(self) -> Result<()> {
        let mut bar = Bar::new(self.position)?;

        let mut widgets = StreamMap::with_capacity(self.widgets.len());
        for widget in self.widgets {
            let idx = bar.add_content(Vec::new())?;
            widgets.insert(idx, widget.into_stream()?);
        }

        let mut event_stream = XcbEventStream::new(bar.connection().clone())?;
        task::spawn_local(async move {
            loop {
                tokio::select! {
                    // Pass each XCB event to the Bar.
                    Some(event) = event_stream.next() => {
                        if let Err(err) = bar.process_event(event) {
                            println!("Error processing XCB event: {}", err);
                        }
                    },

                    // Each time a widget yields new values, pass to the bar.
                    // Ignore (but log) any errors from widgets.
                    Some((idx, result)) = widgets.next() => {
                        match result {
                            Err(err) => println!("Error from widget {}: {}", idx, err),
                            Ok(texts) => {
                                if let Err(err) = bar.update_content(idx, texts) {
                                    println!("Error updating widget {}: {}", idx, err);
                                }
                            }
                        }
                    }
                }
            }
        })
        .await?;

        Ok(())
    }
}
<|endoftext|>


<commit_before>use hermes::stm::Txn;
use hermes::stm::TxnErr;
use hermes::stm::TxnValRef;
use index::btree::Slice;
use index::btree::*;
use itertools::free::chain;
use std::cell::UnsafeCell;
use std::mem;
use std::sync::atomic::AtomicPtr;
use std::sync::Arc;

pub struct InNode {
    pub keys: EntryKeySlice,
    pub ptrs: NodePtrCellSlice,
    pub len: usize,
    pub right: NodeCellRef,
}

pub struct InNodeKeysSplit {
    pub keys_2: EntryKeySlice,
    pub keys_1_len: usize,
    pub keys_2_len: usize,
    pub pivot_key: EntryKey,
}

pub struct InNodePtrSplit {
    pub ptrs_2: NodePtrCellSlice,
}

impl InNode {
    pub fn key_pos_from_ptr_pos(&self, ptr_pos: usize) -> usize {
        if ptr_pos == 0 {
            0
        } else {
            ptr_pos - 1
        }
    }
    pub fn search(&self, key: &EntryKey) -> usize {
        self.keys[..self.len]
            .binary_search(key)
            .map(|i| i + 1)
            .unwrap_or_else(|i| i)
    }
    pub fn remove_at(&mut self, ptr_pos: usize) {
        let mut n_key_len = self.len;
        let mut n_ptr_len = n_key_len + 1;
        let key_pos = self.key_pos_from_ptr_pos(ptr_pos);
        debug!(
            "Removing from internal node pos {}, len {}",
            key_pos, n_key_len
        );
        self.keys.remove_at(key_pos, &mut n_key_len);
        self.ptrs.remove_at(ptr_pos, &mut n_ptr_len);
        self.len = n_key_len;
    }
    pub fn insert(
        &mut self,
        key: EntryKey,
        new_node: NodeCellRef,
        parent: &NodeCellRef,
    ) -> Option<NodeSplit> {
        let node_len = self.len;
        let ptr_len = self.len + 1;
        let pos = self.search(&key);
        debug!("Insert into internal node at {}, key: {:?}", pos, key);
        debug_assert!(node_len <= NUM_KEYS);
        if node_len == NUM_KEYS {
            let pivot = node_len / 2; // pivot key will be removed
            debug!("Going to split at pivot {}", pivot);
            let parent_guard = parent.write();
            let keys_split = {
                debug!("insert into keys");
                if pivot == pos {
                    debug!("special key treatment when pivot == pos");
                    let mut keys_1 = &mut self.keys;
                    let mut keys_2 = keys_1.split_at_pivot(pivot, node_len);
                    let mut keys_1_len = pivot;
                    let mut keys_2_len = node_len - pivot;
                    let pivot_key = key;
                    InNodeKeysSplit {
                        keys_2,
                        keys_1_len,
                        keys_2_len,
                        pivot_key,
                    }
                } else {
                    let mut keys_1 = &mut self.keys;
                    let mut keys_2 = keys_1.split_at_pivot(pivot + 1, node_len);
                    let mut keys_1_len = pivot; // will not count the pivot
                    let mut keys_2_len = node_len - pivot - 1;
                    let mut key_pos = pos;
                    if pos > pivot {
                        // pivot moved, need to compensate
                        key_pos -= 1;
                    }
                    debug!(
                        "keys 1 len: {}, keys 2 len: {}, pos {}",
                        keys_1_len, keys_2_len, key_pos
                    );
                    debug_assert_ne!(pivot, pos);
                    let pivot_key = keys_1[pivot].to_owned();
                    insert_into_split(
                        key,
                        keys_1,
                        &mut keys_2,
                        &mut keys_1_len,
                        &mut keys_2_len,
                        key_pos,
                    );
                    InNodeKeysSplit {
                        keys_2,
                        keys_1_len,
                        keys_2_len,
                        pivot_key,
                    }
                }
            };
            let ptr_split = {
                if pivot == pos {
                    debug!("special ptr treatment when pivot == pos");
                    let mut ptrs_1 = &mut self.ptrs;
                    let mut ptrs_2 = ptrs_1.split_at_pivot(pivot + 1, ptr_len);
                    let mut ptrs_1_len = pivot + 1;
                    let mut ptrs_2_len = ptr_len - pivot - 1;
                    ptrs_2.insert_at(new_node, 0, &mut ptrs_2_len);
                    debug_assert_eq!(ptrs_1_len, keys_split.keys_1_len + 1);
                    debug_assert_eq!(ptrs_2_len, keys_split.keys_2_len + 1);
                    InNodePtrSplit { ptrs_2 }
                } else {
                    debug!("insert into ptrs");
                    let mut ptrs_1 = &mut self.ptrs;
                    let mut ptrs_2 = ptrs_1.split_at_pivot(pivot + 1, ptr_len);
                    let mut ptrs_1_len = pivot + 1;
                    let mut ptrs_2_len = ptr_len - pivot - 1;
                    let mut ptr_pos = pos + 1;
                    insert_into_split(
                        new_node,
                        ptrs_1,
                        &mut ptrs_2,
                        &mut ptrs_1_len,
                        &mut ptrs_2_len,
                        ptr_pos,
                    );
                    debug_assert_eq!(ptrs_1_len, keys_split.keys_1_len + 1);
                    debug_assert_eq!(ptrs_2_len, keys_split.keys_2_len + 1);
                    InNodePtrSplit { ptrs_2 }
                }
            };
            let node_2 = InNode {
                len: keys_split.keys_2_len,
                keys: keys_split.keys_2,
                ptrs: ptr_split.ptrs_2,
                right: self.right.clone(),
            };
            let node_2_ref = Arc::new(Node::internal(node_2));
            self.len = keys_split.keys_1_len;
            self.right = node_2_ref.clone();
            return Some(NodeSplit {
                new_right_node: node_2_ref,
                left_node_latch: NodeWriteGuard::default(),
                pivot: keys_split.pivot_key,
                parent_latch: parent_guard,
            });
        } else {
            let mut new_node_len = node_len;
            let mut new_node_pointers = node_len + 1;
            self.keys.insert_at(key, pos, &mut new_node_len);
            self.ptrs
                .insert_at(new_node, pos + 1, &mut new_node_pointers);
            self.len = new_node_len;
            return None;
        }
    }
    pub fn rebalance_candidate(&self, pointer_pos: usize) -> usize {
        debug_assert!(pointer_pos <= self.len);
        debug!(
            "Searching for rebalance candidate, pos {}, len {}",
            pointer_pos, self.len
        );
        if pointer_pos == 0 {
            1
        } else if pointer_pos + 1 >= self.len {
            // the last one, pick left
            pointer_pos - 1
        } else {
            // pick the right one
            // we should pick the one  with least pointers, but it cost for the check is too high
            pointer_pos + 1
        }
    }
    pub fn merge_children(
        &mut self,
        left_ptr_pos: usize,
        right_ptr_pos: usize,
        left_node: &mut NodeData,
        right_node: &mut NodeData,
        right_node_next: &mut NodeData,
    ) -> Result<(), TxnErr> {
        let left_node_ref = self.ptrs[left_ptr_pos].clone();
        let left_len = left_node.len();
        let right_len = right_node.len();
        let right_key_pos = self.key_pos_from_ptr_pos(right_ptr_pos);
        let mut merged_len = 0;
        debug!("Merge children, left len {}, right len {}, left_ptr_pos {}, right_ptr_pos {}, right_key_pos {}",
                left_len, right_len, left_ptr_pos, right_ptr_pos, right_key_pos);
        debug_assert_eq!(left_node.is_ext(), right_node.is_ext());
        if !left_node.is_ext() {
            {
                let mut left_innode = left_node.innode_mut();
                let mut right_innode = right_node.innode_mut();
                let right_key = self.keys[right_key_pos].clone();
                left_innode.merge_with(&mut right_innode, right_key);
                left_innode.right = right_innode.right.clone();
                merged_len = left_innode.len;
            }
        } else {
            let mut right_extnode = right_node.extnode_mut();
            let mut left_extnode = left_node.extnode_mut();
            {
                left_extnode.merge_with(&mut right_extnode);
                merged_len = left_extnode.len;
            }
            if !right_node_next.is_none() {
                right_node_next.extnode_mut().prev = left_node_ref
            }
            left_extnode.next = right_extnode.next.clone();
        }
        self.remove_at(right_ptr_pos);
        debug!(
            "Removing merged node at {}, left {}, right {}, merged {}",
            right_ptr_pos,left_len, right_len, merged_len
        );
        debug!("Merged parent level keys: {:?}", self.keys);
        debug!("Merged level keys {:?}", left_node.keys());
        Ok(())
    }
    pub fn merge_with(&mut self, right: &mut Self, right_key: EntryKey) {
        debug!(
            "Merge internal node, left len {}, right len {}, right_key {:?}",
            self.len, right.len, right_key
        );
        let mut self_len = self.len;
        let new_len = self_len + right.len + 1;
        debug_assert!(new_len <= self.keys.len());
        // moving keys
        self.keys[self_len] = right_key;
        for i in self_len + 1..new_len {
            mem::swap(&mut self.keys[i], &mut right.keys[i - self_len - 1]);
        }
        for i in self_len + 1..new_len + 1 {
            mem::swap(&mut self.ptrs[i], &mut right.ptrs[i - self_len - 1]);
        }
        self.len += right.len + 1;
    }
    pub fn relocate_children(
        &mut self,
        left_ptr_pos: usize,
        right_ptr_pos: usize,
        left_node: &mut NodeData,
        right_node: &mut NodeData,
    ) {
        debug_assert_ne!(left_ptr_pos, right_ptr_pos);
        let mut new_right_node_key = Default::default();
        let half_full_pos = (left_node.len() + right_node.len()) / 2;
        debug_assert_eq!(left_node.is_ext(), right_node.is_ext());
        if !left_node.is_ext() {
            // relocate internal sub nodes

            {
                let mut left_innode = left_node.innode_mut();
                let mut right_innode = right_node.innode_mut();

                debug!(
                    "Before relocation internal children. left {}:{:?} right {}:{:?}",
                    left_innode.len, left_innode.keys, right_innode.len, right_innode.keys
                );

                let mut new_left_keys = EntryKeySlice::init();
                let mut new_left_ptrs = NodePtrCellSlice::init();

                let mut new_right_keys = EntryKeySlice::init();
                let mut new_right_ptrs = NodePtrCellSlice::init();

                let pivot_key = self.keys[right_ptr_pos - 1].to_owned();
                let mut new_left_keys_len = 0;
                let mut new_right_keys_len = 0;
                debug_assert!(pivot_key > smallvec!(0));
                for (i, key) in chain(
                    chain(
                        left_innode.keys[..left_innode.len].iter_mut(),
                        [pivot_key].iter_mut(),
                    ),
                    right_innode.keys[..right_innode.len].iter_mut(),
                )
                .enumerate()
                {
                    let key_owned = mem::replace(key, Default::default());
                    if i < half_full_pos {
                        new_left_keys[i] = key_owned;
                        new_left_keys_len += 1;
                    } else if i == half_full_pos {
                        new_right_node_key = key_owned
                    } else {
                        let nk_index = i - half_full_pos - 1;
                        new_right_keys[nk_index] = key_owned;
                        new_right_keys_len += 1;
                    }
                }

                for (i, ptr) in chain(
                    left_innode.ptrs[..left_innode.len + 1].iter_mut(),
                    right_innode.ptrs[..right_innode.len + 1].iter_mut(),
                )
                .enumerate()
                {
                    let ptr_owned = mem::replace(ptr, Default::default());
                    if i < half_full_pos + 1 {
                        new_left_ptrs[i] = ptr_owned;
                    } else {
                        new_right_ptrs[i - half_full_pos - 1] = ptr_owned;
                    }
                }

                left_innode.keys = new_left_keys;
                left_innode.ptrs = new_left_ptrs;
                left_innode.len = new_left_keys_len;

                right_innode.keys = new_right_keys;
                right_innode.ptrs = new_right_ptrs;
                right_innode.len = new_right_keys_len;

                debug!(
                    "Relocated internal children. left {}:{:?} right {}:{:?}",
                    left_innode.len, left_innode.keys, right_innode.len, right_innode.keys
                );
            }
        } else if left_node.is_ext() {
            // relocate external sub nodes

            let mut left_extnode = left_node.extnode_mut();
            let mut right_extnode = right_node.extnode_mut();

            debug!(
                "Before relocation external children. left {}:{:?} right {}:{:?}",
                left_extnode.len, left_extnode.keys, right_extnode.len, right_extnode.keys
            );

            let mut new_left_keys = EntryKeySlice::init();
            let mut new_right_keys = EntryKeySlice::init();

            let left_len = left_extnode.len;
            let right_len = right_extnode.len;
            let mut new_left_keys_len = 0;
            let mut new_right_keys_len = 0;
            for (i, key) in chain(
                left_extnode.keys[..left_len].iter_mut(),
                right_extnode.keys[..right_len].iter_mut(),
            )
            .enumerate()
            {
                let key_owned = mem::replace(key, Default::default());
                if i < half_full_pos {
                    new_left_keys[i] = key_owned;
                    new_left_keys_len += 1;
                } else {
                    new_right_keys[i - half_full_pos] = key_owned;
                    new_right_keys_len += 1;
                }
            }

            new_right_node_key = new_right_keys[0].clone();

            left_extnode.keys = new_left_keys;
            left_extnode.len = new_left_keys_len;

            right_extnode.keys = new_right_keys;
            right_extnode.len = new_right_keys_len;

            debug!(
                "Relocated external children. left {}:{:?} right {}:{:?}",
                left_extnode.len, left_extnode.keys, right_extnode.len, right_extnode.keys
            );
        }

        let right_key_pos = right_ptr_pos - 1;
        debug!(
            "Setting key at pos {} to new key {:?}",
            right_key_pos, new_right_node_key
        );
        debug_assert!(new_right_node_key > smallvec!(0));
        self.keys[right_key_pos] = new_right_node_key;
    }
}
<commit_msg>use swap instead of empty instances<commit_after>use hermes::stm::Txn;
use hermes::stm::TxnErr;
use hermes::stm::TxnValRef;
use index::btree::Slice;
use index::btree::*;
use itertools::free::chain;
use std::cell::UnsafeCell;
use std::mem;
use std::sync::atomic::AtomicPtr;
use std::sync::Arc;

pub struct InNode {
    pub keys: EntryKeySlice,
    pub ptrs: NodePtrCellSlice,
    pub len: usize,
    pub right: NodeCellRef,
}

pub struct InNodeKeysSplit {
    pub keys_2: EntryKeySlice,
    pub keys_1_len: usize,
    pub keys_2_len: usize,
    pub pivot_key: EntryKey,
}

pub struct InNodePtrSplit {
    pub ptrs_2: NodePtrCellSlice,
}

impl InNode {
    pub fn key_pos_from_ptr_pos(&self, ptr_pos: usize) -> usize {
        if ptr_pos == 0 {
            0
        } else {
            ptr_pos - 1
        }
    }
    pub fn search(&self, key: &EntryKey) -> usize {
        self.keys[..self.len]
            .binary_search(key)
            .map(|i| i + 1)
            .unwrap_or_else(|i| i)
    }
    pub fn remove_at(&mut self, ptr_pos: usize) {
        let mut n_key_len = self.len;
        let mut n_ptr_len = n_key_len + 1;
        let key_pos = self.key_pos_from_ptr_pos(ptr_pos);
        debug!(
            "Removing from internal node pos {}, len {}",
            key_pos, n_key_len
        );
        self.keys.remove_at(key_pos, &mut n_key_len);
        self.ptrs.remove_at(ptr_pos, &mut n_ptr_len);
        self.len = n_key_len;
    }
    pub fn insert(
        &mut self,
        key: EntryKey,
        new_node: NodeCellRef,
        parent: &NodeCellRef,
    ) -> Option<NodeSplit> {
        let node_len = self.len;
        let ptr_len = self.len + 1;
        let pos = self.search(&key);
        debug!("Insert into internal node at {}, key: {:?}", pos, key);
        debug_assert!(node_len <= NUM_KEYS);
        if node_len == NUM_KEYS {
            let pivot = node_len / 2; // pivot key will be removed
            debug!("Going to split at pivot {}", pivot);
            let parent_guard = parent.write();
            let keys_split = {
                debug!("insert into keys");
                if pivot == pos {
                    debug!("special key treatment when pivot == pos");
                    let mut keys_1 = &mut self.keys;
                    let mut keys_2 = keys_1.split_at_pivot(pivot, node_len);
                    let mut keys_1_len = pivot;
                    let mut keys_2_len = node_len - pivot;
                    let pivot_key = key;
                    InNodeKeysSplit {
                        keys_2,
                        keys_1_len,
                        keys_2_len,
                        pivot_key,
                    }
                } else {
                    let mut keys_1 = &mut self.keys;
                    let mut keys_2 = keys_1.split_at_pivot(pivot + 1, node_len);
                    let mut keys_1_len = pivot; // will not count the pivot
                    let mut keys_2_len = node_len - pivot - 1;
                    let mut key_pos = pos;
                    if pos > pivot {
                        // pivot moved, need to compensate
                        key_pos -= 1;
                    }
                    debug!(
                        "keys 1 len: {}, keys 2 len: {}, pos {}",
                        keys_1_len, keys_2_len, key_pos
                    );
                    debug_assert_ne!(pivot, pos);
                    let pivot_key = keys_1[pivot].to_owned();
                    insert_into_split(
                        key,
                        keys_1,
                        &mut keys_2,
                        &mut keys_1_len,
                        &mut keys_2_len,
                        key_pos,
                    );
                    InNodeKeysSplit {
                        keys_2,
                        keys_1_len,
                        keys_2_len,
                        pivot_key,
                    }
                }
            };
            let ptr_split = {
                if pivot == pos {
                    debug!("special ptr treatment when pivot == pos");
                    let mut ptrs_1 = &mut self.ptrs;
                    let mut ptrs_2 = ptrs_1.split_at_pivot(pivot + 1, ptr_len);
                    let mut ptrs_1_len = pivot + 1;
                    let mut ptrs_2_len = ptr_len - pivot - 1;
                    ptrs_2.insert_at(new_node, 0, &mut ptrs_2_len);
                    debug_assert_eq!(ptrs_1_len, keys_split.keys_1_len + 1);
                    debug_assert_eq!(ptrs_2_len, keys_split.keys_2_len + 1);
                    InNodePtrSplit { ptrs_2 }
                } else {
                    debug!("insert into ptrs");
                    let mut ptrs_1 = &mut self.ptrs;
                    let mut ptrs_2 = ptrs_1.split_at_pivot(pivot + 1, ptr_len);
                    let mut ptrs_1_len = pivot + 1;
                    let mut ptrs_2_len = ptr_len - pivot - 1;
                    let mut ptr_pos = pos + 1;
                    insert_into_split(
                        new_node,
                        ptrs_1,
                        &mut ptrs_2,
                        &mut ptrs_1_len,
                        &mut ptrs_2_len,
                        ptr_pos,
                    );
                    debug_assert_eq!(ptrs_1_len, keys_split.keys_1_len + 1);
                    debug_assert_eq!(ptrs_2_len, keys_split.keys_2_len + 1);
                    InNodePtrSplit { ptrs_2 }
                }
            };
            let node_2 = InNode {
                len: keys_split.keys_2_len,
                keys: keys_split.keys_2,
                ptrs: ptr_split.ptrs_2,
                right: self.right.clone(),
            };
            let node_2_ref = Arc::new(Node::internal(node_2));
            self.len = keys_split.keys_1_len;
            self.right = node_2_ref.clone();
            return Some(NodeSplit {
                new_right_node: node_2_ref,
                left_node_latch: NodeWriteGuard::default(),
                pivot: keys_split.pivot_key,
                parent_latch: parent_guard,
            });
        } else {
            let mut new_node_len = node_len;
            let mut new_node_pointers = node_len + 1;
            self.keys.insert_at(key, pos, &mut new_node_len);
            self.ptrs
                .insert_at(new_node, pos + 1, &mut new_node_pointers);
            self.len = new_node_len;
            return None;
        }
    }
    pub fn rebalance_candidate(&self, pointer_pos: usize) -> usize {
        debug_assert!(pointer_pos <= self.len);
        debug!(
            "Searching for rebalance candidate, pos {}, len {}",
            pointer_pos, self.len
        );
        if pointer_pos == 0 {
            1
        } else if pointer_pos + 1 >= self.len {
            // the last one, pick left
            pointer_pos - 1
        } else {
            // pick the right one
            // we should pick the one  with least pointers, but it cost for the check is too high
            pointer_pos + 1
        }
    }
    pub fn merge_children(
        &mut self,
        left_ptr_pos: usize,
        right_ptr_pos: usize,
        left_node: &mut NodeData,
        right_node: &mut NodeData,
        right_node_next: &mut NodeData,
    ) -> Result<(), TxnErr> {
        let left_node_ref = self.ptrs[left_ptr_pos].clone();
        let left_len = left_node.len();
        let right_len = right_node.len();
        let right_key_pos = self.key_pos_from_ptr_pos(right_ptr_pos);
        let mut merged_len = 0;
        debug!("Merge children, left len {}, right len {}, left_ptr_pos {}, right_ptr_pos {}, right_key_pos {}",
                left_len, right_len, left_ptr_pos, right_ptr_pos, right_key_pos);
        debug_assert_eq!(left_node.is_ext(), right_node.is_ext());
        if !left_node.is_ext() {
            {
                let mut left_innode = left_node.innode_mut();
                let mut right_innode = right_node.innode_mut();
                let right_key = self.keys[right_key_pos].clone();
                left_innode.merge_with(&mut right_innode, right_key);
                left_innode.right = right_innode.right.clone();
                merged_len = left_innode.len;
            }
        } else {
            let mut right_extnode = right_node.extnode_mut();
            let mut left_extnode = left_node.extnode_mut();
            {
                left_extnode.merge_with(&mut right_extnode);
                merged_len = left_extnode.len;
            }
            if !right_node_next.is_none() {
                right_node_next.extnode_mut().prev = left_node_ref
            }
            left_extnode.next = right_extnode.next.clone();
        }
        self.remove_at(right_ptr_pos);
        debug!(
            "Removing merged node at {}, left {}, right {}, merged {}",
            right_ptr_pos,left_len, right_len, merged_len
        );
        debug!("Merged parent level keys: {:?}", self.keys);
        debug!("Merged level keys {:?}", left_node.keys());
        Ok(())
    }
    pub fn merge_with(&mut self, right: &mut Self, right_key: EntryKey) {
        debug!(
            "Merge internal node, left len {}, right len {}, right_key {:?}",
            self.len, right.len, right_key
        );
        let mut self_len = self.len;
        let new_len = self_len + right.len + 1;
        debug_assert!(new_len <= self.keys.len());
        // moving keys
        self.keys[self_len] = right_key;
        for i in self_len + 1..new_len {
            mem::swap(&mut self.keys[i], &mut right.keys[i - self_len - 1]);
        }
        for i in self_len + 1..new_len + 1 {
            mem::swap(&mut self.ptrs[i], &mut right.ptrs[i - self_len - 1]);
        }
        self.len += right.len + 1;
    }
    pub fn relocate_children(
        &mut self,
        left_ptr_pos: usize,
        right_ptr_pos: usize,
        left_node: &mut NodeData,
        right_node: &mut NodeData,
    ) {
        debug_assert_ne!(left_ptr_pos, right_ptr_pos);
        let mut new_right_node_key = Default::default();
        let half_full_pos = (left_node.len() + right_node.len()) / 2;
        debug_assert_eq!(left_node.is_ext(), right_node.is_ext());
        if !left_node.is_ext() {
            // relocate internal sub nodes

            {
                let mut left_innode = left_node.innode_mut();
                let mut right_innode = right_node.innode_mut();

                debug!(
                    "Before relocation internal children. left {}:{:?} right {}:{:?}",
                    left_innode.len, left_innode.keys, right_innode.len, right_innode.keys
                );

                let mut new_left_keys = EntryKeySlice::init();
                let mut new_left_ptrs = NodePtrCellSlice::init();

                let mut new_right_keys = EntryKeySlice::init();
                let mut new_right_ptrs = NodePtrCellSlice::init();

                let pivot_key = self.keys[right_ptr_pos - 1].to_owned();
                let mut new_left_keys_len = 0;
                let mut new_right_keys_len = 0;
                debug_assert!(pivot_key > smallvec!(0));
                for (i, key) in chain(
                    chain(
                        left_innode.keys[..left_innode.len].iter_mut(),
                        [pivot_key].iter_mut(),
                    ),
                    right_innode.keys[..right_innode.len].iter_mut(),
                )
                .enumerate()
                {
                    if i < half_full_pos {
                        mem::swap(key, &mut new_left_keys[i]);
                        new_left_keys_len += 1;
                    } else if i == half_full_pos {
                        mem::swap(key, &mut new_right_node_key);
                    } else {
                        let nk_index = i - half_full_pos - 1;
                        mem::swap(key, &mut new_right_keys[nk_index]);
                        new_right_keys_len += 1;
                    }
                }

                for (i, ptr) in chain(
                    left_innode.ptrs[..left_innode.len + 1].iter_mut(),
                    right_innode.ptrs[..right_innode.len + 1].iter_mut(),
                )
                .enumerate()
                {
                    if i < half_full_pos + 1 {
                        mem::swap(ptr, &mut new_left_ptrs[i]);
                    } else {
                        mem::swap(ptr, &mut new_right_ptrs[i - half_full_pos - 1]);
                    }
                }

                left_innode.keys = new_left_keys;
                left_innode.ptrs = new_left_ptrs;
                left_innode.len = new_left_keys_len;

                right_innode.keys = new_right_keys;
                right_innode.ptrs = new_right_ptrs;
                right_innode.len = new_right_keys_len;

                debug!(
                    "Relocated internal children. left {}:{:?} right {}:{:?}",
                    left_innode.len, left_innode.keys, right_innode.len, right_innode.keys
                );
            }
        } else if left_node.is_ext() {
            // relocate external sub nodes

            let mut left_extnode = left_node.extnode_mut();
            let mut right_extnode = right_node.extnode_mut();

            debug!(
                "Before relocation external children. left {}:{:?} right {}:{:?}",
                left_extnode.len, left_extnode.keys, right_extnode.len, right_extnode.keys
            );

            let mut new_left_keys = EntryKeySlice::init();
            let mut new_right_keys = EntryKeySlice::init();

            let left_len = left_extnode.len;
            let right_len = right_extnode.len;
            let mut new_left_keys_len = 0;
            let mut new_right_keys_len = 0;
            for (i, key) in chain(
                left_extnode.keys[..left_len].iter_mut(),
                right_extnode.keys[..right_len].iter_mut(),
            )
            .enumerate()
            {
                if i < half_full_pos {
                    mem::swap(key, &mut new_left_keys[i]);
                    new_left_keys_len += 1;
                } else {
                    mem::swap(key, &mut new_right_keys[i - half_full_pos]);
                    new_right_keys_len += 1;
                }
            }

            new_right_node_key = new_right_keys[0].clone();

            left_extnode.keys = new_left_keys;
            left_extnode.len = new_left_keys_len;

            right_extnode.keys = new_right_keys;
            right_extnode.len = new_right_keys_len;

            debug!(
                "Relocated external children. left {}:{:?} right {}:{:?}",
                left_extnode.len, left_extnode.keys, right_extnode.len, right_extnode.keys
            );
        }

        let right_key_pos = right_ptr_pos - 1;
        debug!(
            "Setting key at pos {} to new key {:?}",
            right_key_pos, new_right_node_key
        );
        debug_assert!(new_right_node_key > smallvec!(0));
        self.keys[right_key_pos] = new_right_node_key;
    }
}
<|endoftext|>


<commit_before>use dataflow::channels::Content;
use timely_communication::Push;

pub struct Buffer<T, D, P: Push<(T, Content<D>)>> {
    time: Option<T>,  // the currently open time, if it is open
    buffer: Vec<D>,   // a buffer for records, to send at self.time
    pusher: P,
}

impl<T, D, P: Push<(T, Content<D>)>> Buffer<T, D, P> where T: Eq+Clone {

    pub fn new(pusher: P) -> Buffer<T, D, P> {
        Buffer {
            time: None,
            buffer: Vec::with_capacity(Content::<D>::default_length()),
            pusher: pusher,
        }
    }

    /// Returns a Session, which accepts data to send at the associated time
    pub fn session(&mut self, time: &T) -> Session<T, D, P> {
        if let Some(true) = self.time.as_ref().map(|x| x != time) { self.flush(); }
        self.time = Some(time.clone());
        Session { buffer: self }
    }

    pub fn inner(&mut self) -> &mut P { &mut self.pusher }

    pub fn cease(&mut self) {
        self.flush();
        self.pusher.push(&mut None);
    }

    /// moves the contents of
    fn flush(&mut self) {
        if !self.buffer.is_empty() {
            let time = self.time.as_ref().unwrap().clone();
            Content::push_at(&mut self.buffer, time, &mut self.pusher);
        }
    }

    fn give(&mut self, data: D) {
        self.buffer.push(data);
        // assert!(self.buffer.capacity() == Message::<O::Data>::default_length());
        if self.buffer.len() == self.buffer.capacity() {
            self.flush();
        }
    }

    /// Gives an entire message at a specific time.
    fn give_content(&mut self, content: &mut Content<D>) {
        // flush to ensure fifo-ness
        if !self.buffer.is_empty() {
            self.flush();
        }

        let time = self.time.as_ref().unwrap().clone();
        let data = ::std::mem::replace(content, Content::Typed(Vec::new()));
        let mut message = Some((time, data));

        self.pusher.push(&mut message);
        if let Some((_, data)) = message {
            *content = data;
        }
    }
}

pub struct Session<'a, T, D, P: Push<(T, Content<D>)>+'a> where T: Eq+Clone+'a, D: 'a {
    buffer: &'a mut Buffer<T, D, P>,
}

impl<'a, T, D, P: Push<(T, Content<D>)>+'a> Session<'a, T, D, P>  where T: Eq+Clone+'a, D: 'a {
    #[inline(always)]
    pub fn give(&mut self, data: D) {
        self.buffer.give(data);
    }
    #[inline(always)]
    pub fn give_iterator<I: Iterator<Item=D>>(&mut self, iter: I) {
        for item in iter {
            self.give(item);
        }
    }
    #[inline(always)]
    pub fn give_content(&mut self, message: &mut Content<D>) {
        if message.len() > 0 {
            self.buffer.give_content(message);
        }
    }
}
<commit_msg>documentation<commit_after>use dataflow::channels::Content;
use timely_communication::Push;

/// Buffers data sent at the same time, for efficient communication.
///
/// The `Buffer` type should be used by calling `session` with a time, which checks whether
/// data must be flushed and creates a `Session` object which allows sending at the given time.
pub struct Buffer<T, D, P: Push<(T, Content<D>)>> {
    time: Option<T>,  // the currently open time, if it is open
    buffer: Vec<D>,   // a buffer for records, to send at self.time
    pusher: P,
}

impl<T, D, P: Push<(T, Content<D>)>> Buffer<T, D, P> where T: Eq+Clone {

    /// Creates a new `Buffer`.
    pub fn new(pusher: P) -> Buffer<T, D, P> {
        Buffer {
            time: None,
            buffer: Vec::with_capacity(Content::<D>::default_length()),
            pusher: pusher,
        }
    }

    /// Returns a `Session`, which accepts data to send at the associated time
    pub fn session(&mut self, time: &T) -> Session<T, D, P> {
        if let Some(true) = self.time.as_ref().map(|x| x != time) { self.flush(); }
        self.time = Some(time.clone());
        Session { buffer: self }
    }

    /// Returns a reference to the inner `P: Push` type.
    ///
    /// This is currently used internally, and should not be used without some care.
    pub fn inner(&mut self) -> &mut P { &mut self.pusher }

    /// Flushes all data and pushes a `None` to `self.pusher`, indicating a flush.
    pub fn cease(&mut self) {
        self.flush();
        self.pusher.push(&mut None);
    }

    /// moves the contents of
    fn flush(&mut self) {
        if !self.buffer.is_empty() {
            let time = self.time.as_ref().unwrap().clone();
            Content::push_at(&mut self.buffer, time, &mut self.pusher);
        }
    }

    // internal method for use by `Session`.
    fn give(&mut self, data: D) {
        self.buffer.push(data);
        // assert!(self.buffer.capacity() == Message::<O::Data>::default_length());
        if self.buffer.len() == self.buffer.capacity() {
            self.flush();
        }
    }

    // Gives an entire message at a specific time.
    fn give_content(&mut self, content: &mut Content<D>) {
        // flush to ensure fifo-ness
        if !self.buffer.is_empty() {
            self.flush();
        }

        let time = self.time.as_ref().unwrap().clone();
        let data = ::std::mem::replace(content, Content::Typed(Vec::new()));
        let mut message = Some((time, data));

        self.pusher.push(&mut message);
        if let Some((_, data)) = message {
            *content = data;
        }
    }
}

/// An output session for sending records at a specified time.
///
/// The `Session` struct provides the user-facing interface to an operator output, namely
/// the `Buffer` type. A `Session` wraps a session of output at a specified time, and
/// avoids what would otherwise be a constant cost of checking timestamp equality.
pub struct Session<'a, T, D, P: Push<(T, Content<D>)>+'a> where T: Eq+Clone+'a, D: 'a {
    buffer: &'a mut Buffer<T, D, P>,
}

impl<'a, T, D, P: Push<(T, Content<D>)>+'a> Session<'a, T, D, P>  where T: Eq+Clone+'a, D: 'a {
    /// Provides one record at the time specified by the `Session`.
    #[inline(always)]
    pub fn give(&mut self, data: D) {
        self.buffer.give(data);
    }
    /// Provides an iterator of records at the time specified by the `Session`.
    #[inline(always)]
    pub fn give_iterator<I: Iterator<Item=D>>(&mut self, iter: I) {
        for item in iter {
            self.give(item);
        }
    }
    /// Provides a fully formed `Content<D>` message for senders which can use this type.
    ///
    /// The `Content` type is the backing memory for communication in timely, and it can
    /// often be more efficient to re-use this memory rather than have timely allocate
    /// new backing memory.
    #[inline(always)]
    pub fn give_content(&mut self, message: &mut Content<D>) {
        if message.len() > 0 {
            self.buffer.give_content(message);
        }
    }
}
<|endoftext|>


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

#![allow(non_snake_case)]

// Error messages for EXXXX errors.
// Each message should start and end with a new line, and be wrapped to 80 characters.
// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
register_long_diagnostics! {

E0001: r##"
This error suggests that the expression arm corresponding to the noted pattern
will never be reached as for all possible values of the expression being
matched, one of the preceding patterns will match.

This means that perhaps some of the preceding patterns are too general, this one
is too specific or the ordering is incorrect.
"##,

E0002: r##"
This error indicates that an empty match expression is illegal because the type
it is matching on is non-empty (there exist values of this type). In safe code
it is impossible to create an instance of an empty type, so empty match
expressions are almost never desired.  This error is typically fixed by adding
one or more cases to the match expression.

An example of an empty type is `enum Empty { }`.
"##,

E0003: r##"
Not-a-Number (NaN) values cannot be compared for equality and hence can never
match the input to a match expression. To match against NaN values, you should
instead use the `is_nan` method in a guard, as in: x if x.is_nan() => ...
"##,

E0004: r##"
This error indicates that the compiler cannot guarantee a matching pattern for
one or more possible inputs to a match expression. Guaranteed matches are
required in order to assign values to match expressions, or alternatively,
determine the flow of execution.

If you encounter this error you must alter your patterns so that every possible
value of the input type is matched. For types with a small number of variants
(like enums) you should probably cover all cases explicitly. Alternatively, the
underscore `_` wildcard pattern can be added after all other patterns to match
"anything else".
"##,

// FIXME: Remove duplication here?
E0005: r##"
Patterns used to bind names must be irrefutable, that is, they must guarantee that a
name will be extracted in all cases. If you encounter this error you probably need
to use a `match` or `if let` to deal with the possibility of failure.
"##,

E0006: r##"
Patterns used to bind names must be irrefutable, that is, they must guarantee that a
name will be extracted in all cases. If you encounter this error you probably need
to use a `match` or `if let` to deal with the possibility of failure.
"##,

E0007: r##"
This error indicates that the bindings in a match arm would require a value to
be moved into more than one location, thus violating unique ownership. Code like
the following is invalid as it requires the entire Option<String> to be moved
into a variable called `op_string` while simultaneously requiring the inner
String to be moved into a variable called `s`.

let x = Some("s".to_string());
match x {
    op_string @ Some(s) => ...
    None => ...
}

See also Error 303.
"##,

E0008: r##"
Names bound in match arms retain their type in pattern guards. As such, if a
name is bound by move in a pattern, it should also be moved to wherever it is
referenced in the pattern guard code. Doing so however would prevent the name
from being available in the body of the match arm. Consider the following:

match Some("hi".to_string()) {
    Some(s) if s.len() == 0 => // use s.
    ...
}

The variable `s` has type String, and its use in the guard is as a variable of
type String. The guard code effectively executes in a separate scope to the body
of the arm, so the value would be moved into this anonymous scope and therefore
become unavailable in the body of the arm. Although this example seems
innocuous, the problem is most clear when considering functions that take their
argument by value.

match Some("hi".to_string()) {
    Some(s) if { drop(s); false } => (),
    Some(s) => // use s.
    ...
}

The value would be dropped in the guard then become unavailable not only in the
body of that arm but also in all subsequent arms! The solution is to bind by
reference when using guards or refactor the entire expression, perhaps by
putting the condition inside the body of the arm.
"##,

E0297: r##"
Patterns used to bind names must be irrefutable. That is, they must guarantee
that a name will be extracted in all cases. Instead of pattern matching the
loop variable, consider using a `match` or `if let` inside the loop body. For
instance:

// This fails because `None` is not covered.
for Some(x) in xs {
    ...
}

// Match inside the loop instead:
for item in xs {
    match item {
        Some(x) => ...
        None => ...
    }
}

// Or use `if let`:
for item in xs {
    if let Some(x) = item {
        ...
    }
}
"##,

E0301: r##"
Mutable borrows are not allowed in pattern guards, because matching cannot have
side effects. Side effects could alter the matched object or the environment
on which the match depends in such a way, that the match would not be
exhaustive. For instance, the following would not match any arm if mutable
borrows were allowed:

match Some(()) {
    None => { },
    option if option.take().is_none() => { /* impossible, option is `Some` */ },
    Some(_) => { } // When the previous match failed, the option became `None`.
}
"##,

E0303: r##"
In certain cases it is possible for sub-bindings to violate memory safety.
Updates to the borrow checker in a future version of Rust may remove this
restriction, but for now patterns must be rewritten without sub-bindings.

// Code like this...
match Some(5) {
    ref op_num @ Some(num) => ...
    None => ...
}

// ... should be updated to code like this.
match Some(5) {
    Some(num) => {
        let op_num = &Some(num);
        ...
    }
    None => ...
}

See also https://github.com/rust-lang/rust/issues/14587
"##

}

register_diagnostics! {
    E0009,
    E0010,
    E0011,
    E0012,
    E0013,
    E0014,
    E0015,
    E0016,
    E0017,
    E0018,
    E0019,
    E0020,
    E0022,
    E0079, // enum variant: expected signed integer constant
    E0080, // enum variant: constant evaluation error
    E0109,
    E0110,
    E0133,
    E0134,
    E0135,
    E0136,
    E0137,
    E0138,
    E0139,
    E0152,
    E0158,
    E0161,
    E0162,
    E0165,
    E0170,
    E0261, // use of undeclared lifetime name
    E0262, // illegal lifetime parameter name
    E0263, // lifetime name declared twice in same scope
    E0264, // unknown external lang item
    E0265, // recursive constant
    E0266, // expected item
    E0267, // thing inside of a closure
    E0268, // thing outside of a loop
    E0269, // not all control paths return a value
    E0270, // computation may converge in a function marked as diverging
    E0271, // type mismatch resolving
    E0272, // rustc_on_unimplemented attribute refers to non-existent type parameter
    E0273, // rustc_on_unimplemented must have named format arguments
    E0274, // rustc_on_unimplemented must have a value
    E0275, // overflow evaluating requirement
    E0276, // requirement appears on impl method but not on corresponding trait method
    E0277, // trait is not implemented for type
    E0278, // requirement is not satisfied
    E0279, // requirement is not satisfied
    E0280, // requirement is not satisfied
    E0281, // type implements trait but other trait is required
    E0282, // unable to infer enough type information about
    E0283, // cannot resolve type
    E0284, // cannot resolve type
    E0285, // overflow evaluation builtin bounds
    E0296, // malformed recursion limit attribute
    E0298, // mismatched types between arms
    E0299, // mismatched types between arms
    E0300, // unexpanded macro
    E0302, // cannot assign in a pattern guard
    E0304, // expected signed integer constant
    E0305, // expected constant
    E0306, // expected positive integer for repeat count
    E0307, // expected constant integer for repeat count
    E0308,
    E0309, // thing may not live long enough
    E0310, // thing may not live long enough
    E0311, // thing may not live long enough
    E0312, // lifetime of reference outlives lifetime of borrowed content
    E0313, // lifetime of borrowed pointer outlives lifetime of captured variable
    E0314, // closure outlives stack frame
    E0315, // cannot invoke closure outside of its lifetime
    E0316, // nested quantification of lifetimes
    E0370  // discriminant overflow
}

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

#![allow(non_snake_case)]

// Error messages for EXXXX errors.
// Each message should start and end with a new line, and be wrapped to 80 characters.
// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
register_long_diagnostics! {

E0001: r##"
This error suggests that the expression arm corresponding to the noted pattern
will never be reached as for all possible values of the expression being
matched, one of the preceding patterns will match.

This means that perhaps some of the preceding patterns are too general, this one
is too specific or the ordering is incorrect.
"##,

E0002: r##"
This error indicates that an empty match expression is illegal because the type
it is matching on is non-empty (there exist values of this type). In safe code
it is impossible to create an instance of an empty type, so empty match
expressions are almost never desired.  This error is typically fixed by adding
one or more cases to the match expression.

An example of an empty type is `enum Empty { }`.
"##,

E0003: r##"
Not-a-Number (NaN) values cannot be compared for equality and hence can never
match the input to a match expression. To match against NaN values, you should
instead use the `is_nan` method in a guard, as in: x if x.is_nan() => ...
"##,

E0004: r##"
This error indicates that the compiler cannot guarantee a matching pattern for
one or more possible inputs to a match expression. Guaranteed matches are
required in order to assign values to match expressions, or alternatively,
determine the flow of execution.

If you encounter this error you must alter your patterns so that every possible
value of the input type is matched. For types with a small number of variants
(like enums) you should probably cover all cases explicitly. Alternatively, the
underscore `_` wildcard pattern can be added after all other patterns to match
"anything else".
"##,

// FIXME: Remove duplication here?
E0005: r##"
Patterns used to bind names must be irrefutable, that is, they must guarantee that a
name will be extracted in all cases. If you encounter this error you probably need
to use a `match` or `if let` to deal with the possibility of failure.
"##,

E0006: r##"
Patterns used to bind names must be irrefutable, that is, they must guarantee that a
name will be extracted in all cases. If you encounter this error you probably need
to use a `match` or `if let` to deal with the possibility of failure.
"##,

E0007: r##"
This error indicates that the bindings in a match arm would require a value to
be moved into more than one location, thus violating unique ownership. Code like
the following is invalid as it requires the entire Option<String> to be moved
into a variable called `op_string` while simultaneously requiring the inner
String to be moved into a variable called `s`.

let x = Some("s".to_string());
match x {
    op_string @ Some(s) => ...
    None => ...
}

See also Error 303.
"##,

E0008: r##"
Names bound in match arms retain their type in pattern guards. As such, if a
name is bound by move in a pattern, it should also be moved to wherever it is
referenced in the pattern guard code. Doing so however would prevent the name
from being available in the body of the match arm. Consider the following:

match Some("hi".to_string()) {
    Some(s) if s.len() == 0 => // use s.
    ...
}

The variable `s` has type String, and its use in the guard is as a variable of
type String. The guard code effectively executes in a separate scope to the body
of the arm, so the value would be moved into this anonymous scope and therefore
become unavailable in the body of the arm. Although this example seems
innocuous, the problem is most clear when considering functions that take their
argument by value.

match Some("hi".to_string()) {
    Some(s) if { drop(s); false } => (),
    Some(s) => // use s.
    ...
}

The value would be dropped in the guard then become unavailable not only in the
body of that arm but also in all subsequent arms! The solution is to bind by
reference when using guards or refactor the entire expression, perhaps by
putting the condition inside the body of the arm.
"##,

E0297: r##"
Patterns used to bind names must be irrefutable. That is, they must guarantee
that a name will be extracted in all cases. Instead of pattern matching the
loop variable, consider using a `match` or `if let` inside the loop body. For
instance:

// This fails because `None` is not covered.
for Some(x) in xs {
    ...
}

// Match inside the loop instead:
for item in xs {
    match item {
        Some(x) => ...
        None => ...
    }
}

// Or use `if let`:
for item in xs {
    if let Some(x) = item {
        ...
    }
}
"##,

E0301: r##"
Mutable borrows are not allowed in pattern guards, because matching cannot have
side effects. Side effects could alter the matched object or the environment
on which the match depends in such a way, that the match would not be
exhaustive. For instance, the following would not match any arm if mutable
borrows were allowed:

match Some(()) {
    None => { },
    option if option.take().is_none() => { /* impossible, option is `Some` */ },
    Some(_) => { } // When the previous match failed, the option became `None`.
}
"##,

E0302: r##"
Assignments are not allowed in pattern guards, because matching cannot have
side effects. Side effects could alter the matched object or the environment
on which the match depends in such a way, that the match would not be
exhaustive. For instance, the following would not match any arm if assignments
were allowed:

match Some(()) {
    None => { },
    option if { option = None; false } { },
    Some(_) => { } // When the previous match failed, the option became `None`.
}
"##,

E0303: r##"
In certain cases it is possible for sub-bindings to violate memory safety.
Updates to the borrow checker in a future version of Rust may remove this
restriction, but for now patterns must be rewritten without sub-bindings.

// Code like this...
match Some(5) {
    ref op_num @ Some(num) => ...
    None => ...
}

// ... should be updated to code like this.
match Some(5) {
    Some(num) => {
        let op_num = &Some(num);
        ...
    }
    None => ...
}

See also https://github.com/rust-lang/rust/issues/14587
"##

}

register_diagnostics! {
    E0009,
    E0010,
    E0011,
    E0012,
    E0013,
    E0014,
    E0015,
    E0016,
    E0017,
    E0018,
    E0019,
    E0020,
    E0022,
    E0079, // enum variant: expected signed integer constant
    E0080, // enum variant: constant evaluation error
    E0109,
    E0110,
    E0133,
    E0134,
    E0135,
    E0136,
    E0137,
    E0138,
    E0139,
    E0152,
    E0158,
    E0161,
    E0162,
    E0165,
    E0170,
    E0261, // use of undeclared lifetime name
    E0262, // illegal lifetime parameter name
    E0263, // lifetime name declared twice in same scope
    E0264, // unknown external lang item
    E0265, // recursive constant
    E0266, // expected item
    E0267, // thing inside of a closure
    E0268, // thing outside of a loop
    E0269, // not all control paths return a value
    E0270, // computation may converge in a function marked as diverging
    E0271, // type mismatch resolving
    E0272, // rustc_on_unimplemented attribute refers to non-existent type parameter
    E0273, // rustc_on_unimplemented must have named format arguments
    E0274, // rustc_on_unimplemented must have a value
    E0275, // overflow evaluating requirement
    E0276, // requirement appears on impl method but not on corresponding trait method
    E0277, // trait is not implemented for type
    E0278, // requirement is not satisfied
    E0279, // requirement is not satisfied
    E0280, // requirement is not satisfied
    E0281, // type implements trait but other trait is required
    E0282, // unable to infer enough type information about
    E0283, // cannot resolve type
    E0284, // cannot resolve type
    E0285, // overflow evaluation builtin bounds
    E0296, // malformed recursion limit attribute
    E0298, // mismatched types between arms
    E0299, // mismatched types between arms
    E0300, // unexpanded macro
    E0304, // expected signed integer constant
    E0305, // expected constant
    E0306, // expected positive integer for repeat count
    E0307, // expected constant integer for repeat count
    E0308,
    E0309, // thing may not live long enough
    E0310, // thing may not live long enough
    E0311, // thing may not live long enough
    E0312, // lifetime of reference outlives lifetime of borrowed content
    E0313, // lifetime of borrowed pointer outlives lifetime of captured variable
    E0314, // closure outlives stack frame
    E0315, // cannot invoke closure outside of its lifetime
    E0316, // nested quantification of lifetimes
    E0370  // discriminant overflow
}

__build_diagnostic_array! { DIAGNOSTICS }
<|endoftext|>