<commit_before>use super::job_queue::*;

use futures::prelude::*;
use futures::channel::oneshot;
use futures::task;

use std::mem;
use std::sync::*;
use std::pin::{Pin};

///
/// The possible states of a future result
///
enum FutureResultState<T> {
    None,
    Some(T),
    ReturnedViaFuture
}

///
/// Signalling structure used to return the result of a scheduler future
///
struct SchedulerFutureResult<T> {
    /// The result of the future, or None if it has not been generated yet
    result: FutureResultState<Result<T, oneshot::Canceled>>,

    /// The waker to be called when the future is available
    waker: Option<task::Waker>
}

///
/// Wrapper that cancels the future if it is dropped before it is signalled
///
pub (super) struct SchedulerFutureSignaller<T>(Arc<Mutex<SchedulerFutureResult<T>>>);

///
/// Future representing a task pending on a scheduler
///
/// If polled when no threads are available, this future will run synchronously on the current thread
/// (stealing its execution time rather than blocking)
///
pub struct SchedulerFuture<T> {
    /// The queue which will eventually evaluate the result of this future
    queue: Arc<JobQueue>,

    /// A container for the result of this scheduler future
    result: Arc<Mutex<SchedulerFutureResult<T>>>
}

impl<T> SchedulerFuture<T> {
    ///
    /// Creates a new scheduler future and the result needed to signal it
    ///
    pub (super) fn new(queue: &Arc<JobQueue>) -> (SchedulerFuture<T>, SchedulerFutureSignaller<T>) {
        // Create an unfinished result
        let result = SchedulerFutureResult {
            result: FutureResultState::None,
            waker:  None
        };
        let result = Arc::new(Mutex::new(result));

        // Insert into a future
        let future = SchedulerFuture {
            queue:  Arc::clone(queue),
            result: Arc::clone(&result)
        };

        (future, SchedulerFutureSignaller(result))
    }
}

impl<T> FutureResultState<T> {
    ///
    /// Returns true if no result has ever been generated for this future
    ///
    fn is_none(&self) -> bool {
        match self {
            FutureResultState::None                 => true,
            FutureResultState::Some(_)              => false,
            FutureResultState::ReturnedViaFuture    => false
        }
    }

    ///
    /// If a result has been generated by this future and has not previously been taken, returns it
    ///
    fn take(&mut self) -> Option<T> {
        // Move the value out of this object
        let mut new_value = FutureResultState::ReturnedViaFuture;
        mem::swap(self, &mut new_value);

        // Return it if it contains a value
        match new_value {
            FutureResultState::None                 => { *self = FutureResultState::None; None },
            FutureResultState::ReturnedViaFuture    => { *self = FutureResultState::ReturnedViaFuture; None },
            FutureResultState::Some(value)          => { Some(value) }
        }
    }
}

impl<T> Drop for SchedulerFutureSignaller<T> {
    fn drop(&mut self) {
        let waker = {
            let mut future_result = self.0.lock().unwrap();

            // If no result has been generated, then mark the future as canceled
            if future_result.result.is_none() {
                // Mark the future as canceled
                future_result.result = FutureResultState::Some(Err(oneshot::Canceled));

                // Wake up anything that was polling it
                let waker = future_result.waker.take();
                waker
            } else {
                // Result is already set, so don't wake anything up
                None
            }
        };

        // If we need to wake the future, then do so here (note that we're outside of the lock when we do this)
        waker.map(|waker| waker.wake());
    }
}

impl<T> SchedulerFutureSignaller<T> {
    ///
    /// Signals that the result of the calculation is available
    ///
    pub (super) fn signal(self, result: T) {
        let waker = {
            let mut future_result = self.0.lock().unwrap();

            // Set the result
            future_result.result = FutureResultState::Some(Ok(result));

            // Retrieve the waker
            future_result.waker.take()
        };

        // If we retrieved a waker from the result, wake it up
        waker.map(|waker| waker.wake());
    }
}

///
/// Possible actions we can take based on the state of the signal for the future
///
enum SchedulerAction<T> {
    /// Queue is running elsewhere: we should wait for it to reach the point where the future's result is available
    WaitForCompletion,

    /// Future has already completed: we should return the value to sender
    ReturnValue(T),

    /// We've claimed the 'running' state of the queue and should drain it
    DrainQueue
}

impl<T> Future for SchedulerFuture<T> {
    type Output = Result<T, oneshot::Canceled>;

    ///
    /// Polls this future
    ///
    fn poll(self: Pin<&mut Self>, context: &mut task::Context) -> task::Poll<Self::Output> {
        // Lock the result and determine which action to take
        let next_action = {
            let mut future_result = self.result.lock().unwrap();

            if let Some(result) = future_result.result.take() {
                // The result is available: we should return it immediately
                SchedulerAction::ReturnValue(result)
            } else {
                // Wake us up when the future is available
                future_result.waker = Some(context.waker().clone());

                SchedulerAction::WaitForCompletion
            }
        };

        match next_action {
            SchedulerAction::WaitForCompletion  => task::Poll::Pending,
            SchedulerAction::ReturnValue(value) => task::Poll::Ready(value),
            SchedulerAction::DrainQueue         => unimplemented!()
        }
    }
}
<commit_msg>Claim to be running the queue if polled while idle (ie, avoid rescheduling on another thread)<commit_after>use super::job_queue::*;
use super::queue_state::*;

use futures::prelude::*;
use futures::channel::oneshot;
use futures::task;

use std::mem;
use std::sync::*;
use std::pin::{Pin};

///
/// The possible states of a future result
///
enum FutureResultState<T> {
    None,
    Some(T),
    ReturnedViaFuture
}

///
/// Signalling structure used to return the result of a scheduler future
///
struct SchedulerFutureResult<T> {
    /// The result of the future, or None if it has not been generated yet
    result: FutureResultState<Result<T, oneshot::Canceled>>,

    /// The waker to be called when the future is available
    waker: Option<task::Waker>
}

///
/// Wrapper that cancels the future if it is dropped before it is signalled
///
pub (super) struct SchedulerFutureSignaller<T>(Arc<Mutex<SchedulerFutureResult<T>>>);

///
/// Future representing a task pending on a scheduler
///
/// If polled when no threads are available, this future will run synchronously on the current thread
/// (stealing its execution time rather than blocking)
///
pub struct SchedulerFuture<T> {
    /// The queue which will eventually evaluate the result of this future
    queue: Arc<JobQueue>,

    /// A container for the result of this scheduler future
    result: Arc<Mutex<SchedulerFutureResult<T>>>
}

impl<T> FutureResultState<T> {
    ///
    /// Returns true if no result has ever been generated for this future
    ///
    fn is_none(&self) -> bool {
        match self {
            FutureResultState::None                 => true,
            FutureResultState::Some(_)              => false,
            FutureResultState::ReturnedViaFuture    => false
        }
    }

    ///
    /// If a result has been generated by this future and has not previously been taken, returns it
    ///
    fn take(&mut self) -> Option<T> {
        // Move the value out of this object
        let mut new_value = FutureResultState::ReturnedViaFuture;
        mem::swap(self, &mut new_value);

        // Return it if it contains a value
        match new_value {
            FutureResultState::None                 => { *self = FutureResultState::None; None },
            FutureResultState::ReturnedViaFuture    => { *self = FutureResultState::ReturnedViaFuture; None },
            FutureResultState::Some(value)          => { Some(value) }
        }
    }
}

impl<T> Drop for SchedulerFutureSignaller<T> {
    fn drop(&mut self) {
        let waker = {
            let mut future_result = self.0.lock().unwrap();

            // If no result has been generated, then mark the future as canceled
            if future_result.result.is_none() {
                // Mark the future as canceled
                future_result.result = FutureResultState::Some(Err(oneshot::Canceled));

                // Wake up anything that was polling it
                let waker = future_result.waker.take();
                waker
            } else {
                // Result is already set, so don't wake anything up
                None
            }
        };

        // If we need to wake the future, then do so here (note that we're outside of the lock when we do this)
        waker.map(|waker| waker.wake());
    }
}

impl<T> SchedulerFutureSignaller<T> {
    ///
    /// Signals that the result of the calculation is available
    ///
    pub (super) fn signal(self, result: T) {
        let waker = {
            let mut future_result = self.0.lock().unwrap();

            // Set the result
            future_result.result = FutureResultState::Some(Ok(result));

            // Retrieve the waker
            future_result.waker.take()
        };

        // If we retrieved a waker from the result, wake it up
        waker.map(|waker| waker.wake());
    }
}

///
/// Possible actions we can take based on the state of the signal for the future
///
enum SchedulerAction<T> {
    /// Queue is running elsewhere: we should wait for it to reach the point where the future's result is available
    WaitForCompletion,

    /// Future has already completed: we should return the value to sender
    ReturnValue(T),

    /// We've claimed the 'running' state of the queue and should drain it
    DrainQueue,

    /// The queue has panicked
    Panic
}

impl<T> SchedulerFuture<T> {
    ///
    /// Creates a new scheduler future and the result needed to signal it
    ///
    pub (super) fn new(queue: &Arc<JobQueue>) -> (SchedulerFuture<T>, SchedulerFutureSignaller<T>) {
        // Create an unfinished result
        let result = SchedulerFutureResult {
            result: FutureResultState::None,
            waker:  None
        };
        let result = Arc::new(Mutex::new(result));

        // Insert into a future
        let future = SchedulerFuture {
            queue:  Arc::clone(queue),
            result: Arc::clone(&result)
        };

        (future, SchedulerFutureSignaller(result))
    }

    ///
    /// We moved the queue into the running state and need to drain it until we've got a result
    ///
    fn drain_queue(&mut self) -> task::Poll<Result<T, oneshot::Canceled>> {
        unimplemented!()
    }
}

impl<T> Future for SchedulerFuture<T> {
    type Output = Result<T, oneshot::Canceled>;

    ///
    /// Polls this future
    ///
    fn poll(mut self: Pin<&mut Self>, context: &mut task::Context) -> task::Poll<Self::Output> {
        // Lock the result and determine which action to take
        let next_action = {
            let mut future_result = self.result.lock().unwrap();

            if let Some(result) = future_result.result.take() {
                // The result is available: we should return it immediately
                SchedulerAction::ReturnValue(result)
            } else {
                // If the queue is idle when this is called, we need to schedule this task on this thread rather than one owned by the background process
                let run_action = {
                    let mut core = self.queue.core.lock().expect("JobQueue core lock");

                    match core.state {
                        QueueState::Suspended           => SchedulerAction::WaitForCompletion,
                        QueueState::Suspending          => SchedulerAction::WaitForCompletion,
                        QueueState::Running             => SchedulerAction::WaitForCompletion,
                        QueueState::WaitingForWake      => SchedulerAction::WaitForCompletion,
                        QueueState::AwokenWhileRunning  => SchedulerAction::WaitForCompletion,
                        QueueState::Panicked            => SchedulerAction::Panic,
                        QueueState::Pending             => { core.state = QueueState::Running; SchedulerAction::DrainQueue },
                        QueueState::Idle                => { core.state = QueueState::Running; SchedulerAction::DrainQueue }
                    }
                };

                if let SchedulerAction::WaitForCompletion = run_action {
                    // Wake us up when the future is available
                    future_result.waker = Some(context.waker().clone());
                }

                run_action
            }
        };

        match next_action {
            SchedulerAction::WaitForCompletion  => task::Poll::Pending,
            SchedulerAction::ReturnValue(value) => task::Poll::Ready(value),
            SchedulerAction::DrainQueue         => self.drain_queue(),
            SchedulerAction::Panic              => panic!("Cannot schedule jobs on a panicked queue"),
        }
    }
}
<|endoftext|>


<commit_before>//! build command
use clap::{App, Arg, SubCommand};

#[cfg(feature = "self-updates")]
mod internal {
    extern crate flate2;
    extern crate futures;
    extern crate hyper;
    extern crate hyper_rustls;
    extern crate same_file;
    extern crate tar;
    extern crate tokio_core;

    use self::flate2::FlateReadExt;
    use self::futures::future::{err, ok};
    use self::futures::{Future, Stream};
    use self::hyper::{Client, Method, Request, Uri};
    use self::tar::Archive;
    use self::tokio_core::reactor::{Core, Handle};
    use clap::ArgMatches;
    use config_env::ConfigEnv;
    use core::errors::{Error, Result};
    use core::{Context, Version};
    use std::env;
    use std::fs::{self, File};
    use std::io::{self, Cursor};
    use std::path::Path;
    use std::rc::Rc;
    use url::Url;
    use VERSION;

    #[cfg(target_os = "macos")]
    mod os {
        pub const PLATFORM: Option<&str> = Some("osx");
        pub const EXT: Option<&str> = Some("");
    }

    #[cfg(target_os = "linux")]
    mod os {
        pub const PLATFORM: Option<&str> = Some("linux");
        pub const EXT: Option<&str> = Some("");
    }

    #[cfg(target_os = "windows")]
    mod os {
        pub const PLATFORM: Option<&str> = Some("windows");
        pub const EXT: Option<&str> = Some(".exe");
    }

    #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
    mod os {
        pub const PLATFORM: Option<&str> = None;
        pub const EXT: Option<&str> = None;
    }

    #[cfg(target_arch = "x86_64")]
    const ARCH: Option<&str> = Some("x86_64");

    #[cfg(not(target_arch = "x86_64"))]
    const ARCH: Option<&str> = None;

    use self::os::PLATFORM;
    use self::os::EXT;

    const DEFAULT_URL: &str = "https://storage.googleapis.com/reproto-releases/";

    pub fn entry(_: Rc<Context>, m: &ArgMatches) -> Result<()> {
        let config =
            ConfigEnv::new()?.ok_or_else(|| format!("could not setup the reproto environment"))?;

        check_path(&config)?;

        let force = m.is_present("force");
        let prerelease = m.is_present("prerelease");

        let arch = ARCH.clone().or(m.value_of("arch")).ok_or_else(|| {
            format!("Architecture could not be detected, and is not specified with `--arch`")
        })?;

        let platform = PLATFORM.clone().or(m.value_of("platform")).ok_or_else(|| {
            format!("Platform could not be detected, and is not specified with `--platform`")
        })?;

        let ext = EXT.clone().or(m.value_of("ext")).ok_or_else(|| {
            format!(
                "Binary could not be detected, and is not specified with `--ext`. Should be \
                 something like `reproto` or `reproto.exe`"
            )
        })?;

        let current = Version::parse(VERSION)?;

        let url = m.value_of("url").unwrap_or(DEFAULT_URL);
        let url = Url::parse(url)?;

        let mut core = Core::new()?;
        let handle = core.handle();

        let mut client = UpdateClient::new(handle, url)?;

        let mut releases = core.run(client.get_releases())?;

        releases.sort();

        let releases = match prerelease {
            true => releases,
            false => releases
                .into_iter()
                .filter(|r| !r.is_prerelease())
                .collect(),
        };

        let candidate = if !force {
            releases.into_iter().filter(|r| r > &current).last()
        } else {
            releases.into_iter().last()
        };

        let version = match candidate {
            Some(version) => version,
            None => {
                info!("reproto is up-to-date!");
                return Ok(());
            }
        };

        let tuple = format!("{}-{}-{}", version, platform, arch);

        let archived = config
            .releases_dir
            .join(format!("reproto-{}{}", tuple, ext));
        let binary = format!("reproto{}", ext);

        if !archived.is_file() || force {
            let release = core.run(client.get_release(&version, platform, arch))
                .map_err(|e| format!("{}: failed to download archive: {}", tuple, e.display()))?;

            download_archive(release, &archived, &binary).map_err(|e| {
                format!(
                    "failed to download archive to: {}: {}",
                    archived.display(),
                    e.display()
                )
            })?;

            info!("wrote: {}", archived.display());
        }

        let bin = config.bin_home.join(binary);

        setup_symlink(&archived, &bin).map_err(|e| {
            format!(
                "failed to setup symlink to: {}: {}",
                bin.display(),
                e.display()
            )
        })?;

        return Ok(());

        /// Checks that bin_home is in PATH, or warns otherwise.
        fn check_path(config: &ConfigEnv) -> Result<()> {
            let mut bin_in_path = false;

            if config.bin_home.is_dir() {
                if let Some(paths) = env::var_os("PATH") {
                    for path in env::split_paths(&paths) {
                        if !path.is_dir() {
                            continue;
                        }

                        if same_file::is_same_file(path, &config.bin_home)? {
                            bin_in_path = true;
                        }
                    }
                }
            }

            if !bin_in_path {
                warn!(
                    "{}: is not in your PATH. This is required for reproto to work!",
                    config.bin_home.display()
                );
            }

            Ok(())
        }

        fn download_archive(release: Vec<u8>, out: &Path, binary: &str) -> Result<()> {
            let mut archive = Archive::new(Cursor::new(release).gz_decode()?);

            for file in archive.entries()? {
                let mut file = file?;

                {
                    let path_bytes = file.header().path_bytes();
                    let path = ::std::str::from_utf8(path_bytes.as_ref())?;

                    if path != binary {
                        warn!("got unexpected file in archive: {}", path);
                        continue;
                    }
                }

                if let Some(parent) = out.parent() {
                    if !parent.is_dir() {
                        info!("creating directory: {}", parent.display());
                        fs::create_dir_all(parent)?;
                    }
                }

                info!("writing: {}", out.display());
                let mut w = File::create(out)?;
                io::copy(&mut file, &mut w)?;

                let metadata = w.metadata()?;
                let mut perm = metadata.permissions();
                set_executable(&mut perm);
                w.set_permissions(perm)?;
                break;
            }

            return Ok(());

            #[cfg(any(target_os = "linux", target_os = "macos"))]
            fn set_executable(p: &mut fs::Permissions) {
                use std::os::unix::fs::PermissionsExt;
                p.set_mode(0755);
            }

            #[cfg(target_os = "windows")]
            fn set_executable(_p: &mut fs::Permissions) {
                // nothing to do on windows.
            }

            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
            fn set_executable(_p: &mut fs::Permissions) {
                warn!("cannot update permissions on this platform");
            }
        }

        fn setup_symlink(archived: &Path, bin: &Path) -> Result<()> {
            if let Some(parent) = bin.parent() {
                if !parent.is_dir() {
                    info!("creating directory: {}", parent.display());
                    fs::create_dir_all(parent)?;
                }
            }

            info!("creating symlink: {}", bin.display());

            if bin.is_file() {
                fs::remove_file(bin)?;
            }

            symlink(archived, bin)?;
            return Ok(());

            #[cfg(not(target_os = "windows"))]
            fn symlink(archived: &Path, bin: &Path) -> Result<()> {
                use std::os::unix;
                unix::fs::symlink(archived, bin)?;
                Ok(())
            }

            #[cfg(target_os = "windows")]
            fn symlink(archived: &Path, bin: &Path) -> Result<()> {
                use std::os::windows;
                windows::fs::symlink_file(archived, bin)?;
                Ok(())
            }
        }
    }

    struct UpdateClient {
        client: Client<hyper_rustls::HttpsConnector>,
        url: Url,
    }

    impl UpdateClient {
        pub fn new(handle: Handle, url: Url) -> Result<Self> {
            let client = Client::configure()
                .connector(hyper_rustls::HttpsConnector::new(4, &handle))
                .build(&handle);

            Ok(Self { client, url })
        }

        fn request(&mut self, request: Request) -> Box<Future<Item = Vec<u8>, Error = Error>> {
            Box::new(
                self.client
                    .request(request)
                    .map_err(|e| Error::from(e))
                    .and_then(|res| {
                        let status = res.status().clone();

                        res.body()
                            .map_err(|e| Error::from(e))
                            .fold(Vec::new(), |mut out: Vec<u8>, chunk| {
                                out.extend(chunk.as_ref());
                                ok::<_, Error>(out)
                            })
                            .map(move |body| (body, status))
                    })
                    .and_then(|(body, status)| {
                        if !status.is_success() {
                            if let Ok(body) = String::from_utf8(body) {
                                return err(format!("bad response: {}: {}", status, body).into());
                            }

                            return err(format!("bad response: {}", status).into());
                        }

                        ok(body)
                    }),
            )
        }

        pub fn get_releases(&mut self) -> Box<Future<Item = Vec<Version>, Error = Error>> {
            let url = match self.url.join("releases") {
                Err(e) => return Box::new(err(e.into())),
                Ok(url) => url,
            };

            let uri = match url.as_ref().parse::<Uri>() {
                Err(e) => return Box::new(err(e.into())),
                Ok(uri) => uri,
            };

            let request = Request::new(Method::Get, uri);

            let url = url.clone();

            let future = self.request(request)
                .and_then(|body| {
                    let body = match String::from_utf8(body) {
                        Err(e) => return err(format!("body is not utf-8: {}", e).into()),
                        Ok(body) => body,
                    };

                    let mut out = Vec::new();

                    for line in body.split('\n') {
                        let line = line.trim();

                        if line.is_empty() {
                            continue;
                        }

                        let version = match Version::parse(line) {
                            Err(e) => return err(e.into()),
                            Ok(version) => version,
                        };

                        out.push(version);
                    }

                    ok(out)
                })
                .map_err(move |e| format!("request to `{}` failed: {}", url, e.display()).into());

            Box::new(future)
        }

        pub fn get_release(
            &mut self,
            version: &Version,
            platform: &str,
            arch: &str,
        ) -> Box<Future<Item = Vec<u8>, Error = Error>> {
            let url = match self.url
                .join(&format!("reproto-{}-{}-{}.tar.gz", version, platform, arch))
            {
                Err(e) => return Box::new(err(e.into())),
                Ok(url) => url,
            };

            let uri = match url.as_ref().parse::<Uri>() {
                Err(e) => return Box::new(err(e.into())),
                Ok(uri) => uri,
            };

            let request = Request::new(Method::Get, uri);

            let url = url.clone();

            let future = self.request(request)
                .map_err(move |e| format!("request to `{}` failed: {}", url, e.display()).into());

            Box::new(future)
        }
    }
}

#[cfg(not(feature = "self-updates"))]
mod internal {
    use clap::ArgMatches;
    use core::errors::Result;
    use core::Context;
    use std::rc::Rc;

    pub fn entry(_: Rc<Context>, _: &ArgMatches) -> Result<()> {
        return Err("support for self-updates is not enabled".into());
    }
}

pub use self::internal::entry;

pub fn options<'a, 'b>() -> App<'a, 'b> {
    let out = SubCommand::with_name("self-update").about("Update reproto");

    let out = out.arg(
        Arg::with_name("url")
            .long("url")
            .takes_value(true)
            .help("URL to download updates from."),
    );

    let out = out.arg(
        Arg::with_name("arch")
            .long("arch")
            .takes_value(true)
            .help("Architecture to update for"),
    );

    let out = out.arg(
        Arg::with_name("platform")
            .long("platform")
            .takes_value(true)
            .help("Architecture to update for"),
    );

    let out =
        out.arg(Arg::with_name("ext").long("ext").takes_value(true).help(
            "File extension of binary to expect, should be something like `.exe` on windows.",
        ));

    let out = out.arg(
        Arg::with_name("force")
            .short("f")
            .long("force")
            .help("Force downloading the latest release, even though it is already installed"),
    );

    let out = out.arg(
        Arg::with_name("prerelease")
            .long("pre")
            .help("Download a pre-release if available"),
    );

    out
}
<commit_msg>self_update: follow redirects<commit_after>//! build command
use clap::{App, Arg, SubCommand};

#[cfg(feature = "self-updates")]
mod internal {
    extern crate flate2;
    extern crate futures;
    extern crate hyper;
    extern crate hyper_rustls;
    extern crate same_file;
    extern crate tar;
    extern crate tokio_core;

    use self::flate2::FlateReadExt;
    use self::futures::future::{err, ok};
    use self::futures::{Future, Stream};
    use self::hyper::header::Location;
    use self::hyper::{Client, Method, Request, Response, StatusCode, Uri};
    use self::tar::Archive;
    use self::tokio_core::reactor::{Core, Handle};
    use clap::ArgMatches;
    use config_env::ConfigEnv;
    use core::errors::{Error, Result};
    use core::{Context, Version};
    use std::env;
    use std::fs::{self, File};
    use std::io::{self, Cursor};
    use std::path::Path;
    use std::rc::Rc;
    use std::sync::Arc;
    use url::Url;
    use VERSION;

    #[cfg(target_os = "macos")]
    mod os {
        pub const PLATFORM: Option<&str> = Some("osx");
        pub const EXT: Option<&str> = Some("");
    }

    #[cfg(target_os = "linux")]
    mod os {
        pub const PLATFORM: Option<&str> = Some("linux");
        pub const EXT: Option<&str> = Some("");
    }

    #[cfg(target_os = "windows")]
    mod os {
        pub const PLATFORM: Option<&str> = Some("windows");
        pub const EXT: Option<&str> = Some(".exe");
    }

    #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
    mod os {
        pub const PLATFORM: Option<&str> = None;
        pub const EXT: Option<&str> = None;
    }

    #[cfg(target_arch = "x86_64")]
    const ARCH: Option<&str> = Some("x86_64");

    #[cfg(not(target_arch = "x86_64"))]
    const ARCH: Option<&str> = None;

    use self::os::EXT;
    use self::os::PLATFORM;

    const DEFAULT_URL: &str = "https://storage.googleapis.com/reproto-releases/";

    pub fn entry(_: Rc<Context>, m: &ArgMatches) -> Result<()> {
        let config =
            ConfigEnv::new()?.ok_or_else(|| format!("could not setup the reproto environment"))?;

        check_path(&config)?;

        let force = m.is_present("force");
        let prerelease = m.is_present("prerelease");

        let arch = ARCH.clone().or(m.value_of("arch")).ok_or_else(|| {
            format!("Architecture could not be detected, and is not specified with `--arch`")
        })?;

        let platform = PLATFORM.clone().or(m.value_of("platform")).ok_or_else(|| {
            format!("Platform could not be detected, and is not specified with `--platform`")
        })?;

        let ext = EXT.clone().or(m.value_of("ext")).ok_or_else(|| {
            format!(
                "Binary could not be detected, and is not specified with `--ext`. Should be \
                 something like `reproto` or `reproto.exe`"
            )
        })?;

        let current = Version::parse(VERSION)?;

        let url = m.value_of("url").unwrap_or(DEFAULT_URL);
        let url = Url::parse(url)?;

        let mut core = Core::new()?;
        let handle = core.handle();

        let mut client = UpdateClient::new(handle, url)?;

        let mut releases = core.run(client.get_releases())?;

        releases.sort();

        let releases = match prerelease {
            true => releases,
            false => releases
                .into_iter()
                .filter(|r| !r.is_prerelease())
                .collect(),
        };

        let candidate = if !force {
            releases.into_iter().filter(|r| r > &current).last()
        } else {
            releases.into_iter().last()
        };

        let version = match candidate {
            Some(version) => version,
            None => {
                info!("reproto is up-to-date!");
                return Ok(());
            }
        };

        let tuple = format!("{}-{}-{}", version, platform, arch);

        let archived = config
            .releases_dir
            .join(format!("reproto-{}{}", tuple, ext));
        let binary = format!("reproto{}", ext);

        if !archived.is_file() || force {
            let release = core.run(client.get_release(&version, platform, arch))
                .map_err(|e| format!("{}: failed to download archive: {}", tuple, e.display()))?;

            download_archive(release, &archived, &binary).map_err(|e| {
                format!(
                    "failed to download archive to: {}: {}",
                    archived.display(),
                    e.display()
                )
            })?;

            info!("wrote: {}", archived.display());
        }

        let bin = config.bin_home.join(binary);

        setup_symlink(&archived, &bin).map_err(|e| {
            format!(
                "failed to setup symlink to: {}: {}",
                bin.display(),
                e.display()
            )
        })?;

        return Ok(());

        /// Checks that bin_home is in PATH, or warns otherwise.
        fn check_path(config: &ConfigEnv) -> Result<()> {
            let mut bin_in_path = false;

            if config.bin_home.is_dir() {
                if let Some(paths) = env::var_os("PATH") {
                    for path in env::split_paths(&paths) {
                        if !path.is_dir() {
                            continue;
                        }

                        if same_file::is_same_file(path, &config.bin_home)? {
                            bin_in_path = true;
                        }
                    }
                }
            }

            if !bin_in_path {
                warn!(
                    "{}: is not in your PATH. This is required for reproto to work!",
                    config.bin_home.display()
                );
            }

            Ok(())
        }

        fn download_archive(release: Vec<u8>, out: &Path, binary: &str) -> Result<()> {
            let mut archive = Archive::new(Cursor::new(release).gz_decode()?);

            for file in archive.entries()? {
                let mut file = file?;

                {
                    let path_bytes = file.header().path_bytes();
                    let path = ::std::str::from_utf8(path_bytes.as_ref())?;

                    if path != binary {
                        warn!("got unexpected file in archive: {}", path);
                        continue;
                    }
                }

                if let Some(parent) = out.parent() {
                    if !parent.is_dir() {
                        info!("creating directory: {}", parent.display());
                        fs::create_dir_all(parent)?;
                    }
                }

                info!("writing: {}", out.display());
                let mut w = File::create(out)?;
                io::copy(&mut file, &mut w)?;

                let metadata = w.metadata()?;
                let mut perm = metadata.permissions();
                set_executable(&mut perm);
                w.set_permissions(perm)?;
                break;
            }

            return Ok(());

            #[cfg(any(target_os = "linux", target_os = "macos"))]
            fn set_executable(p: &mut fs::Permissions) {
                use std::os::unix::fs::PermissionsExt;
                p.set_mode(0755);
            }

            #[cfg(target_os = "windows")]
            fn set_executable(_p: &mut fs::Permissions) {
                // nothing to do on windows.
            }

            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
            fn set_executable(_p: &mut fs::Permissions) {
                warn!("cannot update permissions on this platform");
            }
        }

        fn setup_symlink(archived: &Path, bin: &Path) -> Result<()> {
            if let Some(parent) = bin.parent() {
                if !parent.is_dir() {
                    info!("creating directory: {}", parent.display());
                    fs::create_dir_all(parent)?;
                }
            }

            info!("creating symlink: {}", bin.display());

            if bin.is_file() {
                fs::remove_file(bin)?;
            }

            symlink(archived, bin)?;
            return Ok(());

            #[cfg(not(target_os = "windows"))]
            fn symlink(archived: &Path, bin: &Path) -> Result<()> {
                use std::os::unix;
                unix::fs::symlink(archived, bin)?;
                Ok(())
            }

            #[cfg(target_os = "windows")]
            fn symlink(archived: &Path, bin: &Path) -> Result<()> {
                use std::os::windows;
                windows::fs::symlink_file(archived, bin)?;
                Ok(())
            }
        }
    }

    struct UpdateClient {
        client: Arc<Client<hyper_rustls::HttpsConnector>>,
        url: Url,
    }

    impl UpdateClient {
        pub fn new(handle: Handle, url: Url) -> Result<Self> {
            let client = Client::configure()
                .connector(hyper_rustls::HttpsConnector::new(4, &handle))
                .build(&handle);

            Ok(Self {
                client: Arc::new(client),
                url,
            })
        }

        /// Handle redirects for request.
        fn handle_redirect(
            client: Arc<Client<hyper_rustls::HttpsConnector>>,
            res: &Response,
        ) -> Option<Box<Future<Item = Vec<u8>, Error = Error>>> {
            let should_redirect = match res.status() {
                StatusCode::MovedPermanently
                | StatusCode::Found
                | StatusCode::SeeOther
                | StatusCode::TemporaryRedirect
                | StatusCode::PermanentRedirect => true,
                _ => false,
            };

            if should_redirect {
                let uri = if let Some(loc) = res.headers().get::<Location>() {
                    match ::std::str::from_utf8(loc.as_bytes())
                        .map_err(Error::from)
                        .and_then(|s| s.parse::<Uri>().map_err(Error::from))
                    {
                        Ok(uri) => uri,
                        Err(e) => return Some(Box::new(err(e))),
                    }
                } else {
                    return None;
                };

                let req = Request::new(Method::Get, uri);
                return Some(Box::new(Self::request(client, req)));
            }

            return None;
        }

        /// Perform the given request.
        fn request(
            client: Arc<Client<hyper_rustls::HttpsConnector>>,
            req: Request,
        ) -> Box<Future<Item = Vec<u8>, Error = Error>> {
            let inner_client = Arc::clone(&client);

            Box::new(
                client
                    .request(req)
                    .map_err(|e| Error::from(e))
                    .and_then(move |res| {
                        if let Some(future) = Self::handle_redirect(inner_client, &res) {
                            return future;
                        }

                        let status = res.status().clone();

                        let fut = res.body()
                            .map_err(|e| Error::from(e))
                            .fold(Vec::new(), |mut out: Vec<u8>, chunk| {
                                out.extend(chunk.as_ref());
                                ok::<_, Error>(out)
                            })
                            .map(move |body| (body, status))
                            .and_then(|(body, status)| {
                                if !status.is_success() {
                                    if let Ok(body) = String::from_utf8(body) {
                                        return err(format!("bad response: {}: {}", status, body).into());
                                    }

                                    return err(format!("bad response: {}", status).into());
                                }

                                ok(body)
                            });

                        Box::new(fut)
                    }),
            )
        }

        pub fn get_releases(&mut self) -> Box<Future<Item = Vec<Version>, Error = Error>> {
            let url = match self.url.join("releases") {
                Err(e) => return Box::new(err(e.into())),
                Ok(url) => url,
            };

            let uri = match url.as_ref().parse::<Uri>() {
                Err(e) => return Box::new(err(e.into())),
                Ok(uri) => uri,
            };

            let request = Request::new(Method::Get, uri);

            let url = url.clone();

            let future = Self::request(Arc::clone(&self.client), request)
                .and_then(|body| {
                    let body = match String::from_utf8(body) {
                        Err(e) => return err(format!("body is not utf-8: {}", e).into()),
                        Ok(body) => body,
                    };

                    let mut out = Vec::new();

                    for line in body.split('\n') {
                        let line = line.trim();

                        if line.is_empty() {
                            continue;
                        }

                        let version = match Version::parse(line) {
                            Err(e) => return err(e.into()),
                            Ok(version) => version,
                        };

                        out.push(version);
                    }

                    ok(out)
                })
                .map_err(move |e| format!("request to `{}` failed: {}", url, e.display()).into());

            Box::new(future)
        }

        pub fn get_release(
            &mut self,
            version: &Version,
            platform: &str,
            arch: &str,
        ) -> Box<Future<Item = Vec<u8>, Error = Error>> {
            let url = match self.url
                .join(&format!("reproto-{}-{}-{}.tar.gz", version, platform, arch))
            {
                Err(e) => return Box::new(err(e.into())),
                Ok(url) => url,
            };

            let uri = match url.as_ref().parse::<Uri>() {
                Err(e) => return Box::new(err(e.into())),
                Ok(uri) => uri,
            };

            let request = Request::new(Method::Get, uri);

            let url = url.clone();

            let future = Self::request(Arc::clone(&self.client), request)
                .map_err(move |e| format!("request to `{}` failed: {}", url, e.display()).into());

            Box::new(future)
        }
    }
}

#[cfg(not(feature = "self-updates"))]
mod internal {
    use clap::ArgMatches;
    use core::errors::Result;
    use core::Context;
    use std::rc::Rc;

    pub fn entry(_: Rc<Context>, _: &ArgMatches) -> Result<()> {
        return Err("support for self-updates is not enabled".into());
    }
}

pub use self::internal::entry;

pub fn options<'a, 'b>() -> App<'a, 'b> {
    let out = SubCommand::with_name("self-update").about("Update reproto");

    let out = out.arg(
        Arg::with_name("url")
            .long("url")
            .takes_value(true)
            .help("URL to download updates from."),
    );

    let out = out.arg(
        Arg::with_name("arch")
            .long("arch")
            .takes_value(true)
            .help("Architecture to update for"),
    );

    let out = out.arg(
        Arg::with_name("platform")
            .long("platform")
            .takes_value(true)
            .help("Architecture to update for"),
    );

    let out =
        out.arg(Arg::with_name("ext").long("ext").takes_value(true).help(
            "File extension of binary to expect, should be something like `.exe` on windows.",
        ));

    let out = out.arg(
        Arg::with_name("force")
            .short("f")
            .long("force")
            .help("Force downloading the latest release, even though it is already installed"),
    );

    let out = out.arg(
        Arg::with_name("prerelease")
            .long("pre")
            .help("Download a pre-release if available"),
    );

    out
}
<|endoftext|>


<commit_before>fn generate_table () {
    let pi: f32 = 3.1415926536897932384626;
    let k1: f32 = 0.6072529350088812561694; // 1/k
    let num_bits: uint = 32;
    let num_elms: uint = num_bits;
    let mul: uint = 1<<(num_bits-2);

    println!("Cordic sin in rust");
    println!("num bits {}", num_bits);
    println!("pi is {}", pi);
    println!("k1 is {}", k1);

    let shift: f32 = 2.0;
    for ii in range(0, num_bits) {
        let ipow: f32 = 1.0/shift.powi(ii as i32);
        let cur: f32 = ipow.atan();
        println!("table values {}", cur);
    }
}

fn main() {
    generate_table();
}
<commit_msg>show more bits of precision<commit_after>fn generate_table () {
    let pi: f32 = 3.1415926536897932384626;
    let k1: f32 = 0.6072529350088812561694; // 1/k
    let num_bits: uint = 32;
    let num_elms: uint = num_bits;
    let mul: uint = 1<<(num_bits-2);

    println!("Cordic sin in rust");
    println!("num bits {}", num_bits);
    println!("pi is {}", pi);
    println!("k1 is {}", k1);

    let shift: f32 = 2.0;
    for ii in range(0, num_bits) {
        let ipow: f32 = 1.0/shift.powi(ii as i32);
        let cur: f32 = ipow.atan();
        println!("table values {:.31f}", cur);
    }
}

fn main() {
    generate_table();
}
<|endoftext|>


<commit_before>//! [POST /_matrix/client/r0/createRoom](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-createroom)

use ruma_api::ruma_api;
use ruma_common::Raw;
use ruma_events::{
    room::{
        create::{CreateEventContent, PreviousRoom},
        power_levels::PowerLevelsEventContent,
    },
    EventType,
};
use ruma_identifiers::{RoomId, RoomVersionId, UserId};
use serde::{Deserialize, Serialize};
use serde_json::value::RawValue as RawJsonValue;

use super::Visibility;
use crate::r0::membership::Invite3pid;

ruma_api! {
    metadata: {
        description: "Create a new room.",
        method: POST,
        name: "create_room",
        path: "/_matrix/client/r0/createRoom",
        rate_limited: false,
        requires_authentication: true,
    }

    request: {
        /// Extra keys to be added to the content of the `m.room.create`.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub creation_content: Option<CreationContent>,

        /// List of state events to send to the new room.
        ///
        /// Takes precedence over events set by preset, but gets overriden by
        /// name and topic keys.
        #[serde(default, skip_serializing_if = "Vec::is_empty")]
        pub initial_state: Vec<InitialStateEvent>,

        /// A list of user IDs to invite to the room.
        ///
        /// This will tell the server to invite everyone in the list to the newly created room.
        #[serde(default, skip_serializing_if = "Vec::is_empty")]
        pub invite: Vec<UserId>,

        /// List of third party IDs of users to invite.
        #[serde(default, skip_serializing_if = "Vec::is_empty")]
        pub invite_3pid: Vec<Invite3pid>,

        /// If set, this sets the `is_direct` flag on room invites.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub is_direct: Option<bool>,

        /// If this is included, an `m.room.name` event will be sent into the room to indicate
        /// the name of the room.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub name: Option<String>,

        /// Power level content to override in the default power level event.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub power_level_content_override: Option<Raw<PowerLevelsEventContent>>,

        /// Convenience parameter for setting various default state events based on a preset.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub preset: Option<RoomPreset>,

        /// The desired room alias local part.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub room_alias_name: Option<String>,

        /// Room version to set for the room. Defaults to homeserver's default if not specified.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub room_version: Option<String>,

        /// If this is included, an `m.room.topic` event will be sent into the room to indicate
        /// the topic for the room.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub topic: Option<String>,

        /// A public visibility indicates that the room will be shown in the published room
        /// list. A private visibility will hide the room from the published room list. Rooms
        /// default to private visibility if this key is not included.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub visibility: Option<Visibility>,
    }

    response: {
        /// The created room's ID.
        pub room_id: RoomId,
    }

    error: crate::Error
}

impl Request {
    /// Creates a `Request` will all-default parameters.
    pub fn new() -> Self {
        Self {
            creation_content: None,
            initial_state: Vec::new(),
            invite: Vec::new(),
            invite_3pid: Vec::new(),
            is_direct: None,
            name: None,
            power_level_content_override: None,
            preset: None,
            room_alias_name: None,
            room_version: None,
            topic: None,
            visibility: None,
        }
    }
}

/// Extra options to be added to the `m.room.create` event.
///
/// This is the same as the event content struct for `m.room.create`, but without some fields that
/// servers are supposed to ignore.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CreationContent {
    /// Whether users on other servers can join this room.
    ///
    /// Defaults to `true` if key does not exist.
    #[serde(
        rename = "m.federate",
        default = "ruma_serde::default_true",
        skip_serializing_if = "ruma_serde::is_true"
    )]
    pub federate: bool,
    /// A reference to the room this room replaces, if the previous room was upgraded.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub predecessor: Option<PreviousRoom>,
}

impl CreationContent {
    /// Given a `CreationContent` and the other fields that a homeserver has to fill, construct
    /// a `CreateEventContent`.
    pub fn into_event_content(
        Self { federate, predecessor }: Self,
        creator: UserId,
        room_version: RoomVersionId,
    ) -> CreateEventContent {
        CreateEventContent { creator, federate, room_version, predecessor }
    }
}

/// A convenience parameter for setting a few default state events.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum RoomPreset {
    /// `join_rules` is set to `invite` and `history_visibility` is set to `shared`.
    PrivateChat,

    /// `join_rules` is set to `public` and `history_visibility` is set to `shared`.
    PublicChat,

    /// Same as `PrivateChat`, but all initial invitees get the same power level as the creator.
    TrustedPrivateChat,
}

/// Represents content of a state event to be used to initalize new room state.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InitialStateEvent {
    /// State event type.
    // FIXME: This should really only be a subset of the EventType enum.
    #[serde(rename = "type")]
    pub event_type: EventType,

    /// `state_key` of the event to be sent.
    pub state_key: Option<String>,

    /// JSON content of the state event.
    ///
    /// To create a `Box<RawJsonValue>`, use `serde_json::value::to_raw_value`.
    pub content: Box<RawJsonValue>,
}
<commit_msg>fixup! Mark types in ruma_events::room::create as non_exhaustive<commit_after>//! [POST /_matrix/client/r0/createRoom](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-createroom)

use ruma_api::ruma_api;
use ruma_common::Raw;
use ruma_events::{
    room::{
        create::{CreateEventContent, PreviousRoom},
        power_levels::PowerLevelsEventContent,
    },
    EventType,
};
use ruma_identifiers::{RoomId, RoomVersionId, UserId};
use serde::{Deserialize, Serialize};
use serde_json::value::RawValue as RawJsonValue;

use super::Visibility;
use crate::r0::membership::Invite3pid;

ruma_api! {
    metadata: {
        description: "Create a new room.",
        method: POST,
        name: "create_room",
        path: "/_matrix/client/r0/createRoom",
        rate_limited: false,
        requires_authentication: true,
    }

    request: {
        /// Extra keys to be added to the content of the `m.room.create`.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub creation_content: Option<CreationContent>,

        /// List of state events to send to the new room.
        ///
        /// Takes precedence over events set by preset, but gets overriden by
        /// name and topic keys.
        #[serde(default, skip_serializing_if = "Vec::is_empty")]
        pub initial_state: Vec<InitialStateEvent>,

        /// A list of user IDs to invite to the room.
        ///
        /// This will tell the server to invite everyone in the list to the newly created room.
        #[serde(default, skip_serializing_if = "Vec::is_empty")]
        pub invite: Vec<UserId>,

        /// List of third party IDs of users to invite.
        #[serde(default, skip_serializing_if = "Vec::is_empty")]
        pub invite_3pid: Vec<Invite3pid>,

        /// If set, this sets the `is_direct` flag on room invites.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub is_direct: Option<bool>,

        /// If this is included, an `m.room.name` event will be sent into the room to indicate
        /// the name of the room.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub name: Option<String>,

        /// Power level content to override in the default power level event.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub power_level_content_override: Option<Raw<PowerLevelsEventContent>>,

        /// Convenience parameter for setting various default state events based on a preset.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub preset: Option<RoomPreset>,

        /// The desired room alias local part.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub room_alias_name: Option<String>,

        /// Room version to set for the room. Defaults to homeserver's default if not specified.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub room_version: Option<String>,

        /// If this is included, an `m.room.topic` event will be sent into the room to indicate
        /// the topic for the room.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub topic: Option<String>,

        /// A public visibility indicates that the room will be shown in the published room
        /// list. A private visibility will hide the room from the published room list. Rooms
        /// default to private visibility if this key is not included.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub visibility: Option<Visibility>,
    }

    response: {
        /// The created room's ID.
        pub room_id: RoomId,
    }

    error: crate::Error
}

impl Request {
    /// Creates a `Request` will all-default parameters.
    pub fn new() -> Self {
        Self {
            creation_content: None,
            initial_state: Vec::new(),
            invite: Vec::new(),
            invite_3pid: Vec::new(),
            is_direct: None,
            name: None,
            power_level_content_override: None,
            preset: None,
            room_alias_name: None,
            room_version: None,
            topic: None,
            visibility: None,
        }
    }
}

/// Extra options to be added to the `m.room.create` event.
///
/// This is the same as the event content struct for `m.room.create`, but without some fields that
/// servers are supposed to ignore.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CreationContent {
    /// Whether users on other servers can join this room.
    ///
    /// Defaults to `true` if key does not exist.
    #[serde(
        rename = "m.federate",
        default = "ruma_serde::default_true",
        skip_serializing_if = "ruma_serde::is_true"
    )]
    pub federate: bool,
    /// A reference to the room this room replaces, if the previous room was upgraded.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub predecessor: Option<PreviousRoom>,
}

impl CreationContent {
    /// Given a `CreationContent` and the other fields that a homeserver has to fill, construct
    /// a `CreateEventContent`.
    pub fn into_event_content(
        Self { federate, predecessor }: Self,
        creator: UserId,
        room_version: RoomVersionId,
    ) -> CreateEventContent {
        let mut res = CreateEventContent::new(creator);
        res.federate = federate;
        res.room_version = room_version;
        res.predecessor = predecessor;
        res
    }
}

/// A convenience parameter for setting a few default state events.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum RoomPreset {
    /// `join_rules` is set to `invite` and `history_visibility` is set to `shared`.
    PrivateChat,

    /// `join_rules` is set to `public` and `history_visibility` is set to `shared`.
    PublicChat,

    /// Same as `PrivateChat`, but all initial invitees get the same power level as the creator.
    TrustedPrivateChat,
}

/// Represents content of a state event to be used to initalize new room state.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InitialStateEvent {
    /// State event type.
    // FIXME: This should really only be a subset of the EventType enum.
    #[serde(rename = "type")]
    pub event_type: EventType,

    /// `state_key` of the event to be sent.
    pub state_key: Option<String>,

    /// JSON content of the state event.
    ///
    /// To create a `Box<RawJsonValue>`, use `serde_json::value::to_raw_value`.
    pub content: Box<RawJsonValue>,
}
<|endoftext|>


<commit_before>extern crate desync;
extern crate futures;

use desync::Desync;

mod scheduler;
use self::scheduler::timeout::*;

use futures::prelude::*;
use futures::future;

use std::sync::*;
use std::time::*;
use std::thread::*;

#[derive(Debug)]
struct TestData {
    val: u32
}

#[test]
fn retrieve_data_synchronously() {
    let desynced = Desync::new(TestData { val: 0 });

    assert!(desynced.sync(|data| data.val) == 0);
}

#[test]
fn retrieve_data_into_local_var() {
    let desynced = Desync::new(TestData { val: 42 });
    let mut val = 0;

    desynced.sync(|data| val = data.val);

    assert!(val == 42);
}

#[test]
fn update_data_asynchronously() {
    let desynced = Desync::new(TestData { val: 0 });

    desynced.desync(|data| {
        sleep(Duration::from_millis(100));
        data.val = 42;
    });

    assert!(desynced.sync(|data| data.val) == 42);
}

#[test]
fn update_data_asynchronously_1000_times() {
    for _i in 0..1000 {
        timeout(|| {
            let desynced = Desync::new(TestData { val: 0 });

            desynced.desync(|data| {
                data.val = 42;
            });
            desynced.desync(|data| {
                data.val = 43;
            });

            assert!(desynced.sync(|data| data.val) == 43);
        }, 500);
    }
}

#[test]
fn update_data_with_future() {
    timeout(|| {
        use futures::executor;

        let desynced = Desync::new(TestData { val: 0 });

        desynced.desync(|data| {
            sleep(Duration::from_millis(100));
            data.val = 42;
        });

        executor::block_on(async {
            let future = desynced.future(|data| { Box::pin(future::ready(data.val)) });
            assert!(future.await.unwrap() == 42);
        });
    }, 500);
}

#[test]
fn update_data_with_future_1000_times() {
    // Seems to timeout fairly reliably after signalling the future
    use futures::executor;

    for _i in 0..1000 {
        timeout(|| {
            let desynced = Desync::new(TestData { val: 0 });

            desynced.desync(|data| {
                data.val = 42;
            });
            desynced.desync(|data| {
                data.val = 43;
            });

            executor::block_on(async {
                let future = desynced.future(|data| Box::pin(future::ready(data.val)));

                assert!(future.await.unwrap() == 43);
            });
        }, 500);
    }
}

#[test]
fn dropping_while_running_isnt_obviously_bad() {
    let desynced = Desync::new(TestData { val: 0 });

    desynced.desync(|data| {
        sleep(Duration::from_millis(100));
        data.val = 42;
    });
    desynced.desync(|data| {
        sleep(Duration::from_millis(100));
        data.val = 42;
    });
}

#[test]
fn wait_for_future() {
    // TODO: occasional test failure that happens if the future 'arrives' before the queue is empty
    // (Because we need a future that arrives when the queue is actually suspended)
    timeout(|| {
        use futures::executor;
        use futures::channel::oneshot;

        // We use a oneshot as our future, and a mpsc channel to track progress
        let desynced                = Desync::new(0);
        let (future_tx, future_rx)  = oneshot::channel();

        // First value 0 -> 1
        desynced.desync(|val| {
            // Sleep here so the future should be waiting for us
            sleep(Duration::from_millis(100));
            assert!(*val == 0);
            *val = 1;
        });

        // Future should go 1 -> 2, but takes whatever future_tx sends
        let future = desynced.after(future_rx, |val, future_result| {
            assert!(*val == 1);
            *val = future_result.unwrap();

            // Return '4' to anything listening for this future
            4
        });

        // Finally, 3
        desynced.desync(move |val| { assert!(*val == 2); *val = 3 });

        executor::block_on(async {
            // Send '2' to the future
            future_tx.send(2).unwrap();

            // Future should resolve to 4
            assert!(future.await == Ok(4));

            // Final value should be 3
            assert!(desynced.sync(|val| *val) == 3);
        })
    }, 500);
}

#[test]
fn future_and_sync() {
    // This test seems to produce different behaviour if it's run by itself (this sleep tends to force it to run after the other tests and thus fail)
    // So far the failure seems reliable when this test is running exclusively
    sleep(Duration::from_millis(1000));

    use std::thread;
    use futures::prelude::*;
    use futures::channel::oneshot;

    // The idea here is we perform an action with a future() and read the result back with a sync() (which is a way you can mix-and-match
    // programming models with desync)
    //
    // The 'core' runs a request as a future, waiting for the channel result. We store the result in sync_request, and then retrieve
    // it again by calling sync - as Desync always runs things sequentially, it guarantees the ordering (something that's much harder
    // to achieve with a mutex)
    let (send, recv)    = oneshot::channel::<i32>();
    let core            = Desync::new(0);
    let sync_request    = Desync::new(None);

    // Send a request to the 'core' via the sync reqeust and store the result
    let _ = sync_request.future(move |data| {
        async move {
            let result = core.future(move |_core| {
                async move {
                    Some(recv.await.unwrap())
                }.boxed()
            }).await;

            *data = result.unwrap();
        }.boxed()
    });

    // Signal the future after a delay
    thread::spawn(move || {
        thread::sleep(Duration::from_millis(50));
        send.send(42).ok();
    });

    // Retrieve the result once the future completes
    let result = sync_request.sync(|req| req.take());

    // Should retrieve the value generated in the future
    assert!(result == Some(42));
}

#[test]
fn double_future_and_sync() {
    use std::thread;

    // TODO: signal with channels instead of using thread::sleep

    // This test will queue two futures here, each of which will need to return to another desync
    // If two futures are scheduled and triggered in a row when draining a queue that both signal
    let core        = Arc::new(Desync::new(()));

    let initiator_1 = Desync::new(None);
    let initiator_2 = Desync::new(None);
    let initiator_3 = Desync::new(None);

    let core_1      = Arc::clone(&core);
    let _           = initiator_1.future(move |val| {
        async move {
            // Wait for a task on the core
            *val = core_1.future(move |_| {
                async move { thread::sleep(Duration::from_millis(400)); Some(1) }.boxed()
            }).await.unwrap();
        }.boxed()
    });

    let core_2      = Arc::clone(&core);
    let _           = initiator_2.future(move |val| {
        async move {
            // Wait for the original initiator to start its future
            thread::sleep(Duration::from_millis(100));

            // Wait for a task on the core
            *val = core_2.future(move |_| {
                async move { thread::sleep(Duration::from_millis(200)); Some(2) }.boxed()
            }).await.unwrap();
        }.boxed()
    });

    let core_3      = Arc::clone(&core);
    let _           = initiator_3.future(move |val| {
        async move {
            // Wait for the original initiator to start its future
            thread::sleep(Duration::from_millis(200));

            // Wait for a task on the core
            *val = core_3.future(move |_| {
                async move { thread::sleep(Duration::from_millis(200)); Some(3) }.boxed()
            }).await.unwrap();
        }.boxed()
    });

    // Wait for the result from the futures synchronously
    assert!(initiator_3.sync(|val| { *val }) == Some(3));
    assert!(initiator_2.sync(|val| { *val }) == Some(2));
    assert!(initiator_1.sync(|val| { *val }) == Some(1));
}

#[test]
fn try_sync_succeeds_on_idle_queue() {
    timeout(|| {
        let core        = Desync::new(0);

        // Queue is doing nothing, so try_sync should succeed
        let sync_result = core.try_sync(|val| {
            *val = 42;
            1
        });

        // Queue is idle, so we should receive a result
        assert!(sync_result == Ok(1));

        // Double-check that the value was updated
        assert!(core.sync(|val| *val) == 42);
    }, 500);
}

#[test]
fn try_sync_succeeds_on_idle_queue_after_async_job() {
    timeout(|| {
        use std::thread;
        let core        = Desync::new(0);

        // Schedule something asynchronously and wait for it to complete
        core.desync(|_val| thread::sleep(Duration::from_millis(50)));
        core.sync(|_val| { });

        // Queue is doing nothing, so try_sync should succeed
        let sync_result = core.try_sync(|val| {
            *val= 42;
            1
        });

        // Queue is idle, so we should receive a result
        assert!(sync_result == Ok(1));

        // Double-check that the value was updated
        assert!(core.sync(|val| *val) == 42);
    }, 500);
}

#[test]
fn try_sync_fails_on_busy_queue() {
    timeout(|| {
        use std::sync::mpsc::*;

        let core        = Desync::new(0);

        // Schedule on the queue and block it
        let (tx, rx)    = channel();

        core.desync(move |_val| { rx.recv().ok(); });

        // Queue is busy, so try_sync should fail
        let sync_result = core.try_sync(|val| {
            *val = 42;
            1
        });

        // Queue is idle, so we should receive a result
        assert!(sync_result.is_err());

        // Unblock the queue
        tx.send(1).ok();

        // Double-check that the value was not updated
        assert!((core.sync(|val| *val)) == 0);
    }, 500);
}
<commit_msg>Add some tests for the new future implementation (failing on the '1000-times-through' test...)<commit_after>extern crate desync;
extern crate futures;

use desync::Desync;

mod scheduler;
use self::scheduler::timeout::*;

use futures::prelude::*;
use futures::future;

use std::sync::*;
use std::time::*;
use std::thread::*;

#[derive(Debug)]
struct TestData {
    val: u32
}

#[test]
fn retrieve_data_synchronously() {
    let desynced = Desync::new(TestData { val: 0 });

    assert!(desynced.sync(|data| data.val) == 0);
}

#[test]
fn retrieve_data_into_local_var() {
    let desynced = Desync::new(TestData { val: 42 });
    let mut val = 0;

    desynced.sync(|data| val = data.val);

    assert!(val == 42);
}

#[test]
fn update_data_asynchronously() {
    let desynced = Desync::new(TestData { val: 0 });

    desynced.desync(|data| {
        sleep(Duration::from_millis(100));
        data.val = 42;
    });

    assert!(desynced.sync(|data| data.val) == 42);
}

#[test]
fn update_data_asynchronously_1000_times() {
    for _i in 0..1000 {
        timeout(|| {
            let desynced = Desync::new(TestData { val: 0 });

            desynced.desync(|data| {
                data.val = 42;
            });
            desynced.desync(|data| {
                data.val = 43;
            });

            assert!(desynced.sync(|data| data.val) == 43);
        }, 500);
    }
}

#[test]
fn update_data_with_future() {
    timeout(|| {
        use futures::executor;

        let desynced = Desync::new(TestData { val: 0 });

        desynced.desync(|data| {
            sleep(Duration::from_millis(100));
            data.val = 42;
        });

        executor::block_on(async {
            let future = desynced.future(|data| { Box::pin(future::ready(data.val)) });
            assert!(future.await.unwrap() == 42);
        });
    }, 500);
}

#[test]
fn update_data_with_future_1000_times() {
    // Seems to timeout fairly reliably after signalling the future
    use futures::executor;

    for _i in 0..1000 {
        timeout(|| {
            let desynced = Desync::new(TestData { val: 0 });

            desynced.desync(|data| {
                data.val = 42;
            });
            desynced.desync(|data| {
                data.val = 43;
            });

            executor::block_on(async {
                let future = desynced.future(|data| Box::pin(future::ready(data.val)));

                assert!(future.await.unwrap() == 43);
            });
        }, 500);
    }
}

#[test]
fn update_data_with_future_sync() {
    timeout(|| {
        use futures::executor;

        let desynced = Desync::new(TestData { val: 0 });

        desynced.desync(|data| {
            sleep(Duration::from_millis(100));
            data.val = 42;
        });

        executor::block_on(async {
            let future = desynced.future_sync(|data| { Box::pin(future::ready(data.val)) });
            assert!(future.await.unwrap() == 42);
        });
    }, 500);
}

#[test]
fn update_data_with_future_sync_1000_times() {
    // Seems to timeout fairly reliably after signalling the future
    use futures::executor;

    for _i in 0..1000 {
        timeout(|| {
            let desynced = Desync::new(TestData { val: 0 });

            desynced.desync(|data| {
                data.val = 42;
            });
            desynced.desync(|data| {
                data.val = 43;
            });

            executor::block_on(async {
                let future = desynced.future_sync(|data| Box::pin(future::ready(data.val)));

                assert!(future.await.unwrap() == 43);
            });
        }, 5000);
    }
}

#[test]
fn dropping_while_running_isnt_obviously_bad() {
    let desynced = Desync::new(TestData { val: 0 });

    desynced.desync(|data| {
        sleep(Duration::from_millis(100));
        data.val = 42;
    });
    desynced.desync(|data| {
        sleep(Duration::from_millis(100));
        data.val = 42;
    });
}

#[test]
fn wait_for_future() {
    // TODO: occasional test failure that happens if the future 'arrives' before the queue is empty
    // (Because we need a future that arrives when the queue is actually suspended)
    timeout(|| {
        use futures::executor;
        use futures::channel::oneshot;

        // We use a oneshot as our future, and a mpsc channel to track progress
        let desynced                = Desync::new(0);
        let (future_tx, future_rx)  = oneshot::channel();

        // First value 0 -> 1
        desynced.desync(|val| {
            // Sleep here so the future should be waiting for us
            sleep(Duration::from_millis(100));
            assert!(*val == 0);
            *val = 1;
        });

        // Future should go 1 -> 2, but takes whatever future_tx sends
        let future = desynced.after(future_rx, |val, future_result| {
            assert!(*val == 1);
            *val = future_result.unwrap();

            // Return '4' to anything listening for this future
            4
        });

        // Finally, 3
        desynced.desync(move |val| { assert!(*val == 2); *val = 3 });

        executor::block_on(async {
            // Send '2' to the future
            future_tx.send(2).unwrap();

            // Future should resolve to 4
            assert!(future.await == Ok(4));

            // Final value should be 3
            assert!(desynced.sync(|val| *val) == 3);
        })
    }, 500);
}

#[test]
fn future_and_sync() {
    // This test seems to produce different behaviour if it's run by itself (this sleep tends to force it to run after the other tests and thus fail)
    // So far the failure seems reliable when this test is running exclusively
    sleep(Duration::from_millis(1000));

    use std::thread;
    use futures::prelude::*;
    use futures::channel::oneshot;

    // The idea here is we perform an action with a future() and read the result back with a sync() (which is a way you can mix-and-match
    // programming models with desync)
    //
    // The 'core' runs a request as a future, waiting for the channel result. We store the result in sync_request, and then retrieve
    // it again by calling sync - as Desync always runs things sequentially, it guarantees the ordering (something that's much harder
    // to achieve with a mutex)
    let (send, recv)    = oneshot::channel::<i32>();
    let core            = Desync::new(0);
    let sync_request    = Desync::new(None);

    // Send a request to the 'core' via the sync reqeust and store the result
    let _ = sync_request.future(move |data| {
        async move {
            let result = core.future(move |_core| {
                async move {
                    Some(recv.await.unwrap())
                }.boxed()
            }).await;

            *data = result.unwrap();
        }.boxed()
    });

    // Signal the future after a delay
    thread::spawn(move || {
        thread::sleep(Duration::from_millis(50));
        send.send(42).ok();
    });

    // Retrieve the result once the future completes
    let result = sync_request.sync(|req| req.take());

    // Should retrieve the value generated in the future
    assert!(result == Some(42));
}

#[test]
fn double_future_and_sync() {
    use std::thread;

    // TODO: signal with channels instead of using thread::sleep

    // This test will queue two futures here, each of which will need to return to another desync
    // If two futures are scheduled and triggered in a row when draining a queue that both signal
    let core        = Arc::new(Desync::new(()));

    let initiator_1 = Desync::new(None);
    let initiator_2 = Desync::new(None);
    let initiator_3 = Desync::new(None);

    let core_1      = Arc::clone(&core);
    let _           = initiator_1.future(move |val| {
        async move {
            // Wait for a task on the core
            *val = core_1.future(move |_| {
                async move { thread::sleep(Duration::from_millis(400)); Some(1) }.boxed()
            }).await.unwrap();
        }.boxed()
    });

    let core_2      = Arc::clone(&core);
    let _           = initiator_2.future(move |val| {
        async move {
            // Wait for the original initiator to start its future
            thread::sleep(Duration::from_millis(100));

            // Wait for a task on the core
            *val = core_2.future(move |_| {
                async move { thread::sleep(Duration::from_millis(200)); Some(2) }.boxed()
            }).await.unwrap();
        }.boxed()
    });

    let core_3      = Arc::clone(&core);
    let _           = initiator_3.future(move |val| {
        async move {
            // Wait for the original initiator to start its future
            thread::sleep(Duration::from_millis(200));

            // Wait for a task on the core
            *val = core_3.future(move |_| {
                async move { thread::sleep(Duration::from_millis(200)); Some(3) }.boxed()
            }).await.unwrap();
        }.boxed()
    });

    // Wait for the result from the futures synchronously
    assert!(initiator_3.sync(|val| { *val }) == Some(3));
    assert!(initiator_2.sync(|val| { *val }) == Some(2));
    assert!(initiator_1.sync(|val| { *val }) == Some(1));
}

#[test]
fn try_sync_succeeds_on_idle_queue() {
    timeout(|| {
        let core        = Desync::new(0);

        // Queue is doing nothing, so try_sync should succeed
        let sync_result = core.try_sync(|val| {
            *val = 42;
            1
        });

        // Queue is idle, so we should receive a result
        assert!(sync_result == Ok(1));

        // Double-check that the value was updated
        assert!(core.sync(|val| *val) == 42);
    }, 500);
}

#[test]
fn try_sync_succeeds_on_idle_queue_after_async_job() {
    timeout(|| {
        use std::thread;
        let core        = Desync::new(0);

        // Schedule something asynchronously and wait for it to complete
        core.desync(|_val| thread::sleep(Duration::from_millis(50)));
        core.sync(|_val| { });

        // Queue is doing nothing, so try_sync should succeed
        let sync_result = core.try_sync(|val| {
            *val= 42;
            1
        });

        // Queue is idle, so we should receive a result
        assert!(sync_result == Ok(1));

        // Double-check that the value was updated
        assert!(core.sync(|val| *val) == 42);
    }, 500);
}

#[test]
fn try_sync_fails_on_busy_queue() {
    timeout(|| {
        use std::sync::mpsc::*;

        let core        = Desync::new(0);

        // Schedule on the queue and block it
        let (tx, rx)    = channel();

        core.desync(move |_val| { rx.recv().ok(); });

        // Queue is busy, so try_sync should fail
        let sync_result = core.try_sync(|val| {
            *val = 42;
            1
        });

        // Queue is idle, so we should receive a result
        assert!(sync_result.is_err());

        // Unblock the queue
        tx.send(1).ok();

        // Double-check that the value was not updated
        assert!((core.sync(|val| *val)) == 0);
    }, 500);
}
<|endoftext|>


<commit_before>use crate::sys::time;

#[inline]
pub(super) fn monotonize(raw: time::Instant) -> time::Instant {
    inner::monotonize(raw)
}

#[cfg(all(target_has_atomic = "64", not(target_has_atomic = "128")))]
pub mod inner {
    use crate::sync::atomic::AtomicU64;
    use crate::sync::atomic::Ordering::*;
    use crate::sys::time;
    use crate::time::Duration;

    pub(in crate::time) const ZERO: time::Instant = time::Instant::zero();

    // bits 30 and 31 are never used since the seconds part never exceeds 10^9
    const UNINITIALIZED: u64 = 0b11 << 30;
    static MONO: AtomicU64 = AtomicU64::new(UNINITIALIZED);

    #[inline]
    pub(super) fn monotonize(raw: time::Instant) -> time::Instant {
        monotonize_impl(&MONO, raw)
    }

    #[inline]
    pub(in crate::time) fn monotonize_impl(mono: &AtomicU64, raw: time::Instant) -> time::Instant {
        let delta = raw.checked_sub_instant(&ZERO).unwrap();
        let secs = delta.as_secs();
        // occupies no more than 30 bits (10^9 seconds)
        let nanos = delta.subsec_nanos() as u64;

        // This wraps around every 136 years (2^32 seconds).
        // To detect backsliding we use wrapping arithmetic and declare forward steps smaller
        // than 2^31 seconds as expected and everything else as a backslide which will be
        // monotonized.
        // This could be a problem for programs that call instants at intervals greater
        // than 68 years. Interstellar probes may want to ensure that actually_monotonic() is true.
        let packed = (secs << 32) | nanos;
        let old = mono.load(Relaxed);

        if old == UNINITIALIZED || packed.wrapping_sub(old) < u64::MAX / 2 {
            mono.store(packed, Relaxed);
            raw
        } else {
            // Backslide occurred. We reconstruct monotonized time from the upper 32 bit of the
            // passed in value and the 64bits loaded from the atomic
            let seconds_lower = old >> 32;
            let mut seconds_upper = secs & 0xffff_ffff_0000_0000;
            if secs & 0xffff_ffff > seconds_lower {
                // Backslide caused the lower 32bit of the seconds part to wrap.
                // This must be the case because the seconds part is larger even though
                // we are in the backslide branch, i.e. the seconds count should be smaller or equal.
                //
                // We assume that backslides are smaller than 2^32 seconds
                // which means we need to add 1 to the upper half to restore it.
                //
                // Example:
                // most recent observed time: 0xA1_0000_0000_0000_0000u128
                // bits stored in AtomicU64:     0x0000_0000_0000_0000u64
                // backslide by 1s
                // caller time is             0xA0_ffff_ffff_0000_0000u128
                // -> we can fix up the upper half time by adding 1 << 32
                seconds_upper = seconds_upper.wrapping_add(0x1_0000_0000);
            }
            let secs = seconds_upper | seconds_lower;
            let nanos = old as u32;
            ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap()
        }
    }
}

#[cfg(target_has_atomic = "128")]
pub mod inner {
    use crate::sync::atomic::AtomicU128;
    use crate::sync::atomic::Ordering::*;
    use crate::sys::time;
    use crate::time::Duration;

    const ZERO: time::Instant = time::Instant::zero();
    static MONO: AtomicU128 = AtomicU128::new(0);

    #[inline]
    pub(super) fn monotonize(raw: time::Instant) -> time::Instant {
        let delta = raw.checked_sub_instant(&ZERO).unwrap();
        // Split into seconds and nanos since Duration doesn't have a
        // constructor that takes an u128
        let secs = delta.as_secs() as u128;
        let nanos = delta.subsec_nanos() as u128;
        let timestamp: u128 = secs << 64 | nanos;
        let timestamp = MONO.fetch_max(timestamp, Relaxed).max(timestamp);
        let secs = (timestamp >> 64) as u64;
        let nanos = timestamp as u32;
        ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap()
    }
}

#[cfg(not(any(target_has_atomic = "64", target_has_atomic = "128")))]
pub mod inner {
    use crate::cmp;
    use crate::sys::time;
    use crate::sys_common::mutex::StaticMutex;

    #[inline]
    pub(super) fn monotonize(os_now: time::Instant) -> time::Instant {
        static LOCK: StaticMutex = StaticMutex::new();
        static mut LAST_NOW: time::Instant = time::Instant::zero();
        unsafe {
            let _lock = LOCK.lock();
            let now = cmp::max(LAST_NOW, os_now);
            LAST_NOW = now;
            now
        }
    }
}
<commit_msg>[review] fix comment<commit_after>use crate::sys::time;

#[inline]
pub(super) fn monotonize(raw: time::Instant) -> time::Instant {
    inner::monotonize(raw)
}

#[cfg(all(target_has_atomic = "64", not(target_has_atomic = "128")))]
pub mod inner {
    use crate::sync::atomic::AtomicU64;
    use crate::sync::atomic::Ordering::*;
    use crate::sys::time;
    use crate::time::Duration;

    pub(in crate::time) const ZERO: time::Instant = time::Instant::zero();

    // bits 30 and 31 are never used since the nanoseconds part never exceeds 10^9
    const UNINITIALIZED: u64 = 0b11 << 30;
    static MONO: AtomicU64 = AtomicU64::new(UNINITIALIZED);

    #[inline]
    pub(super) fn monotonize(raw: time::Instant) -> time::Instant {
        monotonize_impl(&MONO, raw)
    }

    #[inline]
    pub(in crate::time) fn monotonize_impl(mono: &AtomicU64, raw: time::Instant) -> time::Instant {
        let delta = raw.checked_sub_instant(&ZERO).unwrap();
        let secs = delta.as_secs();
        // occupies no more than 30 bits (10^9 seconds)
        let nanos = delta.subsec_nanos() as u64;

        // This wraps around every 136 years (2^32 seconds).
        // To detect backsliding we use wrapping arithmetic and declare forward steps smaller
        // than 2^31 seconds as expected and everything else as a backslide which will be
        // monotonized.
        // This could be a problem for programs that call instants at intervals greater
        // than 68 years. Interstellar probes may want to ensure that actually_monotonic() is true.
        let packed = (secs << 32) | nanos;
        let old = mono.load(Relaxed);

        if old == UNINITIALIZED || packed.wrapping_sub(old) < u64::MAX / 2 {
            mono.store(packed, Relaxed);
            raw
        } else {
            // Backslide occurred. We reconstruct monotonized time from the upper 32 bit of the
            // passed in value and the 64bits loaded from the atomic
            let seconds_lower = old >> 32;
            let mut seconds_upper = secs & 0xffff_ffff_0000_0000;
            if secs & 0xffff_ffff > seconds_lower {
                // Backslide caused the lower 32bit of the seconds part to wrap.
                // This must be the case because the seconds part is larger even though
                // we are in the backslide branch, i.e. the seconds count should be smaller or equal.
                //
                // We assume that backslides are smaller than 2^32 seconds
                // which means we need to add 1 to the upper half to restore it.
                //
                // Example:
                // most recent observed time: 0xA1_0000_0000_0000_0000u128
                // bits stored in AtomicU64:     0x0000_0000_0000_0000u64
                // backslide by 1s
                // caller time is             0xA0_ffff_ffff_0000_0000u128
                // -> we can fix up the upper half time by adding 1 << 32
                seconds_upper = seconds_upper.wrapping_add(0x1_0000_0000);
            }
            let secs = seconds_upper | seconds_lower;
            let nanos = old as u32;
            ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap()
        }
    }
}

#[cfg(target_has_atomic = "128")]
pub mod inner {
    use crate::sync::atomic::AtomicU128;
    use crate::sync::atomic::Ordering::*;
    use crate::sys::time;
    use crate::time::Duration;

    const ZERO: time::Instant = time::Instant::zero();
    static MONO: AtomicU128 = AtomicU128::new(0);

    #[inline]
    pub(super) fn monotonize(raw: time::Instant) -> time::Instant {
        let delta = raw.checked_sub_instant(&ZERO).unwrap();
        // Split into seconds and nanos since Duration doesn't have a
        // constructor that takes an u128
        let secs = delta.as_secs() as u128;
        let nanos = delta.subsec_nanos() as u128;
        let timestamp: u128 = secs << 64 | nanos;
        let timestamp = MONO.fetch_max(timestamp, Relaxed).max(timestamp);
        let secs = (timestamp >> 64) as u64;
        let nanos = timestamp as u32;
        ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap()
    }
}

#[cfg(not(any(target_has_atomic = "64", target_has_atomic = "128")))]
pub mod inner {
    use crate::cmp;
    use crate::sys::time;
    use crate::sys_common::mutex::StaticMutex;

    #[inline]
    pub(super) fn monotonize(os_now: time::Instant) -> time::Instant {
        static LOCK: StaticMutex = StaticMutex::new();
        static mut LAST_NOW: time::Instant = time::Instant::zero();
        unsafe {
            let _lock = LOCK.lock();
            let now = cmp::max(LAST_NOW, os_now);
            LAST_NOW = now;
            now
        }
    }
}
<|endoftext|>


<commit_before>extern crate sdl2;
extern crate sdl2_ttf;

use std::env;
use std::path::Path;

use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::rect::Rect;
use sdl2::render::TextureQuery;
use sdl2::pixels::Color;

static SCREEN_WIDTH : u32 = 800;
static SCREEN_HEIGHT : u32 = 600;

// handle the annoying Rect i32
macro_rules! rect(
    ($x:expr, $y:expr, $w:expr, $h:expr) => (
        Rect::new($x as i32, $y as i32, $w as u32, $h as u32)
    )
);

// Scale fonts to a reasonable size when they're too big (though they might look less smooth)
fn get_centered_rect(rect_width: u32, rect_height: u32, cons_width: u32, cons_height: u32) -> Rect {
    let wr = rect_width as f32 / cons_width as f32;
    let hr = rect_height as f32 / cons_height as f32;

    let (w, h) = if wr > 1f32 || hr > 1f32 {
        if wr > hr {
            println!("Scaling down! The text will look worse!");
            let h = (rect_height as f32 / wr) as i32;
            (cons_width as i32, h)
        } else {
            println!("Scaling down! The text will look worse!");
            let w = (rect_width as f32 / hr) as i32;
            (w, cons_height as i32)
        }
    } else {
        (rect_width as i32, rect_height as i32)
    };

    let cx = (SCREEN_WIDTH as i32 - w) / 2;
    let cy = (SCREEN_HEIGHT as i32 - h) / 2;
    rect!(cx, cy, w, h)
}

fn run(font_path: &Path) {
    let sdl_context = sdl2::init().unwrap();
    let video_subsys = sdl_context.video().unwrap();
    let ttf_context = sdl2_ttf::init().unwrap();

    let window = video_subsys.window("SDL2_TTF Example", SCREEN_WIDTH, SCREEN_HEIGHT)
        .position_centered()
        .opengl()
        .build()
        .unwrap();

    let mut renderer = window.renderer().build().unwrap();

    // Load a font
    let mut font = ttf_context.load_font(font_path, 128).unwrap();
    font.set_style(sdl2_ttf::STYLE_BOLD);

    // render a surface, and convert it to a texture bound to the renderer
    let surface = font.render("Hello Rust!")
        .blended(Color::RGBA(255, 0, 0, 255)).unwrap();
    let mut texture = renderer.create_texture_from_surface(&surface).unwrap();

    renderer.set_draw_color(Color::RGBA(195, 217, 255, 255));
    renderer.clear();

    let TextureQuery { width, height, .. } = texture.query();

    // If the example text is too big for the screen, downscale it (and center irregardless)
    let padding = 64;
    let target = get_centered_rect(width, height, SCREEN_WIDTH - padding, SCREEN_HEIGHT - padding);

    renderer.copy(&mut texture, None, Some(target));
    renderer.present();

    'mainloop: loop {
        for event in sdl_context.event_pump().unwrap().poll_iter() {
            match event {
                Event::Quit{..} => break 'mainloop,
                Event::KeyDown {keycode: Some(Keycode::Escape), ..} => break 'mainloop,
                _ => {}
            }
        }
    }
}

fn main() {
    let args: Vec<_> = env::args().collect();

    println!("linked sdl2_ttf: {}", sdl2_ttf::get_linked_version());

    if args.len() < 2 {
        println!("Usage: ./demo font.[ttf|ttc|fon]")
    } else {
        let path: &Path = Path::new(&args[1]);
        run(path);
    }
}
<commit_msg>remove Warning in examples<commit_after>extern crate sdl2;
extern crate sdl2_ttf;

use std::env;
use std::path::Path;

use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::rect::Rect;
use sdl2::render::TextureQuery;
use sdl2::pixels::Color;

static SCREEN_WIDTH : u32 = 800;
static SCREEN_HEIGHT : u32 = 600;

// handle the annoying Rect i32
macro_rules! rect(
    ($x:expr, $y:expr, $w:expr, $h:expr) => (
        Rect::new($x as i32, $y as i32, $w as u32, $h as u32)
    )
);

// Scale fonts to a reasonable size when they're too big (though they might look less smooth)
fn get_centered_rect(rect_width: u32, rect_height: u32, cons_width: u32, cons_height: u32) -> Rect {
    let wr = rect_width as f32 / cons_width as f32;
    let hr = rect_height as f32 / cons_height as f32;

    let (w, h) = if wr > 1f32 || hr > 1f32 {
        if wr > hr {
            println!("Scaling down! The text will look worse!");
            let h = (rect_height as f32 / wr) as i32;
            (cons_width as i32, h)
        } else {
            println!("Scaling down! The text will look worse!");
            let w = (rect_width as f32 / hr) as i32;
            (w, cons_height as i32)
        }
    } else {
        (rect_width as i32, rect_height as i32)
    };

    let cx = (SCREEN_WIDTH as i32 - w) / 2;
    let cy = (SCREEN_HEIGHT as i32 - h) / 2;
    rect!(cx, cy, w, h)
}

fn run(font_path: &Path) {
    let sdl_context = sdl2::init().unwrap();
    let video_subsys = sdl_context.video().unwrap();
    let ttf_context = sdl2_ttf::init().unwrap();

    let window = video_subsys.window("SDL2_TTF Example", SCREEN_WIDTH, SCREEN_HEIGHT)
        .position_centered()
        .opengl()
        .build()
        .unwrap();

    let mut renderer = window.renderer().build().unwrap();

    // Load a font
    let mut font = ttf_context.load_font(font_path, 128).unwrap();
    font.set_style(sdl2_ttf::STYLE_BOLD);

    // render a surface, and convert it to a texture bound to the renderer
    let surface = font.render("Hello Rust!")
        .blended(Color::RGBA(255, 0, 0, 255)).unwrap();
    let mut texture = renderer.create_texture_from_surface(&surface).unwrap();

    renderer.set_draw_color(Color::RGBA(195, 217, 255, 255));
    renderer.clear();

    let TextureQuery { width, height, .. } = texture.query();

    // If the example text is too big for the screen, downscale it (and center irregardless)
    let padding = 64;
    let target = get_centered_rect(width, height, SCREEN_WIDTH - padding, SCREEN_HEIGHT - padding);

    renderer.copy(&mut texture, None, Some(target)).unwrap();
    renderer.present();

    'mainloop: loop {
        for event in sdl_context.event_pump().unwrap().poll_iter() {
            match event {
                Event::Quit{..} => break 'mainloop,
                Event::KeyDown {keycode: Some(Keycode::Escape), ..} => break 'mainloop,
                _ => {}
            }
        }
    }
}

fn main() {
    let args: Vec<_> = env::args().collect();

    println!("linked sdl2_ttf: {}", sdl2_ttf::get_linked_version());

    if args.len() < 2 {
        println!("Usage: ./demo font.[ttf|ttc|fon]")
    } else {
        let path: &Path = Path::new(&args[1]);
        run(path);
    }
}
<|endoftext|>


<commit_before>pub use self::{
    material_icons_font_ttf::*,
    material_icons_font::*,
    material_icons_round_font::*,
    material_icons_sharp_font::*,
    material_icons_twotone_font::*,
};

// ttf mappings
pub mod material_icons_font_ttf;

// woff2 mappings
pub mod material_icons_font;
pub mod material_icons_round_font;
pub mod material_icons_sharp_font;
pub mod material_icons_twotone_font;
<commit_msg>theme: vector_graphics: update woff2 usage material_icons_baseline_font<commit_after>pub use self::{
    material_icons_font_ttf::*,
    material_icons_baseline_font::*,
    material_icons_round_font::*,
    material_icons_sharp_font::*,
    material_icons_twotone_font::*,
};

// ttf mappings
pub mod material_icons_font_ttf;

// woff2 mappings
pub mod material_icons_baseline_font;
pub mod material_icons_round_font;
pub mod material_icons_sharp_font;
pub mod material_icons_twotone_font;
<|endoftext|>


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

// xfail-test
// aux-build:issue_3907_1.rs
extern mod issue_3907_1;

type Foo = issue_3907_1::Foo;

struct S {
    name: int
}

impl Foo for S {
    fn bar() { }
}

fn main() {
    let s = S {
        name: 0
    };
    s.bar();
}
<commit_msg>Remove run-pass/issue-3907-2.rs<commit_after><|endoftext|>