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

use std::collections::HashMap;
use std::io;
use std::path::{Path, PathBuf};
use std::sync::mpsc::{
    channel, sync_channel, Receiver, SendError, Sender, SyncSender, TryRecvError, TrySendError,
};
use std::thread::Builder as ThreadBuilder;

use super::file_watcher::{default_file_watcher_with_no_initial_event, Callbacks};

use hcore::fs::USER_CONFIG_FILE;
use hcore::service::ServiceGroup;
use manager::service::Service;
use manager::service::UserConfigPath;

static LOGKEY: &'static str = "UCW";

// This trait exists to ease the testing of functions that receive a Service. Creating Services
// requires a lot of ceremony, so we work around this with this trait.
pub trait Serviceable {
    fn name(&self) -> &str;
    fn user_config_path(&self) -> &UserConfigPath;
    fn service_group(&self) -> &ServiceGroup;
}

impl Serviceable for Service {
    fn name(&self) -> &str {
        &self.pkg.name
    }

    fn user_config_path(&self) -> &UserConfigPath {
        &self.cfg.user_config_path
    }

    fn service_group(&self) -> &ServiceGroup {
        &self.service_group
    }
}

// WorkerState contains the channels the worker uses to communicate
// with the Watcher.
struct WorkerState {
    // This receiver is used by the watcher to be notified when a
    // worker has events.  The channel is a SyncChannel with buffer
    // size 1, as we are only interested in the fact that there were
    // events, not how many there were.
    have_events: Receiver<()>,
    // This sender is used by the watcher to notify a worker to stop
    // running.  It is an async channel because we never want the
    // UserConfigWatcher to block, even if the receiver end of the
    // channel somehow dies and/or fails to consume the message.
    stop_running: Sender<()>,
    // This receiver is used by the watcher tests to be notified when
    // a worker finished setting up the watcher and is about to
    // starting looping it.
    //
    // Silence the dead code warnings from rustc, because it is only
    // used in tests for synchronization purposes.
    #[allow(dead_code)]
    started_watching: Receiver<()>,
}

type ServiceName = String;
pub struct UserConfigWatcher {
    states: HashMap<ServiceName, WorkerState>,
}

impl UserConfigWatcher {
    pub fn new() -> Self {
        Self {
            states: HashMap::new(),
        }
    }

    /// Adds a service to the User Config Watcher, thereby starting a watcher thread.
    pub fn add<T: Serviceable>(&mut self, service: &T) -> io::Result<()> {
        // It isn't possible to use the `or_insert_with` function here because it can't have a
        // return value, which we need to return the error from `Worker::run`.
        if self.states.get(service.name()).is_none() {
            let user_toml_path = match service.user_config_path() {
                &UserConfigPath::Recommended(ref p) => p.join(USER_CONFIG_FILE),
                &UserConfigPath::Deprecated(ref p) => {
                    outputln!(
                        preamble service.service_group(),
                        "Not watching {}, because it is located in deprecated path ({}).",
                        USER_CONFIG_FILE,
                        p.display(),
                    );
                    return Ok(());
                }
            };
            // Establish bi-directional communication with the worker by creating two channels.
            // The sync_channel's buffer size is 1 because we want to use it as a boolean, i.e. we
            // are not interested in the events themselves, but only whether at least one has
            // happened.
            let (events_tx, events_rx) = sync_channel(1);
            let (running_tx, running_rx) = channel();
            let (watching_tx, watching_rx) = sync_channel(1);

            Worker::run(user_toml_path, events_tx, running_rx, watching_tx)?;

            outputln!(preamble service.service_group(), "Watching {}", USER_CONFIG_FILE);

            let state = WorkerState {
                have_events: events_rx,
                stop_running: running_tx,
                started_watching: watching_rx,
            };

            self.states.insert(service.name().to_owned(), state);
        }

        Ok(())
    }

    /// Removes a service from the User Config Watcher, and sends a message to the watcher thread
    /// to stop running.
    pub fn remove<T: Serviceable>(&mut self, service: &T) -> Result<(), SendError<()>> {
        if let Some(state) = self.states.remove(service.name()) {
            state.stop_running.send(())?;
        }

        Ok(())
    }

    /// Checks whether the watcher for the specified service has observed any events.
    ///
    /// This also consumes the events.
    pub fn have_events_for<T: Serviceable>(&self, service: &T) -> bool {
        if let Some(state) = self.states.get(service.name()) {
            let rx = &state.have_events;

            match rx.try_recv() {
                Ok(_) => {
                    return true;
                }
                Err(TryRecvError::Empty) => return false,
                Err(TryRecvError::Disconnected) => {
                    debug!("UserConfigWatcher worker has died!");
                    return false;
                }
            }
        }

        false
    }
}

struct UserConfigCallbacks {
    have_events: SyncSender<()>,
}

impl Callbacks for UserConfigCallbacks {
    fn file_appeared(&mut self, _: &Path) {
        self.perform();
    }

    fn file_modified(&mut self, _: &Path) {
        self.perform();
    }

    fn file_disappeared(&mut self, _: &Path) {
        self.perform();
    }
}

impl UserConfigCallbacks {
    fn perform(&self) {
        if let Err(TrySendError::Disconnected(_)) = self.have_events.try_send(()) {
            debug!("Worker could not notify Manager of event");
        }
    }
}

struct Worker;

impl Worker {
    // starts a new thread with the file watcher tracking the service's user-config file
    pub fn run(
        path: PathBuf,
        have_events: SyncSender<()>,
        stop_running: Receiver<()>,
        started_watching: SyncSender<()>,
    ) -> io::Result<()> {
        ThreadBuilder::new()
            .name(format!("user-config-watcher-{}", path.display()))
            .spawn(move || {
                debug!(
                    "UserConfigWatcher({}) worker thread starting",
                    path.display(),
                );
                let callbacks = UserConfigCallbacks {
                    have_events: have_events,
                };
                let mut file_watcher =
                    match default_file_watcher_with_no_initial_event(&path, callbacks) {
                        Ok(w) => w,
                        Err(e) => {
                            outputln!(
                                "UserConfigWatcher({}) could not start notifier, \
                                 ending thread ({})",
                                path.display(),
                                e,
                            );
                            return;
                        }
                    };

                let _ = started_watching.try_send(());

                loop {
                    match stop_running.try_recv() {
                        // As long as the `stop_running` channel is
                        // empty, this branch will execute on every
                        // iteration.
                        Err(TryRecvError::Empty) => {
                            if let Err(e) = file_watcher.single_iteration() {
                                outputln!(
                                    "UserConfigWatcher({}) could not run notifier, \
                                     ending thread ({})",
                                    path.display(),
                                    e,
                                );
                                return;
                            };
                        }

                        // If we receive a message on the channel, we stop.
                        Ok(_) => break,

                        // If the channel is disconnected, we stop as well.
                        Err(TryRecvError::Disconnected) => {
                            debug!(
                                "UserConfigWatcher({}) worker thread failed to receive on channel",
                                path.display(),
                            );
                            break;
                        }
                    }
                }
            })?;

        Ok(())
    }
}

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

    use std::fs::{remove_file, File};
    use std::io::Write;
    use std::str::FromStr;
    use std::thread;
    use std::time::{Duration, Instant};

    use manager::file_watcher::WATCHER_DELAY_MS;

    use tempfile::TempDir;

    #[test]
    fn no_events_at_first() {
        let service = TestService::default();
        let mut ucm = UserConfigWatcher::new();
        ucm.add(&service).expect("adding service");

        assert!(!ucm.have_events_for(&service));
    }

    #[test]
    fn events_present_after_adding_config() {
        let service = TestService::default();
        let mut ucm = UserConfigWatcher::new();
        ucm.add(&service).expect("adding service");
        assert!(wait_for_watcher(&ucm, &service));

        File::create(service.user_config_path().get_path().join(USER_CONFIG_FILE))
            .expect("creating file");

        assert!(wait_for_events(&ucm, &service));
    }

    #[test]
    fn events_present_after_changing_config() {
        let service = TestService::default();
        let file_path = service.user_config_path().get_path().join(USER_CONFIG_FILE);
        let mut ucm = UserConfigWatcher::new();

        ucm.add(&service).expect("adding service");
        assert!(wait_for_watcher(&ucm, &service));
        let mut file = File::create(&file_path).expect("creating file");

        file.write_all(b"42").expect(USER_CONFIG_FILE);

        assert!(wait_for_events(&ucm, &service));
    }

    #[test]
    fn events_present_after_removing_config() {
        let service = TestService::default();
        let file_path = service.user_config_path().get_path().join(USER_CONFIG_FILE);
        let mut ucm = UserConfigWatcher::new();

        ucm.add(&service).expect("adding service");
        assert!(wait_for_watcher(&ucm, &service));
        File::create(&file_path).expect("creating file");

        // Allow the watcher to notice that a file was created.
        wait_for_events(&ucm, &service);

        remove_file(&file_path).expect("removing file");

        assert!(wait_for_events(&ucm, &service));
    }

    fn wait_for_watcher<T: Serviceable>(ucm: &UserConfigWatcher, service: &T) -> bool {
        let start = Instant::now();
        let timeout = Duration::from_millis(1000);

        while start.elapsed() < timeout {
            let state = ucm.states.get(service.name()).expect("service added");
            match state.started_watching.try_recv() {
                Ok(_) => return true,
                Err(TryRecvError::Empty) => (),
                Err(TryRecvError::Disconnected) => return false,
            }

            thread::sleep(Duration::from_millis(10));
        }

        false
    }

    fn wait_for_events<T: Serviceable>(ucm: &UserConfigWatcher, service: &T) -> bool {
        let start = Instant::now();
        let timeout = Duration::from_millis(WATCHER_DELAY_MS * 2);

        while start.elapsed() < timeout {
            if ucm.have_events_for(service) {
                return true;
            }

            thread::sleep(Duration::from_millis(10));
        }

        false
    }

    struct TestService {
        // It is only used as a way to remove the temporary directory
        // when the test finishes. Not used otherwise.
        #[allow(dead_code)]
        tmp: TempDir,
        name: String,
        user_config_path: UserConfigPath,
        service_group: ServiceGroup,
    }

    impl Serviceable for TestService {
        fn name(&self) -> &str {
            &self.name
        }

        fn user_config_path(&self) -> &UserConfigPath {
            &self.user_config_path
        }

        fn service_group(&self) -> &ServiceGroup {
            &self.service_group
        }
    }

    impl Default for TestService {
        fn default() -> Self {
            let tmp = TempDir::new().expect("creating temp dir");
            let path = UserConfigPath::Recommended(tmp.path().to_path_buf());
            Self {
                tmp: tmp,
                name: String::from("foo"),
                user_config_path: path,
                service_group: ServiceGroup::from_str("foo.bar@yoyodine").unwrap(),
            }
        }
    }
}
<commit_msg>Enable UserConfigWatcher to be shared across threads<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashMap;
use std::io;
use std::path::{Path, PathBuf};
use std::sync::{
    mpsc::{
        channel, sync_channel, Receiver, SendError, Sender, SyncSender, TryRecvError, TrySendError,
    },
    Arc, Mutex,
};
use std::thread::Builder as ThreadBuilder;

use super::file_watcher::{default_file_watcher_with_no_initial_event, Callbacks};

use hcore::fs::USER_CONFIG_FILE;
use hcore::service::ServiceGroup;
use manager::service::Service;
use manager::service::UserConfigPath;

static LOGKEY: &'static str = "UCW";

// This trait exists to ease the testing of functions that receive a Service. Creating Services
// requires a lot of ceremony, so we work around this with this trait.
pub trait Serviceable {
    fn name(&self) -> &str;
    fn user_config_path(&self) -> &UserConfigPath;
    fn service_group(&self) -> &ServiceGroup;
}

impl Serviceable for Service {
    fn name(&self) -> &str {
        &self.pkg.name
    }

    fn user_config_path(&self) -> &UserConfigPath {
        &self.cfg.user_config_path
    }

    fn service_group(&self) -> &ServiceGroup {
        &self.service_group
    }
}

// WorkerState contains the channels the worker uses to communicate
// with the Watcher.
struct WorkerState {
    // This receiver is used by the watcher to be notified when a
    // worker has events.  The channel is a SyncChannel with buffer
    // size 1, as we are only interested in the fact that there were
    // events, not how many there were.
    have_events: Receiver<()>,
    // This sender is used by the watcher to notify a worker to stop
    // running.  It is an async channel because we never want the
    // UserConfigWatcher to block, even if the receiver end of the
    // channel somehow dies and/or fails to consume the message.
    stop_running: Sender<()>,
    // This receiver is used by the watcher tests to be notified when
    // a worker finished setting up the watcher and is about to
    // starting looping it.
    //
    // Silence the dead code warnings from rustc, because it is only
    // used in tests for synchronization purposes.
    #[allow(dead_code)]
    started_watching: Receiver<()>,
}

type ServiceName = String;
pub struct UserConfigWatcher {
    // We use Arc/Mutex here, because this needs to be shareable
    // across threads so we can remove watchers from futures; the
    // Sender and Receiver members of WorkerState aren't themselves
    // shareable.
    states: Arc<Mutex<HashMap<ServiceName, WorkerState>>>,
}

impl UserConfigWatcher {
    pub fn new() -> Self {
        Self {
            states: Arc::new(Mutex::new(HashMap::new())),
        }
    }

    /// Adds a service to the User Config Watcher, thereby starting a watcher thread.
    pub fn add<T: Serviceable>(&mut self, service: &T) -> io::Result<()> {
        // It isn't possible to use the `or_insert_with` function here because it can't have a
        // return value, which we need to return the error from `Worker::run`.
        let mut states = self.states.lock().expect("states lock was poisoned");
        if states.get(service.name()).is_none() {
            let user_toml_path = match service.user_config_path() {
                &UserConfigPath::Recommended(ref p) => p.join(USER_CONFIG_FILE),
                &UserConfigPath::Deprecated(ref p) => {
                    outputln!(
                        preamble service.service_group(),
                        "Not watching {}, because it is located in deprecated path ({}).",
                        USER_CONFIG_FILE,
                        p.display(),
                    );
                    return Ok(());
                }
            };
            // Establish bi-directional communication with the worker by creating two channels.
            // The sync_channel's buffer size is 1 because we want to use it as a boolean, i.e. we
            // are not interested in the events themselves, but only whether at least one has
            // happened.
            let (events_tx, events_rx) = sync_channel(1);
            let (running_tx, running_rx) = channel();
            let (watching_tx, watching_rx) = sync_channel(1);

            Worker::run(user_toml_path, events_tx, running_rx, watching_tx)?;

            outputln!(preamble service.service_group(), "Watching {}", USER_CONFIG_FILE);

            let state = WorkerState {
                have_events: events_rx,
                stop_running: running_tx,
                started_watching: watching_rx,
            };

            states.insert(service.name().to_owned(), state);
        }

        Ok(())
    }

    /// Removes a service from the User Config Watcher, and sends a message to the watcher thread
    /// to stop running.
    pub fn remove<T: Serviceable>(&mut self, service: &T) -> Result<(), SendError<()>> {
        if let Some(state) = self
            .states
            .lock()
            .expect("states lock was poisoned")
            .remove(service.name())
        {
            state.stop_running.send(())?;
        }

        Ok(())
    }

    /// Checks whether the watcher for the specified service has observed any events.
    ///
    /// This also consumes the events.
    pub fn have_events_for<T: Serviceable>(&self, service: &T) -> bool {
        if let Some(state) = self
            .states
            .lock()
            .expect("states lock was poisoned")
            .get(service.name())
        {
            let rx = &state.have_events;

            match rx.try_recv() {
                Ok(_) => {
                    return true;
                }
                Err(TryRecvError::Empty) => return false,
                Err(TryRecvError::Disconnected) => {
                    debug!("UserConfigWatcher worker has died!");
                    return false;
                }
            }
        }

        false
    }
}

struct UserConfigCallbacks {
    have_events: SyncSender<()>,
}

impl Callbacks for UserConfigCallbacks {
    fn file_appeared(&mut self, _: &Path) {
        self.perform();
    }

    fn file_modified(&mut self, _: &Path) {
        self.perform();
    }

    fn file_disappeared(&mut self, _: &Path) {
        self.perform();
    }
}

impl UserConfigCallbacks {
    fn perform(&self) {
        if let Err(TrySendError::Disconnected(_)) = self.have_events.try_send(()) {
            debug!("Worker could not notify Manager of event");
        }
    }
}

struct Worker;

impl Worker {
    // starts a new thread with the file watcher tracking the service's user-config file
    pub fn run(
        path: PathBuf,
        have_events: SyncSender<()>,
        stop_running: Receiver<()>,
        started_watching: SyncSender<()>,
    ) -> io::Result<()> {
        ThreadBuilder::new()
            .name(format!("user-config-watcher-{}", path.display()))
            .spawn(move || {
                debug!(
                    "UserConfigWatcher({}) worker thread starting",
                    path.display(),
                );
                let callbacks = UserConfigCallbacks {
                    have_events: have_events,
                };
                let mut file_watcher =
                    match default_file_watcher_with_no_initial_event(&path, callbacks) {
                        Ok(w) => w,
                        Err(e) => {
                            outputln!(
                                "UserConfigWatcher({}) could not start notifier, \
                                 ending thread ({})",
                                path.display(),
                                e,
                            );
                            return;
                        }
                    };

                let _ = started_watching.try_send(());

                loop {
                    match stop_running.try_recv() {
                        // As long as the `stop_running` channel is
                        // empty, this branch will execute on every
                        // iteration.
                        Err(TryRecvError::Empty) => {
                            if let Err(e) = file_watcher.single_iteration() {
                                outputln!(
                                    "UserConfigWatcher({}) could not run notifier, \
                                     ending thread ({})",
                                    path.display(),
                                    e,
                                );
                                return;
                            };
                        }

                        // If we receive a message on the channel, we stop.
                        Ok(_) => break,

                        // If the channel is disconnected, we stop as well.
                        Err(TryRecvError::Disconnected) => {
                            debug!(
                                "UserConfigWatcher({}) worker thread failed to receive on channel",
                                path.display(),
                            );
                            break;
                        }
                    }
                }
            })?;

        Ok(())
    }
}

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

    use std::fs::{remove_file, File};
    use std::io::Write;
    use std::str::FromStr;
    use std::thread;
    use std::time::{Duration, Instant};

    use manager::file_watcher::WATCHER_DELAY_MS;

    use tempfile::TempDir;

    #[test]
    fn no_events_at_first() {
        let service = TestService::default();
        let mut ucm = UserConfigWatcher::new();
        ucm.add(&service).expect("adding service");

        assert!(!ucm.have_events_for(&service));
    }

    #[test]
    fn events_present_after_adding_config() {
        let service = TestService::default();
        let mut ucm = UserConfigWatcher::new();
        ucm.add(&service).expect("adding service");
        assert!(wait_for_watcher(&ucm, &service));

        File::create(service.user_config_path().get_path().join(USER_CONFIG_FILE))
            .expect("creating file");

        assert!(wait_for_events(&ucm, &service));
    }

    #[test]
    fn events_present_after_changing_config() {
        let service = TestService::default();
        let file_path = service.user_config_path().get_path().join(USER_CONFIG_FILE);
        let mut ucm = UserConfigWatcher::new();

        ucm.add(&service).expect("adding service");
        assert!(wait_for_watcher(&ucm, &service));
        let mut file = File::create(&file_path).expect("creating file");

        file.write_all(b"42").expect(USER_CONFIG_FILE);

        assert!(wait_for_events(&ucm, &service));
    }

    #[test]
    fn events_present_after_removing_config() {
        let service = TestService::default();
        let file_path = service.user_config_path().get_path().join(USER_CONFIG_FILE);
        let mut ucm = UserConfigWatcher::new();

        ucm.add(&service).expect("adding service");
        assert!(wait_for_watcher(&ucm, &service));
        File::create(&file_path).expect("creating file");

        // Allow the watcher to notice that a file was created.
        wait_for_events(&ucm, &service);

        remove_file(&file_path).expect("removing file");

        assert!(wait_for_events(&ucm, &service));
    }

    fn wait_for_watcher<T: Serviceable>(ucm: &UserConfigWatcher, service: &T) -> bool {
        let start = Instant::now();
        let timeout = Duration::from_millis(1000);

        while start.elapsed() < timeout {
            let states = ucm.states.lock().expect("states lock was poisoned");
            let state = states.get(service.name()).expect("service added");
            match state.started_watching.try_recv() {
                Ok(_) => return true,
                Err(TryRecvError::Empty) => (),
                Err(TryRecvError::Disconnected) => return false,
            }

            thread::sleep(Duration::from_millis(10));
        }

        false
    }

    fn wait_for_events<T: Serviceable>(ucm: &UserConfigWatcher, service: &T) -> bool {
        let start = Instant::now();
        let timeout = Duration::from_millis(WATCHER_DELAY_MS * 2);

        while start.elapsed() < timeout {
            if ucm.have_events_for(service) {
                return true;
            }

            thread::sleep(Duration::from_millis(10));
        }

        false
    }

    struct TestService {
        // It is only used as a way to remove the temporary directory
        // when the test finishes. Not used otherwise.
        #[allow(dead_code)]
        tmp: TempDir,
        name: String,
        user_config_path: UserConfigPath,
        service_group: ServiceGroup,
    }

    impl Serviceable for TestService {
        fn name(&self) -> &str {
            &self.name
        }

        fn user_config_path(&self) -> &UserConfigPath {
            &self.user_config_path
        }

        fn service_group(&self) -> &ServiceGroup {
            &self.service_group
        }
    }

    impl Default for TestService {
        fn default() -> Self {
            let tmp = TempDir::new().expect("creating temp dir");
            let path = UserConfigPath::Recommended(tmp.path().to_path_buf());
            Self {
                tmp: tmp,
                name: String::from("foo"),
                user_config_path: path,
                service_group: ServiceGroup::from_str("foo.bar@yoyodine").unwrap(),
            }
        }
    }
}
<|endoftext|>


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

// TODO(acourbot): Remove once we start using this file
#![allow(dead_code)]

use std::collections::btree_map::Entry;
use std::collections::BTreeMap;
use std::collections::VecDeque;
use std::time::Duration;

use base::AsRawDescriptor;
use base::Event;
use thiserror::Error as ThisError;

#[cfg(feature = "ffmpeg")]
use crate::virtio::video::resource::BufferHandle;
use crate::virtio::video::resource::GuestResource;

/// Manages a pollable queue of events to be sent to the decoder or encoder.
pub struct EventQueue<T> {
    /// Pipe used to signal available events.
    event: Event,
    /// FIFO of all pending events.
    pending_events: VecDeque<T>,
}

impl<T> EventQueue<T> {
    /// Create a new event queue.
    pub fn new() -> base::Result<Self> {
        Ok(Self {
            // Use semaphore semantics so `eventfd` can be `read` as many times as it has been
            // `write`n to without blocking.
            event: Event::new()?,
            pending_events: Default::default(),
        })
    }

    /// Add `event` to the queue.
    pub fn queue_event(&mut self, event: T) -> base::Result<()> {
        self.pending_events.push_back(event);
        self.event.write(1)?;
        Ok(())
    }

    /// Read the next event, blocking until an event becomes available.
    pub fn dequeue_event(&mut self) -> base::Result<T> {
        // Wait until at least one event is written, if necessary.
        let cpt = self.event.read()?;
        let event = match self.pending_events.pop_front() {
            Some(event) => event,
            None => panic!("event signaled but no pending event - this is a bug."),
        };
        // If we have more than one event pending, write the remainder back into the event so it
        // keeps signalling.
        if cpt > 1 {
            self.event.write(cpt - 1)?;
        }

        Ok(event)
    }

    /// Remove all the posted events for which `predicate` returns `false`.
    pub fn retain<P: FnMut(&T) -> bool>(&mut self, predicate: P) {
        if self.pending_events.len() > 0 {
            let _ = self
                .event
                .read_timeout(Duration::from_millis(0))
                .expect("read_timeout failure");
        }

        self.pending_events.retain(predicate);

        let num_pending_events = self.pending_events.len();
        if num_pending_events > 0 {
            self.event
                .write(num_pending_events as u64)
                .expect("write failure");
        }
    }

    /// Returns the number of events currently pending on this queue, i.e. the number of times
    /// `dequeue_event` can be called without blocking.
    #[cfg(test)]
    pub fn len(&self) -> usize {
        self.pending_events.len()
    }
}

impl<T> AsRawDescriptor for EventQueue<T> {
    fn as_raw_descriptor(&self) -> base::RawDescriptor {
        self.event.as_raw_descriptor()
    }
}

#[cfg(feature = "ffmpeg")]
impl ffmpeg::swscale::SwConverterTarget for GuestResource {
    fn stride(&self) -> Option<usize> {
        self.planes.get(0).map(|p| p.stride)
    }

    fn num_planes(&self) -> usize {
        self.planes.len()
    }

    fn get_mapping(
        &mut self,
        plane: usize,
        required_size: usize,
    ) -> Result<base::MemoryMappingArena, base::MmapError> {
        self.handle.get_mapping(plane, required_size)
    }
}

/// Queue of all the output buffers provided by crosvm.
pub struct OutputQueue {
    // Max number of output buffers that can be imported into this queue.
    num_buffers: usize,
    // Maps picture IDs to the corresponding guest resource.
    buffers: BTreeMap<u32, GuestResource>,
    // Picture IDs of output buffers we can write into.
    ready_buffers: VecDeque<u32>,
}

#[derive(Debug, ThisError)]
pub enum OutputBufferImportError {
    #[error("maximum number of imported buffers ({0}) already reached")]
    MaxBuffersReached(usize),
    #[error("a buffer with picture ID {0} is already imported")]
    AlreadyImported(u32),
}

#[derive(Debug, ThisError)]
pub enum OutputBufferReuseError {
    #[error("no buffer with picture ID {0} is imported at the moment")]
    NotYetImported(u32),
    #[error("buffer with picture ID {0} is already ready for use")]
    AlreadyUsed(u32),
}

impl OutputQueue {
    /// Creates a new output queue capable of containing `num_buffers` buffers.
    pub fn new(num_buffers: usize) -> Self {
        Self {
            num_buffers,
            buffers: Default::default(),
            ready_buffers: Default::default(),
        }
    }

    /// Import a buffer, i.e. associate the buffer's `resource` to a given `picture_buffer_id`, and
    /// make the buffer ready for use.
    ///
    /// A buffer with a given `picture_buffer_id` can only be imported once.
    pub fn import_buffer(
        &mut self,
        picture_buffer_id: u32,
        resource: GuestResource,
    ) -> Result<(), OutputBufferImportError> {
        if self.buffers.len() >= self.num_buffers {
            return Err(OutputBufferImportError::MaxBuffersReached(self.num_buffers));
        }

        match self.buffers.entry(picture_buffer_id) {
            Entry::Vacant(o) => {
                o.insert(resource);
            }
            Entry::Occupied(_) => {
                return Err(OutputBufferImportError::AlreadyImported(picture_buffer_id));
            }
        }

        self.ready_buffers.push_back(picture_buffer_id);

        Ok(())
    }

    /// Mark the previously-imported buffer with ID `picture_buffer_id` as ready for being used.
    pub fn reuse_buffer(&mut self, picture_buffer_id: u32) -> Result<(), OutputBufferReuseError> {
        if !self.buffers.contains_key(&picture_buffer_id) {
            return Err(OutputBufferReuseError::NotYetImported(picture_buffer_id));
        }

        if self.ready_buffers.contains(&picture_buffer_id) {
            return Err(OutputBufferReuseError::AlreadyUsed(picture_buffer_id));
        }

        self.ready_buffers.push_back(picture_buffer_id);

        Ok(())
    }

    /// Get a buffer ready to be decoded into, if any is available.
    pub fn try_get_ready_buffer(&mut self) -> Option<(u32, &mut GuestResource)> {
        let picture_buffer_id = self.ready_buffers.pop_front()?;
        // Unwrapping is safe here because our interface guarantees that ids in `ready_buffers` are
        // valid keys for `buffers`.
        Some((
            picture_buffer_id,
            self.buffers
                .get_mut(&picture_buffer_id)
                .expect("expected buffer not present in queue"),
        ))
    }

    pub fn clear_ready_buffers(&mut self) {
        self.ready_buffers.clear();
    }
}

#[cfg(test)]
mod tests {
    use std::time::Duration;

    use base::EventToken;
    use base::WaitContext;

    use super::*;
    use crate::virtio::video::decoder::DecoderEvent;
    use crate::virtio::video::format::Rect;

    /// Test basic queue/dequeue functionality of `EventQueue`.
    #[test]
    fn event_queue() {
        let mut event_queue = EventQueue::new().unwrap();

        assert_eq!(
            event_queue.queue_event(DecoderEvent::NotifyEndOfBitstreamBuffer(1)),
            Ok(())
        );
        assert_eq!(event_queue.len(), 1);
        assert_eq!(
            event_queue.queue_event(DecoderEvent::PictureReady {
                picture_buffer_id: 0,
                bitstream_id: 1,
                visible_rect: Rect {
                    left: 0,
                    top: 0,
                    right: 320,
                    bottom: 240,
                },
            }),
            Ok(())
        );
        assert_eq!(event_queue.len(), 2);

        assert!(matches!(
            event_queue.dequeue_event(),
            Ok(DecoderEvent::NotifyEndOfBitstreamBuffer(1))
        ));
        assert_eq!(event_queue.len(), 1);
        assert!(matches!(
            event_queue.dequeue_event(),
            Ok(DecoderEvent::PictureReady {
                picture_buffer_id: 0,
                bitstream_id: 1,
                visible_rect: Rect {
                    left: 0,
                    top: 0,
                    right: 320,
                    bottom: 240,
                }
            })
        ));
        assert_eq!(event_queue.len(), 0);
    }

    /// Test polling of `DecoderEventQueue`'s `event_pipe`.
    #[test]
    fn decoder_event_queue_polling() {
        #[derive(EventToken)]
        enum Token {
            Event,
        }

        let mut event_queue = EventQueue::new().unwrap();
        let wait_context = WaitContext::build_with(&[(&event_queue, Token::Event)]).unwrap();

        // The queue is empty, so `event_pipe` should not signal.
        assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 0);

        // `event_pipe` should signal as long as the queue is not empty.
        event_queue
            .queue_event(DecoderEvent::NotifyEndOfBitstreamBuffer(1))
            .unwrap();
        assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 1);
        event_queue
            .queue_event(DecoderEvent::NotifyEndOfBitstreamBuffer(2))
            .unwrap();
        assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 1);
        event_queue
            .queue_event(DecoderEvent::NotifyEndOfBitstreamBuffer(3))
            .unwrap();
        assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 1);

        event_queue.dequeue_event().unwrap();
        assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 1);
        event_queue.dequeue_event().unwrap();
        assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 1);
        event_queue.dequeue_event().unwrap();

        // The queue is empty again, so `event_pipe` should not signal.
        assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 0);
    }
}
<commit_msg>virtio: video: decoder: add SyncEventQueue<commit_after>// Copyright 2022 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO(acourbot): Remove once we start using this file
#![allow(dead_code)]

use std::collections::btree_map::Entry;
use std::collections::BTreeMap;
use std::collections::VecDeque;
use std::time::Duration;

use base::AsRawDescriptor;
use base::Event;
use sync::Mutex;
use thiserror::Error as ThisError;

#[cfg(feature = "ffmpeg")]
use crate::virtio::video::resource::BufferHandle;
use crate::virtio::video::resource::GuestResource;

/// Manages a pollable queue of events to be sent to the decoder or encoder.
pub struct EventQueue<T> {
    /// Pipe used to signal available events.
    event: Event,
    /// FIFO of all pending events.
    pending_events: VecDeque<T>,
}

impl<T> EventQueue<T> {
    /// Create a new event queue.
    pub fn new() -> base::Result<Self> {
        Ok(Self {
            // Use semaphore semantics so `eventfd` can be `read` as many times as it has been
            // `write`n to without blocking.
            event: Event::new()?,
            pending_events: Default::default(),
        })
    }

    /// Add `event` to the queue.
    pub fn queue_event(&mut self, event: T) -> base::Result<()> {
        self.pending_events.push_back(event);
        self.event.write(1)?;
        Ok(())
    }

    /// Read the next event, blocking until an event becomes available.
    pub fn dequeue_event(&mut self) -> base::Result<T> {
        // Wait until at least one event is written, if necessary.
        let cpt = self.event.read()?;
        let event = match self.pending_events.pop_front() {
            Some(event) => event,
            None => panic!("event signaled but no pending event - this is a bug."),
        };
        // If we have more than one event pending, write the remainder back into the event so it
        // keeps signalling.
        if cpt > 1 {
            self.event.write(cpt - 1)?;
        }

        Ok(event)
    }

    /// Remove all the posted events for which `predicate` returns `false`.
    pub fn retain<P: FnMut(&T) -> bool>(&mut self, predicate: P) {
        if self.pending_events.len() > 0 {
            let _ = self
                .event
                .read_timeout(Duration::from_millis(0))
                .expect("read_timeout failure");
        }

        self.pending_events.retain(predicate);

        let num_pending_events = self.pending_events.len();
        if num_pending_events > 0 {
            self.event
                .write(num_pending_events as u64)
                .expect("write failure");
        }
    }

    /// Returns the number of events currently pending on this queue, i.e. the number of times
    /// `dequeue_event` can be called without blocking.
    #[cfg(test)]
    pub fn len(&self) -> usize {
        self.pending_events.len()
    }
}

impl<T> AsRawDescriptor for EventQueue<T> {
    fn as_raw_descriptor(&self) -> base::RawDescriptor {
        self.event.as_raw_descriptor()
    }
}

/// An `EventQueue` that is `Sync`, `Send`, and non-mut - i.e. that can easily be passed across
/// threads and wrapped into a `Rc` or `Arc`.
pub struct SyncEventQueue<T>(Mutex<EventQueue<T>>);

impl<T> From<EventQueue<T>> for SyncEventQueue<T> {
    fn from(queue: EventQueue<T>) -> Self {
        Self(Mutex::new(queue))
    }
}

impl<T> SyncEventQueue<T> {
    /// Add `event` to the queue.
    pub fn queue_event(&self, event: T) -> base::Result<()> {
        self.0.lock().queue_event(event)
    }

    /// Read the next event, blocking until an event becomes available.
    pub fn dequeue_event(&self) -> base::Result<T> {
        self.0.lock().dequeue_event()
    }

    /// Remove all the posted events for which `predicate` returns `false`.
    pub fn retain<P: FnMut(&T) -> bool>(&self, predicate: P) {
        self.0.lock().retain(predicate)
    }

    /// Returns the number of events currently pending on this queue, i.e. the number of times
    /// `dequeue_event` can be called without blocking.
    #[cfg(test)]
    pub fn len(&self) -> usize {
        self.0.lock().len()
    }
}

impl<T> AsRawDescriptor for SyncEventQueue<T> {
    fn as_raw_descriptor(&self) -> base::RawDescriptor {
        self.0.lock().as_raw_descriptor()
    }
}

#[cfg(feature = "ffmpeg")]
impl ffmpeg::swscale::SwConverterTarget for GuestResource {
    fn stride(&self) -> Option<usize> {
        self.planes.get(0).map(|p| p.stride)
    }

    fn num_planes(&self) -> usize {
        self.planes.len()
    }

    fn get_mapping(
        &mut self,
        plane: usize,
        required_size: usize,
    ) -> Result<base::MemoryMappingArena, base::MmapError> {
        self.handle.get_mapping(plane, required_size)
    }
}

/// Queue of all the output buffers provided by crosvm.
pub struct OutputQueue {
    // Max number of output buffers that can be imported into this queue.
    num_buffers: usize,
    // Maps picture IDs to the corresponding guest resource.
    buffers: BTreeMap<u32, GuestResource>,
    // Picture IDs of output buffers we can write into.
    ready_buffers: VecDeque<u32>,
}

#[derive(Debug, ThisError)]
pub enum OutputBufferImportError {
    #[error("maximum number of imported buffers ({0}) already reached")]
    MaxBuffersReached(usize),
    #[error("a buffer with picture ID {0} is already imported")]
    AlreadyImported(u32),
}

#[derive(Debug, ThisError)]
pub enum OutputBufferReuseError {
    #[error("no buffer with picture ID {0} is imported at the moment")]
    NotYetImported(u32),
    #[error("buffer with picture ID {0} is already ready for use")]
    AlreadyUsed(u32),
}

impl OutputQueue {
    /// Creates a new output queue capable of containing `num_buffers` buffers.
    pub fn new(num_buffers: usize) -> Self {
        Self {
            num_buffers,
            buffers: Default::default(),
            ready_buffers: Default::default(),
        }
    }

    /// Import a buffer, i.e. associate the buffer's `resource` to a given `picture_buffer_id`, and
    /// make the buffer ready for use.
    ///
    /// A buffer with a given `picture_buffer_id` can only be imported once.
    pub fn import_buffer(
        &mut self,
        picture_buffer_id: u32,
        resource: GuestResource,
    ) -> Result<(), OutputBufferImportError> {
        if self.buffers.len() >= self.num_buffers {
            return Err(OutputBufferImportError::MaxBuffersReached(self.num_buffers));
        }

        match self.buffers.entry(picture_buffer_id) {
            Entry::Vacant(o) => {
                o.insert(resource);
            }
            Entry::Occupied(_) => {
                return Err(OutputBufferImportError::AlreadyImported(picture_buffer_id));
            }
        }

        self.ready_buffers.push_back(picture_buffer_id);

        Ok(())
    }

    /// Mark the previously-imported buffer with ID `picture_buffer_id` as ready for being used.
    pub fn reuse_buffer(&mut self, picture_buffer_id: u32) -> Result<(), OutputBufferReuseError> {
        if !self.buffers.contains_key(&picture_buffer_id) {
            return Err(OutputBufferReuseError::NotYetImported(picture_buffer_id));
        }

        if self.ready_buffers.contains(&picture_buffer_id) {
            return Err(OutputBufferReuseError::AlreadyUsed(picture_buffer_id));
        }

        self.ready_buffers.push_back(picture_buffer_id);

        Ok(())
    }

    /// Get a buffer ready to be decoded into, if any is available.
    pub fn try_get_ready_buffer(&mut self) -> Option<(u32, &mut GuestResource)> {
        let picture_buffer_id = self.ready_buffers.pop_front()?;
        // Unwrapping is safe here because our interface guarantees that ids in `ready_buffers` are
        // valid keys for `buffers`.
        Some((
            picture_buffer_id,
            self.buffers
                .get_mut(&picture_buffer_id)
                .expect("expected buffer not present in queue"),
        ))
    }

    pub fn clear_ready_buffers(&mut self) {
        self.ready_buffers.clear();
    }
}

#[cfg(test)]
mod tests {
    use std::time::Duration;

    use base::EventToken;
    use base::WaitContext;

    use super::*;
    use crate::virtio::video::decoder::DecoderEvent;
    use crate::virtio::video::format::Rect;

    /// Test basic queue/dequeue functionality of `EventQueue`.
    #[test]
    fn event_queue() {
        let mut event_queue = EventQueue::new().unwrap();

        assert_eq!(
            event_queue.queue_event(DecoderEvent::NotifyEndOfBitstreamBuffer(1)),
            Ok(())
        );
        assert_eq!(event_queue.len(), 1);
        assert_eq!(
            event_queue.queue_event(DecoderEvent::PictureReady {
                picture_buffer_id: 0,
                bitstream_id: 1,
                visible_rect: Rect {
                    left: 0,
                    top: 0,
                    right: 320,
                    bottom: 240,
                },
            }),
            Ok(())
        );
        assert_eq!(event_queue.len(), 2);

        assert!(matches!(
            event_queue.dequeue_event(),
            Ok(DecoderEvent::NotifyEndOfBitstreamBuffer(1))
        ));
        assert_eq!(event_queue.len(), 1);
        assert!(matches!(
            event_queue.dequeue_event(),
            Ok(DecoderEvent::PictureReady {
                picture_buffer_id: 0,
                bitstream_id: 1,
                visible_rect: Rect {
                    left: 0,
                    top: 0,
                    right: 320,
                    bottom: 240,
                }
            })
        ));
        assert_eq!(event_queue.len(), 0);
    }

    /// Test polling of `DecoderEventQueue`'s `event_pipe`.
    #[test]
    fn decoder_event_queue_polling() {
        #[derive(EventToken)]
        enum Token {
            Event,
        }

        let mut event_queue = EventQueue::new().unwrap();
        let wait_context = WaitContext::build_with(&[(&event_queue, Token::Event)]).unwrap();

        // The queue is empty, so `event_pipe` should not signal.
        assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 0);

        // `event_pipe` should signal as long as the queue is not empty.
        event_queue
            .queue_event(DecoderEvent::NotifyEndOfBitstreamBuffer(1))
            .unwrap();
        assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 1);
        event_queue
            .queue_event(DecoderEvent::NotifyEndOfBitstreamBuffer(2))
            .unwrap();
        assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 1);
        event_queue
            .queue_event(DecoderEvent::NotifyEndOfBitstreamBuffer(3))
            .unwrap();
        assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 1);

        event_queue.dequeue_event().unwrap();
        assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 1);
        event_queue.dequeue_event().unwrap();
        assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 1);
        event_queue.dequeue_event().unwrap();

        // The queue is empty again, so `event_pipe` should not signal.
        assert_eq!(wait_context.wait_timeout(Duration::ZERO).unwrap().len(), 0);
    }
}
<|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.

/// Entry point of thread panic, for details, see std::macros
#[macro_export]
macro_rules! panic {
    () => (
        panic!("explicit panic")
    );
    ($msg:expr) => ({
        static _MSG_FILE_LINE: (&'static str, &'static str, u32) = ($msg, file!(), line!());
        ::core::panicking::panic(&_MSG_FILE_LINE)
    });
    ($fmt:expr, $($arg:tt)*) => ({
        // The leading _'s are to avoid dead code warnings if this is
        // used inside a dead function. Just `#[allow(dead_code)]` is
        // insufficient, since the user may have
        // `#[forbid(dead_code)]` and which cannot be overridden.
        static _FILE_LINE: (&'static str, u32) = (file!(), line!());
        ::core::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE)
    });
}

/// Ensure that a boolean expression is `true` at runtime.
///
/// This will invoke the `panic!` macro if the provided expression cannot be
/// evaluated to `true` at runtime.
///
/// # Examples
///
/// ```
/// // the panic message for these assertions is the stringified value of the
/// // expression given.
/// assert!(true);
///
/// fn some_computation() -> bool { true } // a very simple function
///
/// assert!(some_computation());
///
/// // assert with a custom message
/// let x = true;
/// assert!(x, "x wasn't true!");
///
/// let a = 3; let b = 27;
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! assert {
    ($cond:expr) => (
        if !$cond {
            panic!(concat!("assertion failed: ", stringify!($cond)))
        }
    );
    ($cond:expr, $($arg:tt)+) => (
        if !$cond {
            panic!($($arg)+)
        }
    );
}

/// Asserts that two expressions are equal to each other.
///
/// On panic, this macro will print the values of the expressions with their
/// debug representations.
///
/// # Examples
///
/// ```
/// let a = 3;
/// let b = 1 + 2;
/// assert_eq!(a, b);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! assert_eq {
    ($left:expr , $right:expr) => ({
        match (&($left), &($right)) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    panic!("assertion failed: `(left == right)` \
                           (left: `{:?}`, right: `{:?}`)", *left_val, *right_val)
                }
            }
        }
    })
}

/// Ensure that a boolean expression is `true` at runtime.
///
/// This will invoke the `panic!` macro if the provided expression cannot be
/// evaluated to `true` at runtime.
///
/// Unlike `assert!`, `debug_assert!` statements are only enabled in non
/// optimized builds by default. An optimized build will omit all
/// `debug_assert!` statements unless `-C debug-assertions` is passed to the
/// compiler. This makes `debug_assert!` useful for checks that are too
/// expensive to be present in a release build but may be helpful during
/// development.
///
/// # Examples
///
/// ```
/// // the panic message for these assertions is the stringified value of the
/// // expression given.
/// debug_assert!(true);
///
/// fn some_expensive_computation() -> bool { true } // a very simple function
/// debug_assert!(some_expensive_computation());
///
/// // assert with a custom message
/// let x = true;
/// debug_assert!(x, "x wasn't true!");
///
/// let a = 3; let b = 27;
/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! debug_assert {
    ($($arg:tt)*) => (if cfg!(debug_assertions) { assert!($($arg)*); })
}

/// Asserts that two expressions are equal to each other, testing equality in
/// both directions.
///
/// On panic, this macro will print the values of the expressions.
///
/// Unlike `assert_eq!`, `debug_assert_eq!` statements are only enabled in non
/// optimized builds by default. An optimized build will omit all
/// `debug_assert_eq!` statements unless `-C debug-assertions` is passed to the
/// compiler. This makes `debug_assert_eq!` useful for checks that are too
/// expensive to be present in a release build but may be helpful during
/// development.
///
/// # Examples
///
/// ```
/// let a = 3;
/// let b = 1 + 2;
/// debug_assert_eq!(a, b);
/// ```
#[macro_export]
macro_rules! debug_assert_eq {
    ($($arg:tt)*) => (if cfg!(debug_assertions) { assert_eq!($($arg)*); })
}

/// Short circuiting evaluation on Err
///
/// `libstd` contains a more general `try!` macro that uses `From<E>`.
#[macro_export]
macro_rules! try {
    ($e:expr) => ({
        use $crate::result::Result::{Ok, Err};

        match $e {
            Ok(e) => e,
            Err(e) => return Err(e),
        }
    })
}

/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`.
/// See `std::fmt` for more information.
///
/// # Examples
///
/// ```
/// # #![allow(unused_must_use)]
/// use std::io::Write;
///
/// let mut w = Vec::new();
/// write!(&mut w, "test");
/// write!(&mut w, "formatted {}", "arguments");
/// ```
#[macro_export]
macro_rules! write {
    ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*)))
}

/// Equivalent to the `write!` macro, except that a newline is appended after
/// the message is written.
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! writeln {
    ($dst:expr, $fmt:expr) => (
        write!($dst, concat!($fmt, "\n"))
    );
    ($dst:expr, $fmt:expr, $($arg:tt)*) => (
        write!($dst, concat!($fmt, "\n"), $($arg)*)
    );
}

/// A utility macro for indicating unreachable code.
///
/// This is useful any time that the compiler can't determine that some code is unreachable. For
/// example:
///
/// * Match arms with guard conditions.
/// * Loops that dynamically terminate.
/// * Iterators that dynamically terminate.
///
/// # Panics
///
/// This will always panic.
///
/// # Examples
///
/// Match arms:
///
/// ```
/// fn foo(x: Option<i32>) {
///     match x {
///         Some(n) if n >= 0 => println!("Some(Non-negative)"),
///         Some(n) if n <  0 => println!("Some(Negative)"),
///         Some(_)           => unreachable!(), // compile error if commented out
///         None              => println!("None")
///     }
/// }
/// ```
///
/// Iterators:
///
/// ```
/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3
///     for i in 0.. {
///         if 3*i < i { panic!("u32 overflow"); }
///         if x < 3*i { return i-1; }
///     }
///     unreachable!();
/// }
/// ```
#[macro_export]
#[unstable(feature = "core",
           reason = "relationship with panic is unclear")]
macro_rules! unreachable {
    () => ({
        panic!("internal error: entered unreachable code")
    });
    ($msg:expr) => ({
        unreachable!("{}", $msg)
    });
    ($fmt:expr, $($arg:tt)*) => ({
        panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
    });
}

/// A standardised placeholder for marking unfinished code. It panics with the
/// message `"not yet implemented"` when executed.
#[macro_export]
#[unstable(feature = "core",
           reason = "relationship with panic is unclear")]
macro_rules! unimplemented {
    () => (panic!("not yet implemented"))
}
<commit_msg>Rollup merge of #25372 - steveklabnik:gh25355, r=alexcrichton<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.

/// Entry point of thread panic, for details, see std::macros
#[macro_export]
macro_rules! panic {
    () => (
        panic!("explicit panic")
    );
    ($msg:expr) => ({
        static _MSG_FILE_LINE: (&'static str, &'static str, u32) = ($msg, file!(), line!());
        ::core::panicking::panic(&_MSG_FILE_LINE)
    });
    ($fmt:expr, $($arg:tt)*) => ({
        // The leading _'s are to avoid dead code warnings if this is
        // used inside a dead function. Just `#[allow(dead_code)]` is
        // insufficient, since the user may have
        // `#[forbid(dead_code)]` and which cannot be overridden.
        static _FILE_LINE: (&'static str, u32) = (file!(), line!());
        ::core::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE)
    });
}

/// Ensure that a boolean expression is `true` at runtime.
///
/// This will invoke the `panic!` macro if the provided expression cannot be
/// evaluated to `true` at runtime.
///
/// # Examples
///
/// ```
/// // the panic message for these assertions is the stringified value of the
/// // expression given.
/// assert!(true);
///
/// fn some_computation() -> bool { true } // a very simple function
///
/// assert!(some_computation());
///
/// // assert with a custom message
/// let x = true;
/// assert!(x, "x wasn't true!");
///
/// let a = 3; let b = 27;
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! assert {
    ($cond:expr) => (
        if !$cond {
            panic!(concat!("assertion failed: ", stringify!($cond)))
        }
    );
    ($cond:expr, $($arg:tt)+) => (
        if !$cond {
            panic!($($arg)+)
        }
    );
}

/// Asserts that two expressions are equal to each other.
///
/// On panic, this macro will print the values of the expressions with their
/// debug representations.
///
/// # Examples
///
/// ```
/// let a = 3;
/// let b = 1 + 2;
/// assert_eq!(a, b);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! assert_eq {
    ($left:expr , $right:expr) => ({
        match (&($left), &($right)) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    panic!("assertion failed: `(left == right)` \
                           (left: `{:?}`, right: `{:?}`)", *left_val, *right_val)
                }
            }
        }
    })
}

/// Ensure that a boolean expression is `true` at runtime.
///
/// This will invoke the `panic!` macro if the provided expression cannot be
/// evaluated to `true` at runtime.
///
/// Unlike `assert!`, `debug_assert!` statements are only enabled in non
/// optimized builds by default. An optimized build will omit all
/// `debug_assert!` statements unless `-C debug-assertions` is passed to the
/// compiler. This makes `debug_assert!` useful for checks that are too
/// expensive to be present in a release build but may be helpful during
/// development.
///
/// # Examples
///
/// ```
/// // the panic message for these assertions is the stringified value of the
/// // expression given.
/// debug_assert!(true);
///
/// fn some_expensive_computation() -> bool { true } // a very simple function
/// debug_assert!(some_expensive_computation());
///
/// // assert with a custom message
/// let x = true;
/// debug_assert!(x, "x wasn't true!");
///
/// let a = 3; let b = 27;
/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! debug_assert {
    ($($arg:tt)*) => (if cfg!(debug_assertions) { assert!($($arg)*); })
}

/// Asserts that two expressions are equal to each other, testing equality in
/// both directions.
///
/// On panic, this macro will print the values of the expressions.
///
/// Unlike `assert_eq!`, `debug_assert_eq!` statements are only enabled in non
/// optimized builds by default. An optimized build will omit all
/// `debug_assert_eq!` statements unless `-C debug-assertions` is passed to the
/// compiler. This makes `debug_assert_eq!` useful for checks that are too
/// expensive to be present in a release build but may be helpful during
/// development.
///
/// # Examples
///
/// ```
/// let a = 3;
/// let b = 1 + 2;
/// debug_assert_eq!(a, b);
/// ```
#[macro_export]
macro_rules! debug_assert_eq {
    ($($arg:tt)*) => (if cfg!(debug_assertions) { assert_eq!($($arg)*); })
}

/// Short circuiting evaluation on Err
///
/// `libstd` contains a more general `try!` macro that uses `From<E>`.
#[macro_export]
macro_rules! try {
    ($e:expr) => ({
        use $crate::result::Result::{Ok, Err};

        match $e {
            Ok(e) => e,
            Err(e) => return Err(e),
        }
    })
}

/// Use the `format!` syntax to write data into a buffer of type `&mut Write`.
/// See `std::fmt` for more information.
///
/// # Examples
///
/// ```
/// # #![allow(unused_must_use)]
/// use std::io::Write;
///
/// let mut w = Vec::new();
/// write!(&mut w, "test");
/// write!(&mut w, "formatted {}", "arguments");
/// ```
#[macro_export]
macro_rules! write {
    ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*)))
}

/// Equivalent to the `write!` macro, except that a newline is appended after
/// the message is written.
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! writeln {
    ($dst:expr, $fmt:expr) => (
        write!($dst, concat!($fmt, "\n"))
    );
    ($dst:expr, $fmt:expr, $($arg:tt)*) => (
        write!($dst, concat!($fmt, "\n"), $($arg)*)
    );
}

/// A utility macro for indicating unreachable code.
///
/// This is useful any time that the compiler can't determine that some code is unreachable. For
/// example:
///
/// * Match arms with guard conditions.
/// * Loops that dynamically terminate.
/// * Iterators that dynamically terminate.
///
/// # Panics
///
/// This will always panic.
///
/// # Examples
///
/// Match arms:
///
/// ```
/// fn foo(x: Option<i32>) {
///     match x {
///         Some(n) if n >= 0 => println!("Some(Non-negative)"),
///         Some(n) if n <  0 => println!("Some(Negative)"),
///         Some(_)           => unreachable!(), // compile error if commented out
///         None              => println!("None")
///     }
/// }
/// ```
///
/// Iterators:
///
/// ```
/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3
///     for i in 0.. {
///         if 3*i < i { panic!("u32 overflow"); }
///         if x < 3*i { return i-1; }
///     }
///     unreachable!();
/// }
/// ```
#[macro_export]
#[unstable(feature = "core",
           reason = "relationship with panic is unclear")]
macro_rules! unreachable {
    () => ({
        panic!("internal error: entered unreachable code")
    });
    ($msg:expr) => ({
        unreachable!("{}", $msg)
    });
    ($fmt:expr, $($arg:tt)*) => ({
        panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
    });
}

/// A standardised placeholder for marking unfinished code. It panics with the
/// message `"not yet implemented"` when executed.
#[macro_export]
#[unstable(feature = "core",
           reason = "relationship with panic is unclear")]
macro_rules! unimplemented {
    () => (panic!("not yet implemented"))
}
<|endoftext|>


<commit_before>mod terminal;
mod ansi;

use std::io::{self, Write};
use self::terminal::{Terminal, Event, Key};
use self::ansi::{clear, cursor};

pub struct Interface {
    choices: Vec<String>,
    search: String,
    terminal: Terminal
}

impl Interface {
    /// Creates a new Interface with the provided input choices.
    pub fn with_choices(choices: Vec<String>) -> Interface {
        let mut term = Terminal::from("/dev/tty").unwrap();
        term.set_raw_mode().unwrap();

        Interface {
            choices: choices,
            search: String::new(),
            terminal: term
        }
    }

    // Starts the interface
    pub fn run(&mut self) {
        self.render().expect("Unable to render");

        for event in self.terminal.events().unwrap() {
            match event {
                Ok(Event::Key(Key::Ctrl('c'))) => {
                    return;
                },

                Ok(Event::Key(Key::Char(ch))) => {
                    self.search.push(ch);
                    self.render().expect("Unable to render");
                },

                Ok(Event::Key(Key::Backspace)) => {
                    self.search.pop();
                    self.render().expect("Unable to render");
                },

                Ok(_) => {}
                Err(err) => write!(self.terminal, "{:?}", err).unwrap(),
            };
        }
    }

    fn render(&mut self) -> io::Result<()> {
        let ref mut term = self.terminal;
        write!(term, "{}{}", clear::Line, cursor::Column(1))?;
        write!(term, "> {}", self.search)?;
        Ok(())
    }
}
<commit_msg>Initial implementation of matching<commit_after>mod terminal;
mod ansi;

use std::io::{self, Write};
use self::terminal::{Terminal, Event, Key};
use self::ansi::{clear, cursor};
use rff::choice::Choice;

pub struct Interface {
    choices: Vec<String>,
    matching: Vec<Choice>,
    search: String,
    terminal: Terminal
}

impl Interface {
    /// Creates a new Interface with the provided input choices.
    pub fn with_choices(choices: Vec<String>) -> Interface {
        let mut term = Terminal::from("/dev/tty").unwrap();
        term.set_raw_mode().unwrap();

        Interface {
            choices: choices,
            matching: Vec::new(),
            search: String::new(),
            terminal: term
        }
    }

    // Starts the interface
    pub fn run(&mut self) {
        self.filter_choices();
        self.render().expect("Unable to render");

        for event in self.terminal.events().unwrap() {
            match event {
                Ok(Event::Key(Key::Ctrl('c'))) => {
                    return;
                },

                Ok(Event::Key(Key::Char(ch))) => {
                    self.search.push(ch);
                    self.filter_choices();
                    self.render().expect("Unable to render");
                },

                Ok(Event::Key(Key::Backspace)) => {
                    self.search.pop();
                    self.filter_choices();
                    self.render().expect("Unable to render");
                },

                Ok(_) => {}
                Err(err) => write!(self.terminal, "{:?}", err).unwrap(),
            };
        }
    }

    fn filter_choices(&mut self) {
        let mut matches = self.choices.
            iter().
            cloned().
            filter_map(|choice| Choice::new(&self.search, choice)).
            collect::<Vec<_>>();

        matches.sort_by(|a, b| b.partial_cmp(&a).unwrap());

        self.matching = matches;
    }

    fn render(&mut self) -> io::Result<()> {
        let ref mut term = self.terminal;
        write!(term, "{}{}", clear::Line, cursor::Column(1))?;
        write!(term, "> {}", self.search)?;

        for choice in self.matching.iter().take(10) {
            write!(term, "\r\n{}", clear::Line)?;
            write!(term, "{}", choice)?;
        }

        let column = format!("> {}", self.search).len() as u16;
        write!(term, "{}{}", cursor::Up(10), cursor::Column(column + 1))?;

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


<commit_before>// Copyright 2012 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.

/*!
Primitive traits representing basic 'kinds' of types

Rust types can be classified in various useful ways according to
intrinsic properties of the type. These classifications, often called
'kinds', are represented as traits.

They cannot be implemented by user code, but are instead implemented
by the compiler automatically for the types to which they apply.

*/

/// Types able to be transferred across task boundaries.
#[lang="send"]
pub trait Send for Sized? {
    // empty.
}

/// Types with a constant size known at compile-time.
#[lang="sized"]
pub trait Sized for Sized? {
    // Empty.
}

/// Types that can be copied by simply copying bits (i.e. `memcpy`).
#[lang="copy"]
pub trait Copy for Sized? {
    // Empty.
}

/// Types that can be safely shared between tasks when aliased.
///
/// The precise definition is: a type `T` is `Sync` if `&T` is
/// thread-safe. In other words, there is no possibility of data races
/// when passing `&T` references between tasks.
///
/// As one would expect, primitive types like `u8` and `f64` are all
/// `Sync`, and so are simple aggregate types containing them (like
/// tuples, structs and enums). More instances of basic `Sync` types
/// include "immutable" types like `&T` and those with simple
/// inherited mutability, such as `Box<T>`, `Vec<T>` and most other
/// collection types. (Generic parameters need to be `Sync` for their
/// container to be `Sync`.)
///
/// A somewhat surprising consequence of the definition is `&mut T` is
/// `Sync` (if `T` is `Sync`) even though it seems that it might
/// provide unsynchronised mutation. The trick is a mutable reference
/// stored in an aliasable reference (that is, `& &mut T`) becomes
/// read-only, as if it were a `& &T`, hence there is no risk of a data
/// race.
///
/// Types that are not `Sync` are those that have "interior
/// mutability" in a non-thread-safe way, such as `Cell` and `RefCell`
/// in `std::cell`. These types allow for mutation of their contents
/// even when in an immutable, aliasable slot, e.g. the contents of
/// `&Cell<T>` can be `.set`, and do not ensure data races are
/// impossible, hence they cannot be `Sync`. A higher level example
/// of a non-`Sync` type is the reference counted pointer
/// `std::rc::Rc`, because any reference `&Rc<T>` can clone a new
/// reference, which modifies the reference counts in a non-atomic
/// way.
///
/// For cases when one does need thread-safe interior mutability,
/// types like the atomics in `std::sync` and `Mutex` & `RWLock` in
/// the `sync` crate do ensure that any mutation cannot cause data
/// races.  Hence these types are `Sync`.
///
/// Users writing their own types with interior mutability (or anything
/// else that is not thread-safe) should use the `NoSync` marker type
/// (from `std::kinds::marker`) to ensure that the compiler doesn't
/// consider the user-defined type to be `Sync`.  Any types with
/// interior mutability must also use the `std::cell::UnsafeCell` wrapper
/// around the value(s) which can be mutated when behind a `&`
/// reference; not doing this is undefined behaviour (for example,
/// `transmute`-ing from `&T` to `&mut T` is illegal).
#[lang="sync"]
pub trait Sync for Sized? {
    // Empty
}

/// Marker types are special types that are used with unsafe code to
/// inform the compiler of special constraints. Marker types should
/// only be needed when you are creating an abstraction that is
/// implemented using unsafe code. In that case, you may want to embed
/// some of the marker types below into your type.
pub mod marker {
    /// A marker type whose type parameter `T` is considered to be
    /// covariant with respect to the type itself. This is (typically)
    /// used to indicate that an instance of the type `T` is being stored
    /// into memory and read from, even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// *Note:* It is very unusual to have to add a covariant constraint.
    /// If you are not sure, you probably want to use `InvariantType`.
    ///
    /// # Example
    ///
    /// Given a struct `S` that includes a type parameter `T`
    /// but does not actually *reference* that type parameter:
    ///
    /// ```ignore
    /// use std::mem;
    ///
    /// struct S<T> { x: *() }
    /// fn get<T>(s: &S<T>) -> T {
    ///    unsafe {
    ///        let x: *T = mem::transmute(s.x);
    ///        *x
    ///    }
    /// }
    /// ```
    ///
    /// The type system would currently infer that the value of
    /// the type parameter `T` is irrelevant, and hence a `S<int>` is
    /// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
    /// any `U`). But this is incorrect because `get()` converts the
    /// `*()` into a `*T` and reads from it. Therefore, we should include the
    /// a marker field `CovariantType<T>` to inform the type checker that
    /// `S<T>` is a subtype of `S<U>` if `T` is a subtype of `U`
    /// (for example, `S<&'static int>` is a subtype of `S<&'a int>`
    /// for some lifetime `'a`, but not the other way around).
    #[lang="covariant_type"]
    #[deriving(PartialEq,Clone)]
    pub struct CovariantType<T>;

    /// A marker type whose type parameter `T` is considered to be
    /// contravariant with respect to the type itself. This is (typically)
    /// used to indicate that an instance of the type `T` will be consumed
    /// (but not read from), even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// *Note:* It is very unusual to have to add a contravariant constraint.
    /// If you are not sure, you probably want to use `InvariantType`.
    ///
    /// # Example
    ///
    /// Given a struct `S` that includes a type parameter `T`
    /// but does not actually *reference* that type parameter:
    ///
    /// ```
    /// use std::mem;
    ///
    /// struct S<T> { x: *const () }
    /// fn get<T>(s: &S<T>, v: T) {
    ///    unsafe {
    ///        let x: fn(T) = mem::transmute(s.x);
    ///        x(v)
    ///    }
    /// }
    /// ```
    ///
    /// The type system would currently infer that the value of
    /// the type parameter `T` is irrelevant, and hence a `S<int>` is
    /// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
    /// any `U`). But this is incorrect because `get()` converts the
    /// `*()` into a `fn(T)` and then passes a value of type `T` to it.
    ///
    /// Supplying a `ContravariantType` marker would correct the
    /// problem, because it would mark `S` so that `S<T>` is only a
    /// subtype of `S<U>` if `U` is a subtype of `T`; given that the
    /// function requires arguments of type `T`, it must also accept
    /// arguments of type `U`, hence such a conversion is safe.
    #[lang="contravariant_type"]
    #[deriving(PartialEq,Clone)]
    pub struct ContravariantType<T>;

    /// A marker type whose type parameter `T` is considered to be
    /// invariant with respect to the type itself. This is (typically)
    /// used to indicate that instances of the type `T` may be read or
    /// written, even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// # Example
    ///
    /// The Cell type is an example which uses unsafe code to achieve
    /// "interior" mutability:
    ///
    /// ```
    /// pub struct Cell<T> { value: T }
    /// # fn main() {}
    /// ```
    ///
    /// The type system would infer that `value` is only read here and
    /// never written, but in fact `Cell` uses unsafe code to achieve
    /// interior mutability.
    #[lang="invariant_type"]
    #[deriving(PartialEq,Clone)]
    pub struct InvariantType<T>;

    /// As `CovariantType`, but for lifetime parameters. Using
    /// `CovariantLifetime<'a>` indicates that it is ok to substitute
    /// a *longer* lifetime for `'a` than the one you originally
    /// started with (e.g., you could convert any lifetime `'foo` to
    /// `'static`). You almost certainly want `ContravariantLifetime`
    /// instead, or possibly `InvariantLifetime`. The only case where
    /// it would be appropriate is that you have a (type-casted, and
    /// hence hidden from the type system) function pointer with a
    /// signature like `fn(&'a T)` (and no other uses of `'a`). In
    /// this case, it is ok to substitute a larger lifetime for `'a`
    /// (e.g., `fn(&'static T)`), because the function is only
    /// becoming more selective in terms of what it accepts as
    /// argument.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    #[lang="covariant_lifetime"]
    #[deriving(PartialEq,Clone)]
    pub struct CovariantLifetime<'a>;

    /// As `ContravariantType`, but for lifetime parameters. Using
    /// `ContravariantLifetime<'a>` indicates that it is ok to
    /// substitute a *shorter* lifetime for `'a` than the one you
    /// originally started with (e.g., you could convert `'static` to
    /// any lifetime `'foo`). This is appropriate for cases where you
    /// have an unsafe pointer that is actually a pointer into some
    /// memory with lifetime `'a`, and thus you want to limit the
    /// lifetime of your data structure to `'a`. An example of where
    /// this is used is the iterator for vectors.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    #[lang="contravariant_lifetime"]
    #[deriving(PartialEq,Clone)]
    pub struct ContravariantLifetime<'a>;

    /// As `InvariantType`, but for lifetime parameters. Using
    /// `InvariantLifetime<'a>` indicates that it is not ok to
    /// substitute any other lifetime for `'a` besides its original
    /// value. This is appropriate for cases where you have an unsafe
    /// pointer that is actually a pointer into memory with lifetime `'a`,
    /// and this pointer is itself stored in an inherently mutable
    /// location (such as a `Cell`).
    #[lang="invariant_lifetime"]
    #[deriving(PartialEq,Clone)]
    pub struct InvariantLifetime<'a>;

    /// A type which is considered "not sendable", meaning that it cannot
    /// be safely sent between tasks, even if it is owned. This is
    /// typically embedded in other types, such as `Gc`, to ensure that
    /// their instances remain thread-local.
    #[lang="no_send_bound"]
    #[deriving(PartialEq,Clone)]
    pub struct NoSend;

    /// A type which is considered "not POD", meaning that it is not
    /// implicitly copyable. This is typically embedded in other types to
    /// ensure that they are never copied, even if they lack a destructor.
    #[lang="no_copy_bound"]
    #[deriving(PartialEq,Clone)]
    pub struct NoCopy;

    /// A type which is considered "not sync", meaning that
    /// its contents are not threadsafe, hence they cannot be
    /// shared between tasks.
    #[lang="no_sync_bound"]
    #[deriving(PartialEq,Clone)]
    pub struct NoSync;

    /// A type which is considered managed by the GC. This is typically
    /// embedded in other types.
    #[lang="managed_bound"]
    #[deriving(PartialEq,Clone)]
    pub struct Managed;
}
<commit_msg>auto merge of #19007 : huonw/rust/more-marker-impls, r=alexcrichton<commit_after>// Copyright 2012 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.

/*!
Primitive traits representing basic 'kinds' of types

Rust types can be classified in various useful ways according to
intrinsic properties of the type. These classifications, often called
'kinds', are represented as traits.

They cannot be implemented by user code, but are instead implemented
by the compiler automatically for the types to which they apply.

*/

/// Types able to be transferred across task boundaries.
#[lang="send"]
pub trait Send for Sized? {
    // empty.
}

/// Types with a constant size known at compile-time.
#[lang="sized"]
pub trait Sized for Sized? {
    // Empty.
}

/// Types that can be copied by simply copying bits (i.e. `memcpy`).
#[lang="copy"]
pub trait Copy for Sized? {
    // Empty.
}

/// Types that can be safely shared between tasks when aliased.
///
/// The precise definition is: a type `T` is `Sync` if `&T` is
/// thread-safe. In other words, there is no possibility of data races
/// when passing `&T` references between tasks.
///
/// As one would expect, primitive types like `u8` and `f64` are all
/// `Sync`, and so are simple aggregate types containing them (like
/// tuples, structs and enums). More instances of basic `Sync` types
/// include "immutable" types like `&T` and those with simple
/// inherited mutability, such as `Box<T>`, `Vec<T>` and most other
/// collection types. (Generic parameters need to be `Sync` for their
/// container to be `Sync`.)
///
/// A somewhat surprising consequence of the definition is `&mut T` is
/// `Sync` (if `T` is `Sync`) even though it seems that it might
/// provide unsynchronised mutation. The trick is a mutable reference
/// stored in an aliasable reference (that is, `& &mut T`) becomes
/// read-only, as if it were a `& &T`, hence there is no risk of a data
/// race.
///
/// Types that are not `Sync` are those that have "interior
/// mutability" in a non-thread-safe way, such as `Cell` and `RefCell`
/// in `std::cell`. These types allow for mutation of their contents
/// even when in an immutable, aliasable slot, e.g. the contents of
/// `&Cell<T>` can be `.set`, and do not ensure data races are
/// impossible, hence they cannot be `Sync`. A higher level example
/// of a non-`Sync` type is the reference counted pointer
/// `std::rc::Rc`, because any reference `&Rc<T>` can clone a new
/// reference, which modifies the reference counts in a non-atomic
/// way.
///
/// For cases when one does need thread-safe interior mutability,
/// types like the atomics in `std::sync` and `Mutex` & `RWLock` in
/// the `sync` crate do ensure that any mutation cannot cause data
/// races.  Hence these types are `Sync`.
///
/// Users writing their own types with interior mutability (or anything
/// else that is not thread-safe) should use the `NoSync` marker type
/// (from `std::kinds::marker`) to ensure that the compiler doesn't
/// consider the user-defined type to be `Sync`.  Any types with
/// interior mutability must also use the `std::cell::UnsafeCell` wrapper
/// around the value(s) which can be mutated when behind a `&`
/// reference; not doing this is undefined behaviour (for example,
/// `transmute`-ing from `&T` to `&mut T` is illegal).
#[lang="sync"]
pub trait Sync for Sized? {
    // Empty
}

/// Marker types are special types that are used with unsafe code to
/// inform the compiler of special constraints. Marker types should
/// only be needed when you are creating an abstraction that is
/// implemented using unsafe code. In that case, you may want to embed
/// some of the marker types below into your type.
pub mod marker {
    /// A marker type whose type parameter `T` is considered to be
    /// covariant with respect to the type itself. This is (typically)
    /// used to indicate that an instance of the type `T` is being stored
    /// into memory and read from, even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// *Note:* It is very unusual to have to add a covariant constraint.
    /// If you are not sure, you probably want to use `InvariantType`.
    ///
    /// # Example
    ///
    /// Given a struct `S` that includes a type parameter `T`
    /// but does not actually *reference* that type parameter:
    ///
    /// ```ignore
    /// use std::mem;
    ///
    /// struct S<T> { x: *() }
    /// fn get<T>(s: &S<T>) -> T {
    ///    unsafe {
    ///        let x: *T = mem::transmute(s.x);
    ///        *x
    ///    }
    /// }
    /// ```
    ///
    /// The type system would currently infer that the value of
    /// the type parameter `T` is irrelevant, and hence a `S<int>` is
    /// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
    /// any `U`). But this is incorrect because `get()` converts the
    /// `*()` into a `*T` and reads from it. Therefore, we should include the
    /// a marker field `CovariantType<T>` to inform the type checker that
    /// `S<T>` is a subtype of `S<U>` if `T` is a subtype of `U`
    /// (for example, `S<&'static int>` is a subtype of `S<&'a int>`
    /// for some lifetime `'a`, but not the other way around).
    #[lang="covariant_type"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct CovariantType<T>;

    /// A marker type whose type parameter `T` is considered to be
    /// contravariant with respect to the type itself. This is (typically)
    /// used to indicate that an instance of the type `T` will be consumed
    /// (but not read from), even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// *Note:* It is very unusual to have to add a contravariant constraint.
    /// If you are not sure, you probably want to use `InvariantType`.
    ///
    /// # Example
    ///
    /// Given a struct `S` that includes a type parameter `T`
    /// but does not actually *reference* that type parameter:
    ///
    /// ```
    /// use std::mem;
    ///
    /// struct S<T> { x: *const () }
    /// fn get<T>(s: &S<T>, v: T) {
    ///    unsafe {
    ///        let x: fn(T) = mem::transmute(s.x);
    ///        x(v)
    ///    }
    /// }
    /// ```
    ///
    /// The type system would currently infer that the value of
    /// the type parameter `T` is irrelevant, and hence a `S<int>` is
    /// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
    /// any `U`). But this is incorrect because `get()` converts the
    /// `*()` into a `fn(T)` and then passes a value of type `T` to it.
    ///
    /// Supplying a `ContravariantType` marker would correct the
    /// problem, because it would mark `S` so that `S<T>` is only a
    /// subtype of `S<U>` if `U` is a subtype of `T`; given that the
    /// function requires arguments of type `T`, it must also accept
    /// arguments of type `U`, hence such a conversion is safe.
    #[lang="contravariant_type"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct ContravariantType<T>;

    /// A marker type whose type parameter `T` is considered to be
    /// invariant with respect to the type itself. This is (typically)
    /// used to indicate that instances of the type `T` may be read or
    /// written, even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// # Example
    ///
    /// The Cell type is an example which uses unsafe code to achieve
    /// "interior" mutability:
    ///
    /// ```
    /// pub struct Cell<T> { value: T }
    /// # fn main() {}
    /// ```
    ///
    /// The type system would infer that `value` is only read here and
    /// never written, but in fact `Cell` uses unsafe code to achieve
    /// interior mutability.
    #[lang="invariant_type"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct InvariantType<T>;

    /// As `CovariantType`, but for lifetime parameters. Using
    /// `CovariantLifetime<'a>` indicates that it is ok to substitute
    /// a *longer* lifetime for `'a` than the one you originally
    /// started with (e.g., you could convert any lifetime `'foo` to
    /// `'static`). You almost certainly want `ContravariantLifetime`
    /// instead, or possibly `InvariantLifetime`. The only case where
    /// it would be appropriate is that you have a (type-casted, and
    /// hence hidden from the type system) function pointer with a
    /// signature like `fn(&'a T)` (and no other uses of `'a`). In
    /// this case, it is ok to substitute a larger lifetime for `'a`
    /// (e.g., `fn(&'static T)`), because the function is only
    /// becoming more selective in terms of what it accepts as
    /// argument.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    #[lang="covariant_lifetime"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct CovariantLifetime<'a>;

    /// As `ContravariantType`, but for lifetime parameters. Using
    /// `ContravariantLifetime<'a>` indicates that it is ok to
    /// substitute a *shorter* lifetime for `'a` than the one you
    /// originally started with (e.g., you could convert `'static` to
    /// any lifetime `'foo`). This is appropriate for cases where you
    /// have an unsafe pointer that is actually a pointer into some
    /// memory with lifetime `'a`, and thus you want to limit the
    /// lifetime of your data structure to `'a`. An example of where
    /// this is used is the iterator for vectors.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    #[lang="contravariant_lifetime"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct ContravariantLifetime<'a>;

    /// As `InvariantType`, but for lifetime parameters. Using
    /// `InvariantLifetime<'a>` indicates that it is not ok to
    /// substitute any other lifetime for `'a` besides its original
    /// value. This is appropriate for cases where you have an unsafe
    /// pointer that is actually a pointer into memory with lifetime `'a`,
    /// and this pointer is itself stored in an inherently mutable
    /// location (such as a `Cell`).
    #[lang="invariant_lifetime"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct InvariantLifetime<'a>;

    /// A type which is considered "not sendable", meaning that it cannot
    /// be safely sent between tasks, even if it is owned. This is
    /// typically embedded in other types, such as `Gc`, to ensure that
    /// their instances remain thread-local.
    #[lang="no_send_bound"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct NoSend;

    /// A type which is considered "not POD", meaning that it is not
    /// implicitly copyable. This is typically embedded in other types to
    /// ensure that they are never copied, even if they lack a destructor.
    #[lang="no_copy_bound"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct NoCopy;

    /// A type which is considered "not sync", meaning that
    /// its contents are not threadsafe, hence they cannot be
    /// shared between tasks.
    #[lang="no_sync_bound"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct NoSync;

    /// A type which is considered managed by the GC. This is typically
    /// embedded in other types.
    #[lang="managed_bound"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct Managed;
}
<|endoftext|>