<commit_before>use std::path::Path;
use ::subtitles::*;
use ::std::fs::File;
use ::std::io::{BufReader, BufRead};
use ::std::error::Error;
use ::subtitles::pos::RowPosition;

/// frm / lyr / fps
impl<'a> Load for (Option<&'a Path>, &'a Path, f64) {
    fn into_subtitles(&self) -> Result<Subtitles, String> {
        // TODO : split this into with / without frm file, where one calls the other
        let frm: Option<&Path> = self.0;
        let lyr: &Path = self.1;
        let fps: f64 = self.2;
        if fps == 0.0 {
            return Err(String::from("File has no frame/second, impossible to load .lyr/.frm, \
                                     aborting ..."));
        };
        let mut subtitles = Subtitles::default();
        let lyr_file = try!(File::open(lyr).map_err(|e| e.description().to_string()));
        let lyr_file = BufReader::new(&lyr_file);
        let mut subtitles_options: SubtitlesOptions = Default::default();
        let mut current_sentence_options: Option<SentenceOptions> = None;
        for (line_number, lyr_line) in lyr_file.lines().enumerate() {
            let lyr_line = try!(lyr_line.map_err(|e| {
                format!("IoError when reading {} at line {} : '{}'",
                        lyr.display(),
                        line_number,
                        e.description())
            }));
            if (!lyr_line.starts_with("%") && !lyr_line.starts_with("#") && !lyr_line.is_empty()) {
                let mut syllables: Vec<_> = lyr_line.split('&')
                    .map(|s| {
                        Syllable {
                            text: s.to_string(),
                            begin: 0,
                            end: Some(0),
                            syllable_options: None,
                        }
                    })
                    .collect::<Vec<_>>();
                if (lyr_line.starts_with("&")) {
                    syllables.remove(0);
                };
                let sentence = Sentence {
                    syllables: syllables,
                    position: RowPosition::default(),
                    sentence_options: current_sentence_options.clone(),
                };
                subtitles.sentences.push(sentence);
            } else if lyr_line.starts_with("%color") {
                let mut syllable_options = SyllableOptions::default();
                use utils::parse_bgr;
                let colors: Vec<_> = lyr_line.split_whitespace().collect();
                if colors.len() == 4 {
                    let alive_color = parse_bgr(colors[1]);
                    let transition_color = parse_bgr(colors[2]);
                    let dead_color = parse_bgr(colors[3]);
                    match (alive_color, transition_color, dead_color) {
                        (Ok(alive_color), Ok(transition_color), Ok(dead_color)) => {
                            syllable_options.alive_color = Some(alive_color);
                            syllable_options.transition_color = Some(transition_color);
                            syllable_options.dead_color = Some(dead_color);
                        }
                        _ => {
                            error!("Invalid %color syntax when reading {} at line {} : '{}'",
                                   lyr.display(),
                                   line_number,
                                   lyr_line);
                        }
                    }
                } else {
                    error!("Invalid %color syntax when reading {} at line {} : '{}'",
                           lyr.display(),
                           line_number,
                           lyr_line);
                }
                let mut sentence_options = SentenceOptions::default();
                sentence_options.syllable_options = Some(syllable_options);
                match subtitles.sentences.len() {
                    0 => subtitles_options.sentence_options = Some(sentence_options),
                    _ => current_sentence_options = Some(sentence_options),
                };
            };
        }
        if let Some(frm) = frm {
            let frm_file = try!(File::open(frm).map_err(|e| e.description().to_string()));
            let frm_file = BufReader::new(&frm_file);
            let mut frames: Vec<(u32, u32)> = vec![];
            for (line_number, frm_line) in frm_file.lines().enumerate() {
                let frm_line = try!(frm_line.map_err(|e| {
                    format!("IoError when reading {} at line {} : '{}'",
                            frm.display(),
                            line_number,
                            e.description())
                }));
                if !frm_line.trim().is_empty() {
                    let line_frames: Result<Vec<_>, _> = frm_line.split(' ')
                        .map(|s| s.parse::<u32>())
                        .collect();
                    let begin_end =
                        line_frames.map_err(|e| format!("{} at line {}", e, line_number))
                            .and_then(|line_frames| {
                                match (line_frames.get(0), line_frames.get(1), line_frames.get(2)) {
                                    (Some(&begin), Some(&end), None) => Ok((begin, end)),
                                    (None, _, _) | (_, None, _) => {
                                        Err(format!("Error while parsing frm file '{}' at line \
                                                     {}, not enough values",
                                                    frm.display(),
                                                    line_number))
                                    }
                                    (_, _, Some(_)) => {
                                        Err(format!("Error while parsing frm file '{}' at line \
                                                     {}, too many values",
                                                    frm.display(),
                                                    line_number))
                                    }
                                }
                            });
                    let begin_end = try!(begin_end);
                    frames.push(begin_end);
                } else {
                    warn!("empty line {} in frm file '{}'", line_number, frm.display());
                }
            }
            let mut frame_iter = frames.iter();
            'sentences: for sentence in subtitles.sentences.iter_mut() {
                for syllable in sentence.syllables.iter_mut() {
                    match frame_iter.next() {
                        Some(&(begin, end)) => {
                            syllable.begin = (begin as f64 / fps * 1000.0) as u32;
                            syllable.end = Some((end as f64 / fps * 1000.0) as u32);
                        }
                        None => {
                            break 'sentences;
                        }
                    }
                }
            }
        };
        subtitles.subtitles_options = subtitles_options;
        try!(subtitles.check());
        Ok(subtitles)
    }
}
<commit_msg>Improve error handling for lacking frm file<commit_after>use std::path::Path;
use ::subtitles::*;
use ::std::fs::File;
use ::std::io::{BufReader, BufRead};
use ::std::error::Error;
use ::subtitles::pos::RowPosition;

/// frm / lyr / fps
impl<'a> Load for (Option<&'a Path>, &'a Path, f64) {
    fn into_subtitles(&self) -> Result<Subtitles, String> {
        // TODO : split this into with / without frm file, where one calls the other
        let frm: Option<&Path> = self.0;
        let lyr: &Path = self.1;
        let fps: f64 = self.2;
        let mut subtitles = Subtitles::default();
        let lyr_file = try!(File::open(lyr).map_err(|e| e.description().to_string()));
        let lyr_file = BufReader::new(&lyr_file);
        let mut subtitles_options: SubtitlesOptions = Default::default();
        let mut current_sentence_options: Option<SentenceOptions> = None;
        for (line_number, lyr_line) in lyr_file.lines().enumerate() {
            let lyr_line = try!(lyr_line.map_err(|e| {
                format!("IoError when reading {} at line {} : '{}'",
                        lyr.display(),
                        line_number,
                        e.description())
            }));
            if (!lyr_line.starts_with("%") && !lyr_line.starts_with("#") && !lyr_line.is_empty()) {
                let mut syllables: Vec<_> = lyr_line.split('&')
                    .map(|s| {
                        Syllable {
                            text: s.to_string(),
                            begin: 0,
                            end: Some(0),
                            syllable_options: None,
                        }
                    })
                    .collect::<Vec<_>>();
                if (lyr_line.starts_with("&")) {
                    syllables.remove(0);
                };
                let sentence = Sentence {
                    syllables: syllables,
                    position: RowPosition::default(),
                    sentence_options: current_sentence_options.clone(),
                };
                subtitles.sentences.push(sentence);
            } else if lyr_line.starts_with("%color") {
                let mut syllable_options = SyllableOptions::default();
                use utils::parse_bgr;
                let colors: Vec<_> = lyr_line.split_whitespace().collect();
                if colors.len() == 4 {
                    let alive_color = parse_bgr(colors[1]);
                    let transition_color = parse_bgr(colors[2]);
                    let dead_color = parse_bgr(colors[3]);
                    match (alive_color, transition_color, dead_color) {
                        (Ok(alive_color), Ok(transition_color), Ok(dead_color)) => {
                            syllable_options.alive_color = Some(alive_color);
                            syllable_options.transition_color = Some(transition_color);
                            syllable_options.dead_color = Some(dead_color);
                        }
                        _ => {
                            error!("Invalid %color syntax when reading {} at line {} : '{}'",
                                   lyr.display(),
                                   line_number,
                                   lyr_line);
                        }
                    }
                } else {
                    error!("Invalid %color syntax when reading {} at line {} : '{}'",
                           lyr.display(),
                           line_number,
                           lyr_line);
                }
                let mut sentence_options = SentenceOptions::default();
                sentence_options.syllable_options = Some(syllable_options);
                match subtitles.sentences.len() {
                    0 => subtitles_options.sentence_options = Some(sentence_options),
                    _ => current_sentence_options = Some(sentence_options),
                };
            };
        }
        if fps == 0.0 {
            error!("File has no frame per second, impossible to sync .lyr with .frm");
        } else {
            if let Some(frm) = frm {
                let frm_file = try!(File::open(frm).map_err(|e| e.description().to_string()));
                let frm_file = BufReader::new(&frm_file);
                let mut frames: Vec<(u32, u32)> = vec![];
                for (line_number, frm_line) in frm_file.lines().enumerate() {
                    let frm_line = try!(frm_line.map_err(|e| {
                        format!("IoError when reading {} at line {} : '{}'",
                                frm.display(),
                                line_number,
                                e.description())
                    }));
                    if !frm_line.trim().is_empty() {
                        let line_frames: Result<Vec<_>, _> = frm_line.split(' ')
                            .map(|s| s.parse::<u32>())
                            .collect();
                        let begin_end =
                            line_frames.map_err(|e| format!("{} at line {}", e, line_number))
                                .and_then(|line_frames| {
                                    match (line_frames.get(0), line_frames.get(1), line_frames.get(2)) {
                                        (Some(&begin), Some(&end), None) => Ok((begin, end)),
                                        (None, _, _) | (_, None, _) => {
                                            Err(format!("Error while parsing frm file '{}' at line \
                                                         {}, not enough values",
                                                        frm.display(),
                                                        line_number))
                                        }
                                        (_, _, Some(_)) => {
                                            Err(format!("Error while parsing frm file '{}' at line \
                                                         {}, too many values",
                                                        frm.display(),
                                                        line_number))
                                        }
                                    }
                                });
                        let begin_end = try!(begin_end);
                        frames.push(begin_end);
                    } else {
                        warn!("empty line {} in frm file '{}'", line_number, frm.display());
                    }
                }
                let mut frame_iter = frames.iter();
                'sentences: for sentence in subtitles.sentences.iter_mut() {
                    for syllable in sentence.syllables.iter_mut() {
                        match frame_iter.next() {
                            Some(&(begin, end)) => {
                                syllable.begin = (begin as f64 / fps * 1000.0) as u32;
                                syllable.end = Some((end as f64 / fps * 1000.0) as u32);
                            }
                            None => {
                                break 'sentences;
                            }
                        }
                    }
                }
            };
        }
        subtitles.subtitles_options = subtitles_options;
        try!(subtitles.check());
        Ok(subtitles)
    }
}
<|endoftext|>


<commit_before>
use db::connect_db;
use DocBuilderError;
use time::{now, Duration};
use std::collections::BTreeMap;
use rustc_serialize::json::ToJson;

pub fn update_release_activity() -> Result<(), DocBuilderError> {

    let conn = try!(connect_db());
    let mut dates = Vec::new();
    let mut crate_counts = Vec::new();

    for day in 1..31 {
        let rows = try!(conn.query(&format!("SELECT COUNT(*)
                                             FROM releases
                                             WHERE release_time < NOW() - INTERVAL '{} day' AND
                                                   release_time > NOW() - INTERVAL '{} day'",
                                            day,
                                            day + 1),
                                   &[]));
        let release_count: i64 = rows.get(0).get(0);
        let now = now();
        let date = now - Duration::days(day);
        dates.push(format!("{}", date.strftime("%d %b").unwrap()));
        // unwrap is fine here,             ~~~~~~~~~~~~^  our date format is always valid
        crate_counts.push(release_count);
    }

    let map = {
        let mut map = BTreeMap::new();
        map.insert("dates".to_owned(), dates.to_json());
        map.insert("counts".to_owned(), crate_counts.to_json());
        map.to_json()
    };

    try!(conn.query("INSERT INTO config (name, value) VALUES ('release_activity', $1)",
               &[&map])
        .or_else(|_| {
            conn.query("UPDATE config SET value = $1 WHERE name = 'release_activity'",
                       &[&map])
        }));

    Ok(())
}

#[cfg(test)]
mod test {
    extern crate env_logger;
    use super::update_release_activity;

    #[test]
    #[ignore]
    fn test_update_release_activity() {
        let _ = env_logger::init();
        assert!(update_release_activity().is_ok());
    }
}
<commit_msg>Reverse release activity vectors<commit_after>
use db::connect_db;
use DocBuilderError;
use time::{now, Duration};
use std::collections::BTreeMap;
use rustc_serialize::json::ToJson;

pub fn update_release_activity() -> Result<(), DocBuilderError> {

    let conn = try!(connect_db());
    let mut dates = Vec::new();
    let mut crate_counts = Vec::new();

    for day in 1..31 {
        let rows = try!(conn.query(&format!("SELECT COUNT(*)
                                             FROM releases
                                             WHERE release_time < NOW() - INTERVAL '{} day' AND
                                                   release_time > NOW() - INTERVAL '{} day'",
                                            day,
                                            day + 1),
                                   &[]));
        let release_count: i64 = rows.get(0).get(0);
        let now = now();
        let date = now - Duration::days(day);
        dates.push(format!("{}", date.strftime("%d %b").unwrap()));
        // unwrap is fine here,             ~~~~~~~~~~~~^  our date format is always valid
        crate_counts.push(release_count);
    }

    dates.reverse();
    crate_counts.reverse();

    let map = {
        let mut map = BTreeMap::new();
        map.insert("dates".to_owned(), dates.to_json());
        map.insert("counts".to_owned(), crate_counts.to_json());
        map.to_json()
    };

    try!(conn.query("INSERT INTO config (name, value) VALUES ('release_activity', $1)",
               &[&map])
        .or_else(|_| {
            conn.query("UPDATE config SET value = $1 WHERE name = 'release_activity'",
                       &[&map])
        }));

    Ok(())
}

#[cfg(test)]
mod test {
    extern crate env_logger;
    use super::update_release_activity;

    #[test]
    #[ignore]
    fn test_update_release_activity() {
        let _ = env_logger::init();
        assert!(update_release_activity().is_ok());
    }
}
<|endoftext|>


<commit_before>use crate::simd::intrinsics;
use crate::{LaneCount, Simd, SimdElement, SupportedLaneCount};

/// Constructs a new vector by selecting values from the lanes of the source vector or vectors to use.
///
/// When swizzling one vector, the indices of the result vector are indicated by a `const` array
/// of `usize`, like [`Swizzle`].
/// When swizzling two vectors, the indices are indicated by a `const` array of [`Which`], like
/// [`Swizzle2`].
///
/// # Examples
/// ## One source vector
/// ```
/// # #![feature(portable_simd)]
/// # use core_simd::{Simd, simd_swizzle};
/// let v = Simd::<f32, 4>::from_array([0., 1., 2., 3.]);
///
/// // Keeping the same size
/// let r = simd_swizzle!(v, [3, 0, 1, 2]);
/// assert_eq!(r.to_array(), [3., 0., 1., 2.]);
///
/// // Changing the number of lanes
/// let r = simd_swizzle!(v, [3, 1]);
/// assert_eq!(r.to_array(), [3., 1.]);
/// ```
///
/// ## Two source vectors
/// ```
/// # #![feature(portable_simd)]
/// # use core_simd::{Simd, simd_swizzle, Which};
/// use Which::*;
/// let a = Simd::<f32, 4>::from_array([0., 1., 2., 3.]);
/// let b = Simd::<f32, 4>::from_array([4., 5., 6., 7.]);
///
/// // Keeping the same size
/// let r = simd_swizzle!(a, b, [First(0), First(1), Second(2), Second(3)]);
/// assert_eq!(r.to_array(), [0., 1., 6., 7.]);
///
/// // Changing the number of lanes
/// let r = simd_swizzle!(a, b, [First(0), Second(0)]);
/// assert_eq!(r.to_array(), [0., 4.]);
/// ```
#[macro_export]
macro_rules! simd_swizzle {
    {
        $vector:expr, $index:expr $(,)?
    } => {
        {
            use $crate::simd::Swizzle;
            struct SwizzleImpl;
            impl<const LANES: usize> Swizzle<LANES, {$index.len()}> for SwizzleImpl {
                const INDEX: [usize; {$index.len()}] = $index;
            }
            SwizzleImpl::swizzle($vector)
        }
    };
    {
        $first:expr, $second:expr, $index:expr $(,)?
    } => {
        {
            use $crate::simd::{Which, Swizzle2};
            struct SwizzleImpl;
            impl<const LANES: usize> Swizzle2<LANES, {$index.len()}> for SwizzleImpl {
                const INDEX: [Which; {$index.len()}] = $index;
            }
            SwizzleImpl::swizzle2($first, $second)
        }
    }
}

/// An index into one of two vectors.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Which {
    /// Indexes the first vector.
    First(usize),
    /// Indexes the second vector.
    Second(usize),
}

/// Create a vector from the elements of another vector.
pub trait Swizzle<const INPUT_LANES: usize, const OUTPUT_LANES: usize> {
    /// Map from the lanes of the input vector to the output vector.
    const INDEX: [usize; OUTPUT_LANES];

    /// Create a new vector from the lanes of `vector`.
    ///
    /// Lane `i` of the output is `vector[Self::INDEX[i]]`.
    fn swizzle<T>(vector: Simd<T, INPUT_LANES>) -> Simd<T, OUTPUT_LANES>
    where
        T: SimdElement,
        LaneCount<INPUT_LANES>: SupportedLaneCount,
        LaneCount<OUTPUT_LANES>: SupportedLaneCount,
    {
        unsafe { intrinsics::simd_shuffle(vector, vector, Self::INDEX_IMPL) }
    }
}

/// Create a vector from the elements of two other vectors.
pub trait Swizzle2<const INPUT_LANES: usize, const OUTPUT_LANES: usize> {
    /// Map from the lanes of the input vectors to the output vector
    const INDEX: [Which; OUTPUT_LANES];

    /// Create a new vector from the lanes of `first` and `second`.
    ///
    /// Lane `i` is `first[j]` when `Self::INDEX[i]` is `First(j)`, or `second[j]` when it is
    /// `Second(j)`.
    fn swizzle2<T>(
        first: Simd<T, INPUT_LANES>,
        second: Simd<T, INPUT_LANES>,
    ) -> Simd<T, OUTPUT_LANES>
    where
        T: SimdElement,
        LaneCount<INPUT_LANES>: SupportedLaneCount,
        LaneCount<OUTPUT_LANES>: SupportedLaneCount,
    {
        unsafe { intrinsics::simd_shuffle(first, second, Self::INDEX_IMPL) }
    }
}

/// The `simd_shuffle` intrinsic expects `u32`, so do error checking and conversion here.
trait SwizzleImpl<const INPUT_LANES: usize, const OUTPUT_LANES: usize> {
    const INDEX_IMPL: [u32; OUTPUT_LANES];
}

impl<T, const INPUT_LANES: usize, const OUTPUT_LANES: usize> SwizzleImpl<INPUT_LANES, OUTPUT_LANES>
    for T
where
    T: Swizzle<INPUT_LANES, OUTPUT_LANES> + ?Sized,
{
    const INDEX_IMPL: [u32; OUTPUT_LANES] = {
        let mut output = [0; OUTPUT_LANES];
        let mut i = 0;
        while i < OUTPUT_LANES {
            let index = Self::INDEX[i];
            assert!(index as u32 as usize == index);
            assert!(index < INPUT_LANES, "source lane exceeds input lane count",);
            output[i] = index as u32;
            i += 1;
        }
        output
    };
}

/// The `simd_shuffle` intrinsic expects `u32`, so do error checking and conversion here.
trait Swizzle2Impl<const INPUT_LANES: usize, const OUTPUT_LANES: usize> {
    const INDEX_IMPL: [u32; OUTPUT_LANES];
}

impl<T, const INPUT_LANES: usize, const OUTPUT_LANES: usize> Swizzle2Impl<INPUT_LANES, OUTPUT_LANES>
    for T
where
    T: Swizzle2<INPUT_LANES, OUTPUT_LANES> + ?Sized,
{
    const INDEX_IMPL: [u32; OUTPUT_LANES] = {
        let mut output = [0; OUTPUT_LANES];
        let mut i = 0;
        while i < OUTPUT_LANES {
            let (offset, index) = match Self::INDEX[i] {
                Which::First(index) => (false, index),
                Which::Second(index) => (true, index),
            };
            assert!(index < INPUT_LANES, "source lane exceeds input lane count",);

            // lanes are indexed by the first vector, then second vector
            let index = if offset { index + INPUT_LANES } else { index };
            assert!(index as u32 as usize == index);
            output[i] = index as u32;
            i += 1;
        }
        output
    };
}

impl<T, const LANES: usize> Simd<T, LANES>
where
    T: SimdElement,
    LaneCount<LANES>: SupportedLaneCount,
{
    /// Reverse the order of the lanes in the vector.
    #[inline]
    pub fn reverse(self) -> Self {
        const fn reverse_index<const LANES: usize>() -> [usize; LANES] {
            let mut index = [0; LANES];
            let mut i = 0;
            while i < LANES {
                index[i] = LANES - i - 1;
                i += 1;
            }
            index
        }

        struct Reverse;

        impl<const LANES: usize> Swizzle<LANES, LANES> for Reverse {
            const INDEX: [usize; LANES] = reverse_index::<LANES>();
        }

        Reverse::swizzle(self)
    }

    /// Rotates the vector such that the first `OFFSET` elements of the slice move to the end
    /// while the last `LANES - OFFSET` elements move to the front. After calling `rotate_left`, the
    /// element previously in lane `OFFSET` will become the first element in the slice.
    #[inline]
    pub fn rotate_left<const OFFSET: usize>(self) -> Self {
        const fn rotate_index<const OFFSET: usize, const LANES: usize>() -> [usize; LANES] {
            let offset = OFFSET % LANES;
            let mut index = [0; LANES];
            let mut i = 0;
            while i < LANES {
                index[i] = (i + offset) % LANES;
                i += 1;
            }
            index
        }

        struct Rotate<const OFFSET: usize>;

        impl<const OFFSET: usize, const LANES: usize> Swizzle<LANES, LANES> for Rotate<OFFSET> {
            const INDEX: [usize; LANES] = rotate_index::<OFFSET, LANES>();
        }

        Rotate::<OFFSET>::swizzle(self)
    }

    /// Rotates the vector such that the first `LANES - OFFSET` elements of the vector move to
    /// the end while the last `OFFSET` elements move to the front. After calling `rotate_right`, the
    /// element previously at index `LANES - OFFSET` will become the first element in the slice.
    #[inline]
    pub fn rotate_right<const OFFSET: usize>(self) -> Self {
        const fn rotate_index<const OFFSET: usize, const LANES: usize>() -> [usize; LANES] {
            let offset = LANES - OFFSET % LANES;
            let mut index = [0; LANES];
            let mut i = 0;
            while i < LANES {
                index[i] = (i + offset) % LANES;
                i += 1;
            }
            index
        }

        struct Rotate<const OFFSET: usize>;

        impl<const OFFSET: usize, const LANES: usize> Swizzle<LANES, LANES> for Rotate<OFFSET> {
            const INDEX: [usize; LANES] = rotate_index::<OFFSET, LANES>();
        }

        Rotate::<OFFSET>::swizzle(self)
    }

    /// Interleave two vectors.
    ///
    /// Produces two vectors with lanes taken alternately from `self` and `other`.
    ///
    /// The first result contains the first `LANES / 2` lanes from `self` and `other`,
    /// alternating, starting with the first lane of `self`.
    ///
    /// The second result contains the last `LANES / 2` lanes from `self` and `other`,
    /// alternating, starting with the lane `LANES / 2` from the start of `self`.
    ///
    /// This particular permutation is efficient on many architectures.
    ///
    /// ```
    /// #![feature(portable_simd)]
    /// # use core_simd::Simd;
    /// let a = Simd::from_array([0, 1, 2, 3]);
    /// let b = Simd::from_array([4, 5, 6, 7]);
    /// let (x, y) = a.interleave(b);
    /// assert_eq!(x.to_array(), [0, 4, 1, 5]);
    /// assert_eq!(y.to_array(), [2, 6, 3, 7]);
    /// ```
    #[inline]
    pub fn interleave(self, other: Self) -> (Self, Self) {
        const fn lo<const LANES: usize>() -> [Which; LANES] {
            let mut idx = [Which::First(0); LANES];
            let mut i = 0;
            while i < LANES {
                let offset = i / 2;
                idx[i] = if i % 2 == 0 {
                    Which::First(offset)
                } else {
                    Which::Second(offset)
                };
                i += 1;
            }
            idx
        }
        const fn hi<const LANES: usize>() -> [Which; LANES] {
            let mut idx = [Which::First(0); LANES];
            let mut i = 0;
            while i < LANES {
                let offset = (LANES + i) / 2;
                idx[i] = if i % 2 == 0 {
                    Which::First(offset)
                } else {
                    Which::Second(offset)
                };
                i += 1;
            }
            idx
        }

        struct Lo;
        struct Hi;

        impl<const LANES: usize> Swizzle2<LANES, LANES> for Lo {
            const INDEX: [Which; LANES] = lo::<LANES>();
        }

        impl<const LANES: usize> Swizzle2<LANES, LANES> for Hi {
            const INDEX: [Which; LANES] = hi::<LANES>();
        }

        (Lo::swizzle2(self, other), Hi::swizzle2(self, other))
    }

    /// Deinterleave two vectors.
    ///
    /// The first result takes every other lane of `self` and then `other`, starting with
    /// the first lane.
    ///
    /// The second result takes every other lane of `self` and then `other`, starting with
    /// the second lane.
    ///
    /// This particular permutation is efficient on many architectures.
    ///
    /// ```
    /// #![feature(portable_simd)]
    /// # use core_simd::Simd;
    /// let a = Simd::from_array([0, 4, 1, 5]);
    /// let b = Simd::from_array([2, 6, 3, 7]);
    /// let (x, y) = a.deinterleave(b);
    /// assert_eq!(x.to_array(), [0, 1, 2, 3]);
    /// assert_eq!(y.to_array(), [4, 5, 6, 7]);
    /// ```
    #[inline]
    pub fn deinterleave(self, other: Self) -> (Self, Self) {
        const fn even<const LANES: usize>() -> [Which; LANES] {
            let mut idx = [Which::First(0); LANES];
            let mut i = 0;
            while i < LANES / 2 {
                idx[i] = Which::First(2 * i);
                idx[i + LANES / 2] = Which::Second(2 * i);
                i += 1;
            }
            idx
        }
        const fn odd<const LANES: usize>() -> [Which; LANES] {
            let mut idx = [Which::First(0); LANES];
            let mut i = 0;
            while i < LANES / 2 {
                idx[i] = Which::First(2 * i + 1);
                idx[i + LANES / 2] = Which::Second(2 * i + 1);
                i += 1;
            }
            idx
        }

        struct Even;
        struct Odd;

        impl<const LANES: usize> Swizzle2<LANES, LANES> for Even {
            const INDEX: [Which; LANES] = even::<LANES>();
        }

        impl<const LANES: usize> Swizzle2<LANES, LANES> for Odd {
            const INDEX: [Which; LANES] = odd::<LANES>();
        }

        (Even::swizzle2(self, other), Odd::swizzle2(self, other))
    }
}
<commit_msg>Improve docs<commit_after>use crate::simd::intrinsics;
use crate::{LaneCount, Simd, SimdElement, SupportedLaneCount};

/// Constructs a new vector by selecting values from the lanes of the source vector or vectors to use.
///
/// When swizzling one vector, the indices of the result vector are indicated by a `const` array
/// of `usize`, like [`Swizzle`].
/// When swizzling two vectors, the indices are indicated by a `const` array of [`Which`], like
/// [`Swizzle2`].
///
/// # Examples
/// ## One source vector
/// ```
/// # #![feature(portable_simd)]
/// # use core_simd::{Simd, simd_swizzle};
/// let v = Simd::<f32, 4>::from_array([0., 1., 2., 3.]);
///
/// // Keeping the same size
/// let r = simd_swizzle!(v, [3, 0, 1, 2]);
/// assert_eq!(r.to_array(), [3., 0., 1., 2.]);
///
/// // Changing the number of lanes
/// let r = simd_swizzle!(v, [3, 1]);
/// assert_eq!(r.to_array(), [3., 1.]);
/// ```
///
/// ## Two source vectors
/// ```
/// # #![feature(portable_simd)]
/// # use core_simd::{Simd, simd_swizzle, Which};
/// use Which::*;
/// let a = Simd::<f32, 4>::from_array([0., 1., 2., 3.]);
/// let b = Simd::<f32, 4>::from_array([4., 5., 6., 7.]);
///
/// // Keeping the same size
/// let r = simd_swizzle!(a, b, [First(0), First(1), Second(2), Second(3)]);
/// assert_eq!(r.to_array(), [0., 1., 6., 7.]);
///
/// // Changing the number of lanes
/// let r = simd_swizzle!(a, b, [First(0), Second(0)]);
/// assert_eq!(r.to_array(), [0., 4.]);
/// ```
#[macro_export]
macro_rules! simd_swizzle {
    {
        $vector:expr, $index:expr $(,)?
    } => {
        {
            use $crate::simd::Swizzle;
            struct Impl;
            impl<const LANES: usize> Swizzle<LANES, {$index.len()}> for Impl {
                const INDEX: [usize; {$index.len()}] = $index;
            }
            Impl::swizzle($vector)
        }
    };
    {
        $first:expr, $second:expr, $index:expr $(,)?
    } => {
        {
            use $crate::simd::{Which, Swizzle2};
            struct Impl;
            impl<const LANES: usize> Swizzle2<LANES, {$index.len()}> for Impl {
                const INDEX: [Which; {$index.len()}] = $index;
            }
            Impl::swizzle2($first, $second)
        }
    }
}

/// An index into one of two vectors.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Which {
    /// Indexes the first vector.
    First(usize),
    /// Indexes the second vector.
    Second(usize),
}

/// Create a vector from the elements of another vector.
pub trait Swizzle<const INPUT_LANES: usize, const OUTPUT_LANES: usize> {
    /// Map from the lanes of the input vector to the output vector.
    const INDEX: [usize; OUTPUT_LANES];

    /// Create a new vector from the lanes of `vector`.
    ///
    /// Lane `i` of the output is `vector[Self::INDEX[i]]`.
    fn swizzle<T>(vector: Simd<T, INPUT_LANES>) -> Simd<T, OUTPUT_LANES>
    where
        T: SimdElement,
        LaneCount<INPUT_LANES>: SupportedLaneCount,
        LaneCount<OUTPUT_LANES>: SupportedLaneCount,
    {
        unsafe { intrinsics::simd_shuffle(vector, vector, Self::INDEX_IMPL) }
    }
}

/// Create a vector from the elements of two other vectors.
pub trait Swizzle2<const INPUT_LANES: usize, const OUTPUT_LANES: usize> {
    /// Map from the lanes of the input vectors to the output vector
    const INDEX: [Which; OUTPUT_LANES];

    /// Create a new vector from the lanes of `first` and `second`.
    ///
    /// Lane `i` is `first[j]` when `Self::INDEX[i]` is `First(j)`, or `second[j]` when it is
    /// `Second(j)`.
    fn swizzle2<T>(
        first: Simd<T, INPUT_LANES>,
        second: Simd<T, INPUT_LANES>,
    ) -> Simd<T, OUTPUT_LANES>
    where
        T: SimdElement,
        LaneCount<INPUT_LANES>: SupportedLaneCount,
        LaneCount<OUTPUT_LANES>: SupportedLaneCount,
    {
        unsafe { intrinsics::simd_shuffle(first, second, Self::INDEX_IMPL) }
    }
}

/// The `simd_shuffle` intrinsic expects `u32`, so do error checking and conversion here.
/// This trait hides `INDEX_IMPL` from the public API.
trait SwizzleImpl<const INPUT_LANES: usize, const OUTPUT_LANES: usize> {
    const INDEX_IMPL: [u32; OUTPUT_LANES];
}

impl<T, const INPUT_LANES: usize, const OUTPUT_LANES: usize> SwizzleImpl<INPUT_LANES, OUTPUT_LANES>
    for T
where
    T: Swizzle<INPUT_LANES, OUTPUT_LANES> + ?Sized,
{
    const INDEX_IMPL: [u32; OUTPUT_LANES] = {
        let mut output = [0; OUTPUT_LANES];
        let mut i = 0;
        while i < OUTPUT_LANES {
            let index = Self::INDEX[i];
            assert!(index as u32 as usize == index);
            assert!(index < INPUT_LANES, "source lane exceeds input lane count",);
            output[i] = index as u32;
            i += 1;
        }
        output
    };
}

/// The `simd_shuffle` intrinsic expects `u32`, so do error checking and conversion here.
/// This trait hides `INDEX_IMPL` from the public API.
trait Swizzle2Impl<const INPUT_LANES: usize, const OUTPUT_LANES: usize> {
    const INDEX_IMPL: [u32; OUTPUT_LANES];
}

impl<T, const INPUT_LANES: usize, const OUTPUT_LANES: usize> Swizzle2Impl<INPUT_LANES, OUTPUT_LANES>
    for T
where
    T: Swizzle2<INPUT_LANES, OUTPUT_LANES> + ?Sized,
{
    const INDEX_IMPL: [u32; OUTPUT_LANES] = {
        let mut output = [0; OUTPUT_LANES];
        let mut i = 0;
        while i < OUTPUT_LANES {
            let (offset, index) = match Self::INDEX[i] {
                Which::First(index) => (false, index),
                Which::Second(index) => (true, index),
            };
            assert!(index < INPUT_LANES, "source lane exceeds input lane count",);

            // lanes are indexed by the first vector, then second vector
            let index = if offset { index + INPUT_LANES } else { index };
            assert!(index as u32 as usize == index);
            output[i] = index as u32;
            i += 1;
        }
        output
    };
}

impl<T, const LANES: usize> Simd<T, LANES>
where
    T: SimdElement,
    LaneCount<LANES>: SupportedLaneCount,
{
    /// Reverse the order of the lanes in the vector.
    #[inline]
    pub fn reverse(self) -> Self {
        const fn reverse_index<const LANES: usize>() -> [usize; LANES] {
            let mut index = [0; LANES];
            let mut i = 0;
            while i < LANES {
                index[i] = LANES - i - 1;
                i += 1;
            }
            index
        }

        struct Reverse;

        impl<const LANES: usize> Swizzle<LANES, LANES> for Reverse {
            const INDEX: [usize; LANES] = reverse_index::<LANES>();
        }

        Reverse::swizzle(self)
    }

    /// Rotates the vector such that the first `OFFSET` elements of the slice move to the end
    /// while the last `LANES - OFFSET` elements move to the front. After calling `rotate_left`, the
    /// element previously in lane `OFFSET` will become the first element in the slice.
    #[inline]
    pub fn rotate_left<const OFFSET: usize>(self) -> Self {
        const fn rotate_index<const OFFSET: usize, const LANES: usize>() -> [usize; LANES] {
            let offset = OFFSET % LANES;
            let mut index = [0; LANES];
            let mut i = 0;
            while i < LANES {
                index[i] = (i + offset) % LANES;
                i += 1;
            }
            index
        }

        struct Rotate<const OFFSET: usize>;

        impl<const OFFSET: usize, const LANES: usize> Swizzle<LANES, LANES> for Rotate<OFFSET> {
            const INDEX: [usize; LANES] = rotate_index::<OFFSET, LANES>();
        }

        Rotate::<OFFSET>::swizzle(self)
    }

    /// Rotates the vector such that the first `LANES - OFFSET` elements of the vector move to
    /// the end while the last `OFFSET` elements move to the front. After calling `rotate_right`, the
    /// element previously at index `LANES - OFFSET` will become the first element in the slice.
    #[inline]
    pub fn rotate_right<const OFFSET: usize>(self) -> Self {
        const fn rotate_index<const OFFSET: usize, const LANES: usize>() -> [usize; LANES] {
            let offset = LANES - OFFSET % LANES;
            let mut index = [0; LANES];
            let mut i = 0;
            while i < LANES {
                index[i] = (i + offset) % LANES;
                i += 1;
            }
            index
        }

        struct Rotate<const OFFSET: usize>;

        impl<const OFFSET: usize, const LANES: usize> Swizzle<LANES, LANES> for Rotate<OFFSET> {
            const INDEX: [usize; LANES] = rotate_index::<OFFSET, LANES>();
        }

        Rotate::<OFFSET>::swizzle(self)
    }

    /// Interleave two vectors.
    ///
    /// Produces two vectors with lanes taken alternately from `self` and `other`.
    ///
    /// The first result contains the first `LANES / 2` lanes from `self` and `other`,
    /// alternating, starting with the first lane of `self`.
    ///
    /// The second result contains the last `LANES / 2` lanes from `self` and `other`,
    /// alternating, starting with the lane `LANES / 2` from the start of `self`.
    ///
    /// ```
    /// #![feature(portable_simd)]
    /// # use core_simd::Simd;
    /// let a = Simd::from_array([0, 1, 2, 3]);
    /// let b = Simd::from_array([4, 5, 6, 7]);
    /// let (x, y) = a.interleave(b);
    /// assert_eq!(x.to_array(), [0, 4, 1, 5]);
    /// assert_eq!(y.to_array(), [2, 6, 3, 7]);
    /// ```
    #[inline]
    pub fn interleave(self, other: Self) -> (Self, Self) {
        const fn lo<const LANES: usize>() -> [Which; LANES] {
            let mut idx = [Which::First(0); LANES];
            let mut i = 0;
            while i < LANES {
                let offset = i / 2;
                idx[i] = if i % 2 == 0 {
                    Which::First(offset)
                } else {
                    Which::Second(offset)
                };
                i += 1;
            }
            idx
        }
        const fn hi<const LANES: usize>() -> [Which; LANES] {
            let mut idx = [Which::First(0); LANES];
            let mut i = 0;
            while i < LANES {
                let offset = (LANES + i) / 2;
                idx[i] = if i % 2 == 0 {
                    Which::First(offset)
                } else {
                    Which::Second(offset)
                };
                i += 1;
            }
            idx
        }

        struct Lo;
        struct Hi;

        impl<const LANES: usize> Swizzle2<LANES, LANES> for Lo {
            const INDEX: [Which; LANES] = lo::<LANES>();
        }

        impl<const LANES: usize> Swizzle2<LANES, LANES> for Hi {
            const INDEX: [Which; LANES] = hi::<LANES>();
        }

        (Lo::swizzle2(self, other), Hi::swizzle2(self, other))
    }

    /// Deinterleave two vectors.
    ///
    /// The first result takes every other lane of `self` and then `other`, starting with
    /// the first lane.
    ///
    /// The second result takes every other lane of `self` and then `other`, starting with
    /// the second lane.
    ///
    /// ```
    /// #![feature(portable_simd)]
    /// # use core_simd::Simd;
    /// let a = Simd::from_array([0, 4, 1, 5]);
    /// let b = Simd::from_array([2, 6, 3, 7]);
    /// let (x, y) = a.deinterleave(b);
    /// assert_eq!(x.to_array(), [0, 1, 2, 3]);
    /// assert_eq!(y.to_array(), [4, 5, 6, 7]);
    /// ```
    #[inline]
    pub fn deinterleave(self, other: Self) -> (Self, Self) {
        const fn even<const LANES: usize>() -> [Which; LANES] {
            let mut idx = [Which::First(0); LANES];
            let mut i = 0;
            while i < LANES / 2 {
                idx[i] = Which::First(2 * i);
                idx[i + LANES / 2] = Which::Second(2 * i);
                i += 1;
            }
            idx
        }
        const fn odd<const LANES: usize>() -> [Which; LANES] {
            let mut idx = [Which::First(0); LANES];
            let mut i = 0;
            while i < LANES / 2 {
                idx[i] = Which::First(2 * i + 1);
                idx[i + LANES / 2] = Which::Second(2 * i + 1);
                i += 1;
            }
            idx
        }

        struct Even;
        struct Odd;

        impl<const LANES: usize> Swizzle2<LANES, LANES> for Even {
            const INDEX: [Which; LANES] = even::<LANES>();
        }

        impl<const LANES: usize> Swizzle2<LANES, LANES> for Odd {
            const INDEX: [Which; LANES] = odd::<LANES>();
        }

        (Even::swizzle2(self, other), Odd::swizzle2(self, other))
    }
}
<|endoftext|>


<commit_before>use std::{
    fmt, time,
    sync::Arc,
};

use rustc_hash::FxHashMap;
use ra_db::{
    SourceRootId, FileId, CrateGraph, SourceDatabase, SourceRoot,
    salsa::{Database, SweepStrategy},
};
use ra_syntax::SourceFile;
use ra_prof::profile;
use relative_path::RelativePathBuf;
use rayon::prelude::*;

use crate::{
    db::RootDatabase,
    symbol_index::{SymbolIndex, SymbolsDatabase},
    status::syntax_tree_stats,
};

#[derive(Default)]
pub struct AnalysisChange {
    new_roots: Vec<(SourceRootId, bool)>,
    roots_changed: FxHashMap<SourceRootId, RootChange>,
    files_changed: Vec<(FileId, Arc<String>)>,
    libraries_added: Vec<LibraryData>,
    crate_graph: Option<CrateGraph>,
}

impl fmt::Debug for AnalysisChange {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let mut d = fmt.debug_struct("AnalysisChange");
        if !self.new_roots.is_empty() {
            d.field("new_roots", &self.new_roots);
        }
        if !self.roots_changed.is_empty() {
            d.field("roots_changed", &self.roots_changed);
        }
        if !self.files_changed.is_empty() {
            d.field("files_changed", &self.files_changed.len());
        }
        if !self.libraries_added.is_empty() {
            d.field("libraries_added", &self.libraries_added.len());
        }
        if !self.crate_graph.is_some() {
            d.field("crate_graph", &self.crate_graph);
        }
        d.finish()
    }
}

impl AnalysisChange {
    pub fn new() -> AnalysisChange {
        AnalysisChange::default()
    }

    pub fn add_root(&mut self, root_id: SourceRootId, is_local: bool) {
        self.new_roots.push((root_id, is_local));
    }

    pub fn add_file(
        &mut self,
        root_id: SourceRootId,
        file_id: FileId,
        path: RelativePathBuf,
        text: Arc<String>,
    ) {
        let file = AddFile { file_id, path, text };
        self.roots_changed.entry(root_id).or_default().added.push(file);
    }

    pub fn change_file(&mut self, file_id: FileId, new_text: Arc<String>) {
        self.files_changed.push((file_id, new_text))
    }

    pub fn remove_file(&mut self, root_id: SourceRootId, file_id: FileId, path: RelativePathBuf) {
        let file = RemoveFile { file_id, path };
        self.roots_changed.entry(root_id).or_default().removed.push(file);
    }

    pub fn add_library(&mut self, data: LibraryData) {
        self.libraries_added.push(data)
    }

    pub fn set_crate_graph(&mut self, graph: CrateGraph) {
        self.crate_graph = Some(graph);
    }
}

#[derive(Debug)]
struct AddFile {
    file_id: FileId,
    path: RelativePathBuf,
    text: Arc<String>,
}

#[derive(Debug)]
struct RemoveFile {
    file_id: FileId,
    path: RelativePathBuf,
}

#[derive(Default)]
struct RootChange {
    added: Vec<AddFile>,
    removed: Vec<RemoveFile>,
}

impl fmt::Debug for RootChange {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("AnalysisChange")
            .field("added", &self.added.len())
            .field("removed", &self.removed.len())
            .finish()
    }
}

pub struct LibraryData {
    root_id: SourceRootId,
    root_change: RootChange,
    symbol_index: SymbolIndex,
}

impl fmt::Debug for LibraryData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("LibraryData")
            .field("root_id", &self.root_id)
            .field("root_change", &self.root_change)
            .field("n_symbols", &self.symbol_index.len())
            .finish()
    }
}

impl LibraryData {
    pub fn prepare(
        root_id: SourceRootId,
        files: Vec<(FileId, RelativePathBuf, Arc<String>)>,
    ) -> LibraryData {
        let symbol_index = SymbolIndex::for_files(files.par_iter().map(|(file_id, _, text)| {
            let file = SourceFile::parse(text);
            (*file_id, file)
        }));
        let mut root_change = RootChange::default();
        root_change.added = files
            .into_iter()
            .map(|(file_id, path, text)| AddFile { file_id, path, text })
            .collect();
        LibraryData { root_id, root_change, symbol_index }
    }
}

const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100);

impl RootDatabase {
    pub(crate) fn apply_change(&mut self, change: AnalysisChange) {
        let _p = profile("RootDatabase::apply_change");
        log::info!("apply_change {:?}", change);
        if !change.new_roots.is_empty() {
            let mut local_roots = Vec::clone(&self.local_roots());
            for (root_id, is_local) in change.new_roots {
                self.set_source_root(root_id, Default::default());
                if is_local {
                    local_roots.push(root_id);
                }
            }
            self.set_local_roots(Arc::new(local_roots));
        }

        for (root_id, root_change) in change.roots_changed {
            self.apply_root_change(root_id, root_change);
        }
        for (file_id, text) in change.files_changed {
            self.set_file_text(file_id, text)
        }
        if !change.libraries_added.is_empty() {
            let mut libraries = Vec::clone(&self.library_roots());
            for library in change.libraries_added {
                libraries.push(library.root_id);
                self.set_source_root(library.root_id, Default::default());
                self.set_constant_library_symbols(library.root_id, Arc::new(library.symbol_index));
                self.apply_root_change(library.root_id, library.root_change);
            }
            self.set_library_roots(Arc::new(libraries));
        }
        if let Some(crate_graph) = change.crate_graph {
            self.set_crate_graph(Arc::new(crate_graph))
        }
    }

    fn apply_root_change(&mut self, root_id: SourceRootId, root_change: RootChange) {
        let mut source_root = SourceRoot::clone(&self.source_root(root_id));
        for add_file in root_change.added {
            self.set_file_text(add_file.file_id, add_file.text);
            self.set_file_relative_path(add_file.file_id, add_file.path.clone());
            self.set_file_source_root(add_file.file_id, root_id);
            source_root.files.insert(add_file.path, add_file.file_id);
        }
        for remove_file in root_change.removed {
            self.set_file_text(remove_file.file_id, Default::default());
            source_root.files.remove(&remove_file.path);
        }
        self.set_source_root(root_id, Arc::new(source_root));
    }

    pub(crate) fn maybe_collect_garbage(&mut self) {
        if self.last_gc_check.elapsed() > GC_COOLDOWN {
            self.last_gc_check = time::Instant::now();
            let retained_trees = syntax_tree_stats(self).retained;
            if retained_trees > 100 {
                log::info!("automatic garbadge collection, {} retained trees", retained_trees);
                self.collect_garbage();
            }
        }
    }

    pub(crate) fn collect_garbage(&mut self) {
        let _p = profile("RootDatabase::collect_garbage");
        self.last_gc = time::Instant::now();

        let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();

        self.query(ra_db::ParseQuery).sweep(sweep);

        self.query(hir::db::ParseOrExpandQuery).sweep(sweep);
        self.query(hir::db::AstIdMapQuery).sweep(sweep);
        self.query(hir::db::AstIdToNodeQuery).sweep(sweep);

        self.query(hir::db::RawItemsWithSourceMapQuery).sweep(sweep);
        self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep);
    }
}
<commit_msg>specifically profile cancellation<commit_after>use std::{
    fmt, time,
    sync::Arc,
};

use rustc_hash::FxHashMap;
use ra_db::{
    SourceRootId, FileId, CrateGraph, SourceDatabase, SourceRoot,
    salsa::{Database, SweepStrategy},
};
use ra_syntax::SourceFile;
use ra_prof::profile;
use relative_path::RelativePathBuf;
use rayon::prelude::*;

use crate::{
    db::RootDatabase,
    symbol_index::{SymbolIndex, SymbolsDatabase},
    status::syntax_tree_stats,
};

#[derive(Default)]
pub struct AnalysisChange {
    new_roots: Vec<(SourceRootId, bool)>,
    roots_changed: FxHashMap<SourceRootId, RootChange>,
    files_changed: Vec<(FileId, Arc<String>)>,
    libraries_added: Vec<LibraryData>,
    crate_graph: Option<CrateGraph>,
}

impl fmt::Debug for AnalysisChange {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let mut d = fmt.debug_struct("AnalysisChange");
        if !self.new_roots.is_empty() {
            d.field("new_roots", &self.new_roots);
        }
        if !self.roots_changed.is_empty() {
            d.field("roots_changed", &self.roots_changed);
        }
        if !self.files_changed.is_empty() {
            d.field("files_changed", &self.files_changed.len());
        }
        if !self.libraries_added.is_empty() {
            d.field("libraries_added", &self.libraries_added.len());
        }
        if !self.crate_graph.is_some() {
            d.field("crate_graph", &self.crate_graph);
        }
        d.finish()
    }
}

impl AnalysisChange {
    pub fn new() -> AnalysisChange {
        AnalysisChange::default()
    }

    pub fn add_root(&mut self, root_id: SourceRootId, is_local: bool) {
        self.new_roots.push((root_id, is_local));
    }

    pub fn add_file(
        &mut self,
        root_id: SourceRootId,
        file_id: FileId,
        path: RelativePathBuf,
        text: Arc<String>,
    ) {
        let file = AddFile { file_id, path, text };
        self.roots_changed.entry(root_id).or_default().added.push(file);
    }

    pub fn change_file(&mut self, file_id: FileId, new_text: Arc<String>) {
        self.files_changed.push((file_id, new_text))
    }

    pub fn remove_file(&mut self, root_id: SourceRootId, file_id: FileId, path: RelativePathBuf) {
        let file = RemoveFile { file_id, path };
        self.roots_changed.entry(root_id).or_default().removed.push(file);
    }

    pub fn add_library(&mut self, data: LibraryData) {
        self.libraries_added.push(data)
    }

    pub fn set_crate_graph(&mut self, graph: CrateGraph) {
        self.crate_graph = Some(graph);
    }
}

#[derive(Debug)]
struct AddFile {
    file_id: FileId,
    path: RelativePathBuf,
    text: Arc<String>,
}

#[derive(Debug)]
struct RemoveFile {
    file_id: FileId,
    path: RelativePathBuf,
}

#[derive(Default)]
struct RootChange {
    added: Vec<AddFile>,
    removed: Vec<RemoveFile>,
}

impl fmt::Debug for RootChange {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("AnalysisChange")
            .field("added", &self.added.len())
            .field("removed", &self.removed.len())
            .finish()
    }
}

pub struct LibraryData {
    root_id: SourceRootId,
    root_change: RootChange,
    symbol_index: SymbolIndex,
}

impl fmt::Debug for LibraryData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("LibraryData")
            .field("root_id", &self.root_id)
            .field("root_change", &self.root_change)
            .field("n_symbols", &self.symbol_index.len())
            .finish()
    }
}

impl LibraryData {
    pub fn prepare(
        root_id: SourceRootId,
        files: Vec<(FileId, RelativePathBuf, Arc<String>)>,
    ) -> LibraryData {
        let symbol_index = SymbolIndex::for_files(files.par_iter().map(|(file_id, _, text)| {
            let file = SourceFile::parse(text);
            (*file_id, file)
        }));
        let mut root_change = RootChange::default();
        root_change.added = files
            .into_iter()
            .map(|(file_id, path, text)| AddFile { file_id, path, text })
            .collect();
        LibraryData { root_id, root_change, symbol_index }
    }
}

const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100);

impl RootDatabase {
    pub(crate) fn apply_change(&mut self, change: AnalysisChange) {
        let _p = profile("RootDatabase::apply_change");
        log::info!("apply_change {:?}", change);
        {
            let _p = profile("RootDatabase::apply_change/cancellation");
            self.salsa_runtime().next_revision();
        }
        if !change.new_roots.is_empty() {
            let mut local_roots = Vec::clone(&self.local_roots());
            for (root_id, is_local) in change.new_roots {
                self.set_source_root(root_id, Default::default());
                if is_local {
                    local_roots.push(root_id);
                }
            }
            self.set_local_roots(Arc::new(local_roots));
        }

        for (root_id, root_change) in change.roots_changed {
            self.apply_root_change(root_id, root_change);
        }
        for (file_id, text) in change.files_changed {
            self.set_file_text(file_id, text)
        }
        if !change.libraries_added.is_empty() {
            let mut libraries = Vec::clone(&self.library_roots());
            for library in change.libraries_added {
                libraries.push(library.root_id);
                self.set_source_root(library.root_id, Default::default());
                self.set_constant_library_symbols(library.root_id, Arc::new(library.symbol_index));
                self.apply_root_change(library.root_id, library.root_change);
            }
            self.set_library_roots(Arc::new(libraries));
        }
        if let Some(crate_graph) = change.crate_graph {
            self.set_crate_graph(Arc::new(crate_graph))
        }
    }

    fn apply_root_change(&mut self, root_id: SourceRootId, root_change: RootChange) {
        let mut source_root = SourceRoot::clone(&self.source_root(root_id));
        for add_file in root_change.added {
            self.set_file_text(add_file.file_id, add_file.text);
            self.set_file_relative_path(add_file.file_id, add_file.path.clone());
            self.set_file_source_root(add_file.file_id, root_id);
            source_root.files.insert(add_file.path, add_file.file_id);
        }
        for remove_file in root_change.removed {
            self.set_file_text(remove_file.file_id, Default::default());
            source_root.files.remove(&remove_file.path);
        }
        self.set_source_root(root_id, Arc::new(source_root));
    }

    pub(crate) fn maybe_collect_garbage(&mut self) {
        if self.last_gc_check.elapsed() > GC_COOLDOWN {
            self.last_gc_check = time::Instant::now();
            let retained_trees = syntax_tree_stats(self).retained;
            if retained_trees > 100 {
                log::info!("automatic garbadge collection, {} retained trees", retained_trees);
                self.collect_garbage();
            }
        }
    }

    pub(crate) fn collect_garbage(&mut self) {
        let _p = profile("RootDatabase::collect_garbage");
        self.last_gc = time::Instant::now();

        let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();

        self.query(ra_db::ParseQuery).sweep(sweep);

        self.query(hir::db::ParseOrExpandQuery).sweep(sweep);
        self.query(hir::db::AstIdMapQuery).sweep(sweep);
        self.query(hir::db::AstIdToNodeQuery).sweep(sweep);

        self.query(hir::db::RawItemsWithSourceMapQuery).sweep(sweep);
        self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep);
    }
}
<|endoftext|>


<commit_before>extern crate glm;

use sdl2::EventPump;
use sdl2::event::EventPollIterator;
use sdl2::event::Event;
use sdl2::mouse::Mouse;
use sdl2::keyboard::Keycode;
use std::collections::HashSet;

pub trait EventStreamGenerator<'a> {
    type I: Iterator<Item = Event>;
    fn next(&'a mut self) -> EventStream<Self::I>;
}

pub struct SdlEventStreamGenerator {
    pub event_pump: EventPump,
}

pub struct EventStream<I> {
    event_iterator: I,
}

impl<I: Iterator<Item = Event>> Iterator for EventStream<I> {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        self.event_iterator.next()
    }
}

impl<'a> EventStreamGenerator<'a> for SdlEventStreamGenerator {
    type I = EventPollIterator<'a>;

    fn next(&'a mut self) -> EventStream<EventPollIterator> {
        let event_iterator = self.event_pump.poll_iter();
        EventStream { event_iterator: event_iterator }
    }
}

pub struct InputManager<E> {
    pressed_keys: HashSet<Keycode>,
    pressed_buttons: HashSet<Mouse>,
    mouse_coords: glm::IVec2,
    event_stream_generator: E,
}

impl<'a, E> InputManager<E>
    where E: EventStreamGenerator<'a>
{
    pub fn new(events_generator: E) -> InputManager<E>
        where E: EventStreamGenerator<'a>
    {
        InputManager {
            pressed_keys: HashSet::new(),
            pressed_buttons: HashSet::new(),
            mouse_coords: glm::ivec2(0, 0),
            event_stream_generator: events_generator,
        }
    }

    pub fn update(&'a mut self) {
        let event_stream = self.event_stream_generator.next();
        for event in event_stream {
            match event {
                Event::KeyDown { keycode: Some(keycode), .. } => {
                    self.pressed_keys.insert(keycode);
                }
                Event::KeyUp { keycode: Some(keycode), .. } => {
                    self.pressed_keys.remove(&keycode);
                }
                Event::MouseMotion { x, y, .. } => {
                    self.mouse_coords = glm::ivec2(x, y);
                }
                Event::MouseButtonDown { mouse_btn, .. } => {
                    self.pressed_buttons.insert(mouse_btn);
                }
                Event::MouseButtonUp { mouse_btn, .. } => {
                    self.pressed_buttons.remove(&mouse_btn);
                }
                _ => {}
            }
        }
    }

    pub fn is_key_down(&self, keycode: Keycode) -> bool {
        self.pressed_keys.contains(&keycode)
    }

    pub fn is_mouse_down(&self, mouse: Mouse) -> bool {
        self.pressed_buttons.contains(&mouse)
    }

    pub fn mouse_coords(&self) -> glm::IVec2 {
        self.mouse_coords
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use sdl2::keyboard::Keycode;
    use sdl2::event::Event;
    use sdl2::keyboard::NOMOD;

    struct MockEventIterator {
        events: Vec<Event>,
    }

    impl Iterator for MockEventIterator {
        type Item = Event;

        fn next(&mut self) -> Option<Event> {
            self.events.pop()
        }
    }

    struct MockEventStreamGenerator {
        streams: Vec<MockEventIterator>,
    }

    impl<'a> EventStreamGenerator<'a> for MockEventStreamGenerator {
        type I = MockEventIterator;

        fn next(&'a mut self) -> EventStream<MockEventIterator> {
            let stream = self.streams.pop().unwrap();
            EventStream { event_iterator: stream }
        }
    }

    #[test]
    fn it_adds_pressed_keys() {
        let event_key_down = Event::KeyDown {
            keycode: Some(Keycode::Down),
            timestamp: 0,
            window_id: 0,
            scancode: None,
            repeat: false,
            keymod: NOMOD,
        };
        let streams = vec![MockEventIterator { events: vec![event_key_down] }];
        let generator = MockEventStreamGenerator { streams: streams };
        let mut subject = InputManager::new(generator);
        assert_eq!(subject.is_key_down(Keycode::Down), false);
        subject.update();
        assert_eq!(subject.is_key_down(Keycode::Down), true);
    }

    #[test]
    fn it_releases_keys() {
        let event_key_down = Event::KeyDown {
            keycode: Some(Keycode::Down),
            timestamp: 0,
            window_id: 0,
            scancode: None,
            repeat: false,
            keymod: NOMOD,
        };

        let event_key_down_up = Event::KeyDown {
            keycode: Some(Keycode::Up),
            timestamp: 0,
            window_id: 0,
            scancode: None,
            repeat: false,
            keymod: NOMOD,
        };

        let event_key_up = Event::KeyUp {
            keycode: Some(Keycode::Down),
            timestamp: 0,
            window_id: 0,
            scancode: None,
            repeat: false,
            keymod: NOMOD,
        };

        let streams = vec![MockEventIterator { events: vec![event_key_up] },
                           MockEventIterator { events: vec![event_key_down, event_key_down_up] },];
        let generator = MockEventStreamGenerator { streams: streams };
        let mut subject = InputManager::new(generator);
        subject.update();
        assert_eq!(subject.is_key_down(Keycode::Down), true);
        assert_eq!(subject.is_key_down(Keycode::Up), true);
        subject.update();
        assert_eq!(subject.is_key_down(Keycode::Down), false);
        assert_eq!(subject.is_key_down(Keycode::Up), true);
    }
}
<commit_msg>added macro on test to create key_events<commit_after>extern crate glm;

use sdl2::EventPump;
use sdl2::event::EventPollIterator;
use sdl2::event::Event;
use sdl2::mouse::Mouse;
use sdl2::keyboard::Keycode;
use std::collections::HashSet;

pub trait EventStreamGenerator<'a> {
    type I: Iterator<Item = Event>;
    fn next(&'a mut self) -> EventStream<Self::I>;
}

pub struct SdlEventStreamGenerator {
    pub event_pump: EventPump,
}

pub struct EventStream<I> {
    event_iterator: I,
}

impl<I: Iterator<Item = Event>> Iterator for EventStream<I> {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        self.event_iterator.next()
    }
}

impl<'a> EventStreamGenerator<'a> for SdlEventStreamGenerator {
    type I = EventPollIterator<'a>;

    fn next(&'a mut self) -> EventStream<EventPollIterator> {
        let event_iterator = self.event_pump.poll_iter();
        EventStream { event_iterator: event_iterator }
    }
}

pub struct InputManager<E> {
    pressed_keys: HashSet<Keycode>,
    pressed_buttons: HashSet<Mouse>,
    mouse_coords: glm::IVec2,
    event_stream_generator: E,
}

impl<'a, E> InputManager<E>
    where E: EventStreamGenerator<'a>
{
    pub fn new(events_generator: E) -> InputManager<E>
        where E: EventStreamGenerator<'a>
    {
        InputManager {
            pressed_keys: HashSet::new(),
            pressed_buttons: HashSet::new(),
            mouse_coords: glm::ivec2(0, 0),
            event_stream_generator: events_generator,
        }
    }

    pub fn update(&'a mut self) {
        let event_stream = self.event_stream_generator.next();
        for event in event_stream {
            match event {
                Event::KeyDown { keycode: Some(keycode), .. } => {
                    self.pressed_keys.insert(keycode);
                }
                Event::KeyUp { keycode: Some(keycode), .. } => {
                    self.pressed_keys.remove(&keycode);
                }
                Event::MouseMotion { x, y, .. } => {
                    self.mouse_coords = glm::ivec2(x, y);
                }
                Event::MouseButtonDown { mouse_btn, .. } => {
                    self.pressed_buttons.insert(mouse_btn);
                }
                Event::MouseButtonUp { mouse_btn, .. } => {
                    self.pressed_buttons.remove(&mouse_btn);
                }
                _ => {}
            }
        }
    }

    pub fn is_key_down(&self, keycode: Keycode) -> bool {
        self.pressed_keys.contains(&keycode)
    }

    pub fn is_mouse_down(&self, mouse: Mouse) -> bool {
        self.pressed_buttons.contains(&mouse)
    }

    pub fn mouse_coords(&self) -> glm::IVec2 {
        self.mouse_coords
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use sdl2::keyboard::Keycode;
    use sdl2::event::Event;
    use sdl2::keyboard::NOMOD;

    struct MockEventIterator {
        events: Vec<Event>,
    }

    impl Iterator for MockEventIterator {
        type Item = Event;

        fn next(&mut self) -> Option<Event> {
            self.events.pop()
        }
    }

    struct MockEventStreamGenerator {
        streams: Vec<MockEventIterator>,
    }

    impl<'a> EventStreamGenerator<'a> for MockEventStreamGenerator {
        type I = MockEventIterator;

        fn next(&'a mut self) -> EventStream<MockEventIterator> {
            let stream = self.streams.pop().unwrap();
            EventStream { event_iterator: stream }
        }
    }

    macro_rules! key_event {
        ($t:ident, $e:expr) => {
            {
                let event = Event::$t {
                    keycode: Some($e),
                    timestamp: 0,
                    window_id: 0,
                    scancode: None,
                    repeat: false,
                    keymod: NOMOD,
                };
                event
            }
        };
    }

    #[test]
    fn it_adds_pressed_keys() {
        let down_key_down = key_event!(KeyDown, Keycode::Down);
        let streams = vec![MockEventIterator { events: vec![down_key_down] }];
        let generator = MockEventStreamGenerator { streams: streams };
        let mut subject = InputManager::new(generator);
        assert_eq!(subject.is_key_down(Keycode::Down), false);
        subject.update();
        assert_eq!(subject.is_key_down(Keycode::Down), true);
    }

    #[test]
    fn it_releases_keys() {
        let event_key_down = key_event!(KeyDown, Keycode::Down);
        let event_key_down_up = key_event!(KeyDown, Keycode::Up);
        let event_key_up = key_event!(KeyUp, Keycode::Down);

        let streams = vec![MockEventIterator { events: vec![event_key_up] },
                           MockEventIterator { events: vec![event_key_down, event_key_down_up] },];
        let generator = MockEventStreamGenerator { streams: streams };
        let mut subject = InputManager::new(generator);
        subject.update();
        assert_eq!(subject.is_key_down(Keycode::Down), true);
        assert_eq!(subject.is_key_down(Keycode::Up), true);
        subject.update();
        assert_eq!(subject.is_key_down(Keycode::Down), false);
        assert_eq!(subject.is_key_down(Keycode::Up), true);
    }
}
<|endoftext|>


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

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

fn main() {

    let mut server = Nickel::new();

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

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

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

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

    server.listen(Ipv4Addr(127, 0, 0, 1), 6767);
}
<commit_msg>Remove unused imports.<commit_after>extern crate serialize;
extern crate nickel;
extern crate http;

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

fn main() {

    let mut server = Nickel::new();

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

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

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

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

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


<commit_before>use std::{
    fmt::{self, Debug},
    ops::Deref,
    sync::atomic::Ordering::{Acquire, Release, AcqRel},
};

use crossbeam_epoch::{
    unprotected, Atomic, Guard,
    Owned, Shared,
};

use crate::pagecache::debug::debug_delay;

type CompareAndSwapResult<'g, T> = std::result::Result<
    Shared<'g, Node<T>>,
    (Shared<'g, Node<T>>, Owned<Node<T>>),
>;

/// A node in the lock-free `Stack`.
#[derive(Debug)]
pub struct Node<T: Send + 'static> {
    pub(crate) inner: T,
    pub(crate) next: Atomic<Node<T>>,
}

impl<T: Send + 'static> Drop for Node<T> {
    fn drop(&mut self) {
        unsafe {
            let next = self.next.load(Acquire, unprotected());
            if !next.as_raw().is_null() {
                drop(next.into_owned());
            }
        }
    }
}

/// A simple lock-free stack, with the ability to atomically
/// append or entirely swap-out entries.
pub struct Stack<T: Send + 'static> {
    head: Atomic<Node<T>>,
}

impl<T: Send + 'static> Default for Stack<T> {
    fn default() -> Self {
        Self {
            head: Atomic::null(),
        }
    }
}

impl<T: Send + 'static> Drop for Stack<T> {
    fn drop(&mut self) {
        unsafe {
            let curr = self.head.load(Acquire, unprotected());
            if !curr.as_raw().is_null() {
                drop(curr.into_owned());
            }
        }
    }
}

impl<T> Debug for Stack<T>
where
    T: Clone + Debug + Send + 'static + Sync,
{
    fn fmt(
        &self,
        formatter: &mut fmt::Formatter<'_>,
    ) -> std::result::Result<(), fmt::Error> {
        let guard = crossbeam_epoch::pin();
        let head = self.head(&guard);
        let iter = StackIter::from_ptr(head, &guard);

        formatter.write_str("Stack [")?;
        let mut written = false;
        for node in iter {
            if written {
                formatter.write_str(", ")?;
            }
            formatter.write_str(&*format!("({:?}) ", &node as *const _))?;
            node.fmt(formatter)?;
            written = true;
        }
        formatter.write_str("]")?;
        Ok(())
    }
}

impl<T: Send + 'static> Deref for Node<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.inner
    }
}

impl<T: Clone + Send + Sync + 'static> Stack<T> {
    /// Add an item to the stack, spinning until successful.
    pub fn push(&self, inner: T, guard: &Guard) {
        debug_delay();
        let node = Owned::new(Node {
            inner,
            next: Atomic::null(),
        });

        unsafe {
            let node = node.into_shared(guard);

            loop {
                let head = self.head(guard);
                node.deref().next.store(head, Release);
                if self
                    .head
                    .compare_and_set(head, node, Release, guard)
                    .is_ok()
                {
                    return;
                }
            }
        }
    }

    /// Pop the next item off the stack. Returns None if nothing is there.
    fn _pop(&self, guard: &Guard) -> Option<T> {
        use std::ptr;
        debug_delay();
        let mut head = self.head(&guard);
        loop {
            match unsafe { head.as_ref() } {
                Some(h) => {
                    let next = h.next.load(Acquire, &guard);
                    match self.head.compare_and_set(head, next, Release, &guard)
                    {
                        Ok(_) => unsafe {
                            // we use Acquire because we want to unset
                            // the next pointer before destruction
                            // to avoid double-frees.
                            h.next.store(Shared::default(), Acquire);
                            guard.defer_destroy(head);
                            return Some(ptr::read(&h.inner));
                        },
                        Err(h) => head = h.current,
                    }
                }
                None => return None,
            }
        }
    }

    /// compare and push
    pub fn cap_node<'g>(
        &self,
        old: Shared<'_, Node<T>>,
        mut node: Owned<Node<T>>,
        guard: &'g Guard,
    ) -> CompareAndSwapResult<'g, T> {
        // properly set next ptr
        node.next = Atomic::from(old);
        let res = self.head.compare_and_set(old, node, AcqRel, guard);

        match res {
            Err(e) => {
                // we want to set next to null to prevent
                // the current shared head from being
                // dropped when we drop this node.
                let mut returned = e.new;
                returned.next = Atomic::null();
                Err((e.current, returned))
            }
            Ok(success) => Ok(success),
        }
    }

    /// compare and swap
    pub fn cas<'g>(
        &self,
        old: Shared<'g, Node<T>>,
        new: Owned<Node<T>>,
        guard: &'g Guard,
    ) -> CompareAndSwapResult<'g, T> {
        debug_delay();
        let res = self.head.compare_and_set(old, new, AcqRel, guard);

        match res {
            Ok(success) => {
                if !old.is_null() {
                    unsafe {
                        guard.defer_destroy(old);
                    };
                }
                Ok(success)
            }
            Err(e) => Err((e.current, e.new)),
        }
    }

    /// Returns the current head pointer of the stack, which can
    /// later be used as the key for cas and cap operations.
    pub fn head<'g>(&self, guard: &'g Guard) -> Shared<'g, Node<T>> {
        self.head.load(Acquire, guard)
    }
}

/// An iterator over nodes in a lock-free stack.
pub struct StackIter<'a, T>
where
    T: Send + 'static + Sync,
{
    inner: Shared<'a, Node<T>>,
    guard: &'a Guard,
}

impl<'a, T> StackIter<'a, T>
where
    T: 'a + Send + 'static + Sync,
{
    /// Creates a StackIter from a pointer to one.
    pub fn from_ptr<'b>(
        ptr: Shared<'b, Node<T>>,
        guard: &'b Guard,
    ) -> StackIter<'b, T> {
        StackIter { inner: ptr, guard }
    }
}

impl<'a, T> Iterator for StackIter<'a, T>
where
    T: Send + 'static + Sync,
{
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        debug_delay();
        if self.inner.is_null() {
            None
        } else {
            unsafe {
                let ret = &self.inner.deref().inner;
                self.inner = self.inner.deref().next.load(Acquire, self.guard);
                Some(ret)
            }
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let mut size = 0;
        let mut cursor = self.inner;

        while !cursor.is_null() {
            unsafe {
                cursor = cursor.deref().next.load(Acquire, self.guard);
            }
            size += 1;
        }

        (size, Some(size))
    }
}

/// Turns a vector of elements into a lock-free stack
/// of them, and returns the head of the stack.
pub fn node_from_frag_vec<T>(from: Vec<T>) -> Owned<Node<T>>
where
    T: Send + 'static + Sync,
{
    let mut last = None;

    for item in from.into_iter().rev() {
        last = if let Some(last) = last {
            Some(Owned::new(Node {
                inner: item,
                next: Atomic::from(last),
            }))
        } else {
            Some(Owned::new(Node {
                inner: item,
                next: Atomic::null(),
            }))
        }
    }

    last.expect("at least one frag was provided in the from Vec")
}

#[test]
fn basic_functionality() {
    use std::sync::Arc;
    use std::thread;
    use crossbeam_epoch::pin;
    use crossbeam_utils::CachePadded;

    let guard = pin();
    let ll = Arc::new(Stack::default());
    assert_eq!(ll._pop(&guard), None);
    ll.push(CachePadded::new(1), &guard);
    let ll2 = Arc::clone(&ll);
    let t = thread::spawn(move || {
        let guard = pin();
        ll2.push(CachePadded::new(2), &guard);
        ll2.push(CachePadded::new(3), &guard);
        ll2.push(CachePadded::new(4), &guard);
        guard.flush();
    });
    t.join().unwrap();
    ll.push(CachePadded::new(5), &guard);
    assert_eq!(ll._pop(&guard), Some(CachePadded::new(5)));
    assert_eq!(ll._pop(&guard), Some(CachePadded::new(4)));
    let ll3 = Arc::clone(&ll);
    let t = thread::spawn(move || {
        let guard = pin();
        assert_eq!(ll3._pop(&guard), Some(CachePadded::new(3)));
        assert_eq!(ll3._pop(&guard), Some(CachePadded::new(2)));
        guard.flush();
    });
    t.join().unwrap();
    assert_eq!(ll._pop(&guard), Some(CachePadded::new(1)));
    let ll4 = Arc::clone(&ll);
    let t = thread::spawn(move || {
        let guard = pin();
        assert_eq!(ll4._pop(&guard), None);
        guard.flush();
    });
    t.join().unwrap();
    drop(ll);
    guard.flush();
    drop(guard);
}
<commit_msg>Small cleanup of Stack testing code<commit_after>use std::{
    fmt::{self, Debug},
    ops::Deref,
    sync::atomic::Ordering::{Acquire, Release, AcqRel},
};

use crossbeam_epoch::{
    unprotected, Atomic, Guard,
    Owned, Shared,
};

use crate::pagecache::debug::debug_delay;

type CompareAndSwapResult<'g, T> = std::result::Result<
    Shared<'g, Node<T>>,
    (Shared<'g, Node<T>>, Owned<Node<T>>),
>;

/// A node in the lock-free `Stack`.
#[derive(Debug)]
pub struct Node<T: Send + 'static> {
    pub(crate) inner: T,
    pub(crate) next: Atomic<Node<T>>,
}

impl<T: Send + 'static> Drop for Node<T> {
    fn drop(&mut self) {
        unsafe {
            let next = self.next.load(Acquire, unprotected());
            if !next.as_raw().is_null() {
                drop(next.into_owned());
            }
        }
    }
}

/// A simple lock-free stack, with the ability to atomically
/// append or entirely swap-out entries.
pub struct Stack<T: Send + 'static> {
    head: Atomic<Node<T>>,
}

impl<T: Send + 'static> Default for Stack<T> {
    fn default() -> Self {
        Self {
            head: Atomic::null(),
        }
    }
}

impl<T: Send + 'static> Drop for Stack<T> {
    fn drop(&mut self) {
        unsafe {
            let curr = self.head.load(Acquire, unprotected());
            if !curr.as_raw().is_null() {
                drop(curr.into_owned());
            }
        }
    }
}

impl<T> Debug for Stack<T>
where
    T: Clone + Debug + Send + 'static + Sync,
{
    fn fmt(
        &self,
        formatter: &mut fmt::Formatter<'_>,
    ) -> std::result::Result<(), fmt::Error> {
        let guard = crossbeam_epoch::pin();
        let head = self.head(&guard);
        let iter = StackIter::from_ptr(head, &guard);

        formatter.write_str("Stack [")?;
        let mut written = false;
        for node in iter {
            if written {
                formatter.write_str(", ")?;
            }
            formatter.write_str(&*format!("({:?}) ", &node as *const _))?;
            node.fmt(formatter)?;
            written = true;
        }
        formatter.write_str("]")?;
        Ok(())
    }
}

impl<T: Send + 'static> Deref for Node<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.inner
    }
}

impl<T: Clone + Send + Sync + 'static> Stack<T> {
    /// Add an item to the stack, spinning until successful.
    pub fn push(&self, inner: T, guard: &Guard) {
        debug_delay();
        let node = Owned::new(Node {
            inner,
            next: Atomic::null(),
        });

        unsafe {
            let node = node.into_shared(guard);

            loop {
                let head = self.head(guard);
                node.deref().next.store(head, Release);
                if self
                    .head
                    .compare_and_set(head, node, Release, guard)
                    .is_ok()
                {
                    return;
                }
            }
        }
    }

    /// Pop the next item off the stack. Returns None if nothing is there.
    #[cfg(test)]
    fn pop(&self, guard: &Guard) -> Option<T> {
        use std::ptr;
        use std::sync::atomic::Ordering::SeqCst;
        debug_delay();
        let mut head = self.head(&guard);
        loop {
            match unsafe { head.as_ref() } {
                Some(h) => {
                    let next = h.next.load(Acquire, &guard);
                    match self.head.compare_and_set(head, next, Release, &guard)
                    {
                        Ok(_) => unsafe {
                            // we unset the next pointer before destruction
                            // to avoid double-frees.
                            h.next.store(Shared::default(), SeqCst);
                            guard.defer_destroy(head);
                            return Some(ptr::read(&h.inner));
                        },
                        Err(h) => head = h.current,
                    }
                }
                None => return None,
            }
        }
    }

    /// compare and push
    pub fn cap_node<'g>(
        &self,
        old: Shared<'_, Node<T>>,
        mut node: Owned<Node<T>>,
        guard: &'g Guard,
    ) -> CompareAndSwapResult<'g, T> {
        // properly set next ptr
        node.next = Atomic::from(old);
        let res = self.head.compare_and_set(old, node, AcqRel, guard);

        match res {
            Err(e) => {
                // we want to set next to null to prevent
                // the current shared head from being
                // dropped when we drop this node.
                let mut returned = e.new;
                returned.next = Atomic::null();
                Err((e.current, returned))
            }
            Ok(success) => Ok(success),
        }
    }

    /// compare and swap
    pub fn cas<'g>(
        &self,
        old: Shared<'g, Node<T>>,
        new: Owned<Node<T>>,
        guard: &'g Guard,
    ) -> CompareAndSwapResult<'g, T> {
        debug_delay();
        let res = self.head.compare_and_set(old, new, AcqRel, guard);

        match res {
            Ok(success) => {
                if !old.is_null() {
                    unsafe {
                        guard.defer_destroy(old);
                    };
                }
                Ok(success)
            }
            Err(e) => Err((e.current, e.new)),
        }
    }

    /// Returns the current head pointer of the stack, which can
    /// later be used as the key for cas and cap operations.
    pub fn head<'g>(&self, guard: &'g Guard) -> Shared<'g, Node<T>> {
        self.head.load(Acquire, guard)
    }
}

/// An iterator over nodes in a lock-free stack.
pub struct StackIter<'a, T>
where
    T: Send + 'static + Sync,
{
    inner: Shared<'a, Node<T>>,
    guard: &'a Guard,
}

impl<'a, T> StackIter<'a, T>
where
    T: 'a + Send + 'static + Sync,
{
    /// Creates a StackIter from a pointer to one.
    pub fn from_ptr<'b>(
        ptr: Shared<'b, Node<T>>,
        guard: &'b Guard,
    ) -> StackIter<'b, T> {
        StackIter { inner: ptr, guard }
    }
}

impl<'a, T> Iterator for StackIter<'a, T>
where
    T: Send + 'static + Sync,
{
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        debug_delay();
        if self.inner.is_null() {
            None
        } else {
            unsafe {
                let ret = &self.inner.deref().inner;
                self.inner = self.inner.deref().next.load(Acquire, self.guard);
                Some(ret)
            }
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let mut size = 0;
        let mut cursor = self.inner;

        while !cursor.is_null() {
            unsafe {
                cursor = cursor.deref().next.load(Acquire, self.guard);
            }
            size += 1;
        }

        (size, Some(size))
    }
}

/// Turns a vector of elements into a lock-free stack
/// of them, and returns the head of the stack.
pub fn node_from_frag_vec<T>(from: Vec<T>) -> Owned<Node<T>>
where
    T: Send + 'static + Sync,
{
    let mut last = None;

    for item in from.into_iter().rev() {
        last = if let Some(last) = last {
            Some(Owned::new(Node {
                inner: item,
                next: Atomic::from(last),
            }))
        } else {
            Some(Owned::new(Node {
                inner: item,
                next: Atomic::null(),
            }))
        }
    }

    last.expect("at least one frag was provided in the from Vec")
}

#[test]
fn basic_functionality() {
    use std::sync::Arc;
    use std::thread;
    use crossbeam_epoch::pin;
    use crossbeam_utils::CachePadded;

    let guard = pin();
    let ll = Arc::new(Stack::default());
    assert_eq!(ll.pop(&guard), None);
    ll.push(CachePadded::new(1), &guard);
    let ll2 = Arc::clone(&ll);
    let t = thread::spawn(move || {
        let guard = pin();
        ll2.push(CachePadded::new(2), &guard);
        ll2.push(CachePadded::new(3), &guard);
        ll2.push(CachePadded::new(4), &guard);
        guard.flush();
    });
    t.join().unwrap();
    ll.push(CachePadded::new(5), &guard);
    assert_eq!(ll.pop(&guard), Some(CachePadded::new(5)));
    assert_eq!(ll.pop(&guard), Some(CachePadded::new(4)));
    let ll3 = Arc::clone(&ll);
    let t = thread::spawn(move || {
        let guard = pin();
        assert_eq!(ll3.pop(&guard), Some(CachePadded::new(3)));
        assert_eq!(ll3.pop(&guard), Some(CachePadded::new(2)));
        guard.flush();
    });
    t.join().unwrap();
    assert_eq!(ll.pop(&guard), Some(CachePadded::new(1)));
    let ll4 = Arc::clone(&ll);
    let t = thread::spawn(move || {
        let guard = pin();
        assert_eq!(ll4.pop(&guard), None);
        guard.flush();
    });
    t.join().unwrap();
    drop(ll);
    guard.flush();
    drop(guard);
}
<|endoftext|>