<commit_before>//!
//! [`Device`](Device) and [`Surface`](Surface)
//! implementations using egl contexts and surfaces for efficient rendering.
//!
//! Usually this implementation's [`EglSurface`](::backend::drm::egl::EglSurface)s implementation
//! of [`GLGraphicsBackend`](::backend::graphics::gl::GLGraphicsBackend) will be used
//! to let your compositor render.
//! Take a look at `anvil`s source code for an example of this.
//!

use drm::control::{connector, crtc, encoder, framebuffer, plane, ResourceHandles};
use drm::SystemError as DrmError;
use nix::libc::dev_t;
use std::os::unix::io::{AsRawFd, RawFd};
#[cfg(feature = "use_system_lib")]
use wayland_server::Display;

use super::{Device, DeviceHandler, Surface};
use crate::backend::egl::native::{Backend, NativeDisplay, NativeSurface};
use crate::backend::egl::Error as EGLError;
#[cfg(feature = "use_system_lib")]
use crate::backend::egl::{display::EGLBufferReader, EGLGraphicsBackend};

mod surface;
pub use self::surface::*;
use crate::backend::egl::context::GlAttributes;
use crate::backend::egl::display::EGLDisplay;

#[cfg(feature = "backend_session")]
pub mod session;

/// Errors for the DRM/EGL module
#[derive(thiserror::Error, Debug)]
pub enum Error<U: std::error::Error + std::fmt::Debug + std::fmt::Display + 'static> {
    /// EGL Error
    #[error("EGL error: {0:?}")]
    EGL(#[source] EGLError),
    /// Underlying backend error
    #[error("Underlying backend error: {0:?}")]
    Underlying(#[source] U),
}

/// Representation of an egl device to create egl rendering surfaces
pub struct EglDevice<B, D>
where
    B: Backend<Surface = <D as Device>::Surface> + 'static,
    D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
    <D as Device>::Surface: NativeSurface,
{
    dev: EGLDisplay<B, D>,
    logger: ::slog::Logger,
}

impl<B, D> AsRawFd for EglDevice<B, D>
where
    B: Backend<Surface = <D as Device>::Surface> + 'static,
    D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
    <D as Device>::Surface: NativeSurface,
{
    fn as_raw_fd(&self) -> RawFd {
        self.dev.borrow().as_raw_fd()
    }
}

impl<B, D> EglDevice<B, D>
where
    B: Backend<Surface = <D as Device>::Surface> + 'static,
    D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
    <D as Device>::Surface: NativeSurface,
{
    /// Try to create a new [`EglDevice`] from an open device.
    ///
    /// Returns an error if the file is no valid device or context
    /// creation was not successful.
    pub fn new<L>(mut dev: D, logger: L) -> Result<Self, Error<<<D as Device>::Surface as Surface>::Error>>
    where
        L: Into<Option<::slog::Logger>>,
    {
        let log = crate::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_egl"));

        dev.clear_handler();

        debug!(log, "Creating egl context from device");
        Ok(EglDevice {
            dev: EGLDisplay::new(dev, log.clone()).map_err(Error::EGL)?,
            logger: log,
        })
    }
}

struct InternalDeviceHandler<B, D>
where
    B: Backend<Surface = <D as Device>::Surface> + 'static,
    D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
    <D as Device>::Surface: NativeSurface,
{
    handler: Box<dyn DeviceHandler<Device = EglDevice<B, D>> + 'static>,
}

impl<B, D> DeviceHandler for InternalDeviceHandler<B, D>
where
    B: Backend<Surface = <D as Device>::Surface> + 'static,
    D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
    <D as Device>::Surface: NativeSurface,
{
    type Device = D;

    fn vblank(&mut self, crtc: crtc::Handle) {
        self.handler.vblank(crtc)
    }
    fn error(&mut self, error: <<D as Device>::Surface as Surface>::Error) {
        self.handler.error(Error::Underlying(error));
    }
}

impl<B, D> Device for EglDevice<B, D>
where
    B: Backend<Surface = <D as Device>::Surface> + 'static,
    D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
    <D as Device>::Surface: NativeSurface,
{
    type Surface = EglSurface<<D as Device>::Surface>;

    fn device_id(&self) -> dev_t {
        self.dev.borrow().device_id()
    }

    fn set_handler(&mut self, handler: impl DeviceHandler<Device = Self> + 'static) {
        self.dev.borrow_mut().set_handler(InternalDeviceHandler {
            handler: Box::new(handler),
        });
    }

    fn clear_handler(&mut self) {
        self.dev.borrow_mut().clear_handler()
    }

    fn create_surface(
        &mut self,
        crtc: crtc::Handle,
    ) -> Result<Self::Surface, <Self::Surface as Surface>::Error> {
        info!(self.logger, "Initializing EglSurface");

        // Device trait is unaware of opengl, so using sensible defaults
        let attributes = GlAttributes {
            version: None,
            profile: None,
            debug: cfg!(debug_assertions),
            vsync: true,
        };
        let reqs = Default::default();

        let context = self.dev.create_context(attributes, reqs).map_err(Error::EGL)?;
        let surface = self
            .dev
            .create_surface(
                context.get_pixel_format(),
                reqs.double_buffer,
                context.get_config_id(),
                crtc,
            )
            .map_err(Error::EGL)?;

        Ok(EglSurface { context, surface })
    }

    fn process_events(&mut self) {
        self.dev.borrow_mut().process_events()
    }

    fn resource_handles(&self) -> Result<ResourceHandles, <Self::Surface as Surface>::Error> {
        self.dev.borrow().resource_handles().map_err(Error::Underlying)
    }

    fn get_connector_info(&self, conn: connector::Handle) -> std::result::Result<connector::Info, DrmError> {
        self.dev.borrow().get_connector_info(conn)
    }
    fn get_crtc_info(&self, crtc: crtc::Handle) -> std::result::Result<crtc::Info, DrmError> {
        self.dev.borrow().get_crtc_info(crtc)
    }
    fn get_encoder_info(&self, enc: encoder::Handle) -> std::result::Result<encoder::Info, DrmError> {
        self.dev.borrow().get_encoder_info(enc)
    }
    fn get_framebuffer_info(
        &self,
        fb: framebuffer::Handle,
    ) -> std::result::Result<framebuffer::Info, DrmError> {
        self.dev.borrow().get_framebuffer_info(fb)
    }
    fn get_plane_info(&self, plane: plane::Handle) -> std::result::Result<plane::Info, DrmError> {
        self.dev.borrow().get_plane_info(plane)
    }
}

#[cfg(feature = "use_system_lib")]
impl<B, D> EGLGraphicsBackend for EglDevice<B, D>
where
    B: Backend<Surface = <D as Device>::Surface> + 'static,
    D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
    <D as Device>::Surface: NativeSurface,
{
    fn bind_wl_display(&self, display: &Display) -> Result<EGLBufferReader, EGLError> {
        self.dev.bind_wl_display(display)
    }
}

impl<B, D> Drop for EglDevice<B, D>
where
    B: Backend<Surface = <D as Device>::Surface> + 'static,
    D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
    <D as Device>::Surface: NativeSurface,
{
    fn drop(&mut self) {
        self.clear_handler();
    }
}
<commit_msg>Add default settings for surface creation<commit_after>//!
//! [`Device`](Device) and [`Surface`](Surface)
//! implementations using egl contexts and surfaces for efficient rendering.
//!
//! Usually this implementation's [`EglSurface`](::backend::drm::egl::EglSurface)s implementation
//! of [`GLGraphicsBackend`](::backend::graphics::gl::GLGraphicsBackend) will be used
//! to let your compositor render.
//! Take a look at `anvil`s source code for an example of this.
//!

use drm::control::{connector, crtc, encoder, framebuffer, plane, ResourceHandles};
use drm::SystemError as DrmError;
use nix::libc::dev_t;
use std::os::unix::io::{AsRawFd, RawFd};
#[cfg(feature = "use_system_lib")]
use wayland_server::Display;

use super::{Device, DeviceHandler, Surface};
use crate::backend::egl::native::{Backend, NativeDisplay, NativeSurface};
use crate::backend::egl::Error as EGLError;
#[cfg(feature = "use_system_lib")]
use crate::backend::egl::{display::EGLBufferReader, EGLGraphicsBackend};

mod surface;
pub use self::surface::*;
use crate::backend::egl::context::{GlAttributes, PixelFormatRequirements};
use crate::backend::egl::display::EGLDisplay;

#[cfg(feature = "backend_session")]
pub mod session;

/// Errors for the DRM/EGL module
#[derive(thiserror::Error, Debug)]
pub enum Error<U: std::error::Error + std::fmt::Debug + std::fmt::Display + 'static> {
    /// EGL Error
    #[error("EGL error: {0:?}")]
    EGL(#[source] EGLError),
    /// Underlying backend error
    #[error("Underlying backend error: {0:?}")]
    Underlying(#[source] U),
}

/// Representation of an egl device to create egl rendering surfaces
pub struct EglDevice<B, D>
where
    B: Backend<Surface = <D as Device>::Surface> + 'static,
    D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
    <D as Device>::Surface: NativeSurface,
{
    dev: EGLDisplay<B, D>,
    logger: ::slog::Logger,
    default_attributes: GlAttributes,
    default_requirements: PixelFormatRequirements,
}

impl<B, D> AsRawFd for EglDevice<B, D>
where
    B: Backend<Surface = <D as Device>::Surface> + 'static,
    D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
    <D as Device>::Surface: NativeSurface,
{
    fn as_raw_fd(&self) -> RawFd {
        self.dev.borrow().as_raw_fd()
    }
}

impl<B, D> EglDevice<B, D>
where
    B: Backend<Surface = <D as Device>::Surface> + 'static,
    D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
    <D as Device>::Surface: NativeSurface,
{
    /// Try to create a new [`EglDevice`] from an open device.
    ///
    /// Returns an error if the file is no valid device or context
    /// creation was not successful.
    pub fn new<L>(dev: D, logger: L) -> Result<Self, Error<<<D as Device>::Surface as Surface>::Error>>
    where
        L: Into<Option<::slog::Logger>>,
    {
        EglDevice::new_with_defaults(
            dev,
            GlAttributes {
                version: None,
                profile: None,
                debug: cfg!(debug_assertions),
                vsync: true,
            },
            Default::default(),
            logger,
        )
    }

    /// Try to create a new [`EglDevice`] from an open device with the given attributes and
    /// requirements as defaults for new surfaces.
    ///
    /// Returns an error if the file is no valid device or context
    /// creation was not successful.
    pub fn new_with_defaults<L>(
        mut dev: D,
        default_attributes: GlAttributes,
        default_requirements: PixelFormatRequirements,
        logger: L,
    ) -> Result<Self, Error<<<D as Device>::Surface as Surface>::Error>>
    where
        L: Into<Option<::slog::Logger>>,
    {
        let log = crate::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_egl"));

        dev.clear_handler();

        debug!(log, "Creating egl context from device");
        Ok(EglDevice {
            dev: EGLDisplay::new(dev, log.clone()).map_err(Error::EGL)?,
            default_attributes,
            default_requirements,
            logger: log,
        })
    }
}

struct InternalDeviceHandler<B, D>
where
    B: Backend<Surface = <D as Device>::Surface> + 'static,
    D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
    <D as Device>::Surface: NativeSurface,
{
    handler: Box<dyn DeviceHandler<Device = EglDevice<B, D>> + 'static>,
}

impl<B, D> DeviceHandler for InternalDeviceHandler<B, D>
where
    B: Backend<Surface = <D as Device>::Surface> + 'static,
    D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
    <D as Device>::Surface: NativeSurface,
{
    type Device = D;

    fn vblank(&mut self, crtc: crtc::Handle) {
        self.handler.vblank(crtc)
    }
    fn error(&mut self, error: <<D as Device>::Surface as Surface>::Error) {
        self.handler.error(Error::Underlying(error));
    }
}

impl<B, D> Device for EglDevice<B, D>
where
    B: Backend<Surface = <D as Device>::Surface> + 'static,
    D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
    <D as Device>::Surface: NativeSurface,
{
    type Surface = EglSurface<<D as Device>::Surface>;

    fn device_id(&self) -> dev_t {
        self.dev.borrow().device_id()
    }

    fn set_handler(&mut self, handler: impl DeviceHandler<Device = Self> + 'static) {
        self.dev.borrow_mut().set_handler(InternalDeviceHandler {
            handler: Box::new(handler),
        });
    }

    fn clear_handler(&mut self) {
        self.dev.borrow_mut().clear_handler()
    }

    fn create_surface(
        &mut self,
        crtc: crtc::Handle,
    ) -> Result<Self::Surface, <Self::Surface as Surface>::Error> {
        info!(self.logger, "Initializing EglSurface");

        let context = self
            .dev
            .create_context(self.default_attributes, self.default_requirements)
            .map_err(Error::EGL)?;
        let surface = self
            .dev
            .create_surface(
                context.get_pixel_format(),
                self.default_requirements.double_buffer,
                context.get_config_id(),
                crtc,
            )
            .map_err(Error::EGL)?;

        Ok(EglSurface { context, surface })
    }

    fn process_events(&mut self) {
        self.dev.borrow_mut().process_events()
    }

    fn resource_handles(&self) -> Result<ResourceHandles, <Self::Surface as Surface>::Error> {
        self.dev.borrow().resource_handles().map_err(Error::Underlying)
    }

    fn get_connector_info(&self, conn: connector::Handle) -> std::result::Result<connector::Info, DrmError> {
        self.dev.borrow().get_connector_info(conn)
    }
    fn get_crtc_info(&self, crtc: crtc::Handle) -> std::result::Result<crtc::Info, DrmError> {
        self.dev.borrow().get_crtc_info(crtc)
    }
    fn get_encoder_info(&self, enc: encoder::Handle) -> std::result::Result<encoder::Info, DrmError> {
        self.dev.borrow().get_encoder_info(enc)
    }
    fn get_framebuffer_info(
        &self,
        fb: framebuffer::Handle,
    ) -> std::result::Result<framebuffer::Info, DrmError> {
        self.dev.borrow().get_framebuffer_info(fb)
    }
    fn get_plane_info(&self, plane: plane::Handle) -> std::result::Result<plane::Info, DrmError> {
        self.dev.borrow().get_plane_info(plane)
    }
}

#[cfg(feature = "use_system_lib")]
impl<B, D> EGLGraphicsBackend for EglDevice<B, D>
where
    B: Backend<Surface = <D as Device>::Surface> + 'static,
    D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
    <D as Device>::Surface: NativeSurface,
{
    fn bind_wl_display(&self, display: &Display) -> Result<EGLBufferReader, EGLError> {
        self.dev.bind_wl_display(display)
    }
}

impl<B, D> Drop for EglDevice<B, D>
where
    B: Backend<Surface = <D as Device>::Surface> + 'static,
    D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
    <D as Device>::Surface: NativeSurface,
{
    fn drop(&mut self) {
        self.clear_handler();
    }
}
<|endoftext|>


<commit_before>//! [PUT /_matrix/client/r0/rooms/{roomId}/typing/{userId}](https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-rooms-roomid-typing-userid)

use serde::{de::Error, Deserialize, Deserializer, Serialize};
use std::time::Duration;

use ruma_api::ruma_api;
use ruma_identifiers::{RoomId, UserId};

ruma_api! {
    metadata: {
        method: PUT,
        path: "/_matrix/client/r0/rooms/:room_id/typing/:user_id",
        name: "create_typing_event",
        description: "Send a typing event to a room.",
        authentication: AccessToken,
        rate_limited: true,
    }

    request: {
        /// The user who has started to type.
        #[ruma_api(path)]
        pub user_id: &'a UserId,

        /// The room in which the user is typing.
        #[ruma_api(path)]
        pub room_id: &'a RoomId,

        /// Whether the user is typing within a length of time or not.
        #[serde(flatten)]
        pub state: Typing,
    }

    #[derive(Default)]
    response: {}

    error: crate::Error
}

impl<'a> Request<'a> {
    /// Creates a new `Request` with the given user ID, room ID and typing state.
    pub fn new(user_id: &'a UserId, room_id: &'a RoomId, state: Typing) -> Self {
        Self { user_id, room_id, state }
    }
}

impl Response {
    /// Creates an empty `Response`.
    pub fn new() -> Self {
        Self
    }
}

/// A mark for whether the user is typing within a length of time or not.
#[derive(Clone, Copy, Debug, Serialize)]
#[serde(into = "TypingInner")]
pub enum Typing {
    /// Not typing.
    No,

    /// Typing during the specified length of time.
    Yes(Duration),
}

#[derive(Deserialize, Serialize)]
struct TypingInner {
    typing: bool,
    #[serde(
        with = "ruma_serde::duration::opt_ms",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    timeout: Option<Duration>,
}

impl From<Typing> for TypingInner {
    fn from(typing: Typing) -> Self {
        match typing {
            Typing::No => Self { typing: false, timeout: None },
            Typing::Yes(time) => Self { typing: true, timeout: Some(time) },
        }
    }
}

impl<'de> Deserialize<'de> for Typing {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let inner = TypingInner::deserialize(deserializer)?;

        match (inner.typing, inner.timeout) {
            (false, _) => Ok(Self::No),
            (true, Some(time)) => Ok(Self::Yes(time)),
            _ => Err(D::Error::missing_field("timeout")),
        }
    }
}
<commit_msg>Add missing whitespace<commit_after>//! [PUT /_matrix/client/r0/rooms/{roomId}/typing/{userId}](https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-rooms-roomid-typing-userid)

use serde::{de::Error, Deserialize, Deserializer, Serialize};
use std::time::Duration;

use ruma_api::ruma_api;
use ruma_identifiers::{RoomId, UserId};

ruma_api! {
    metadata: {
        method: PUT,
        path: "/_matrix/client/r0/rooms/:room_id/typing/:user_id",
        name: "create_typing_event",
        description: "Send a typing event to a room.",
        authentication: AccessToken,
        rate_limited: true,
    }

    request: {
        /// The user who has started to type.
        #[ruma_api(path)]
        pub user_id: &'a UserId,

        /// The room in which the user is typing.
        #[ruma_api(path)]
        pub room_id: &'a RoomId,

        /// Whether the user is typing within a length of time or not.
        #[serde(flatten)]
        pub state: Typing,
    }

    #[derive(Default)]
    response: {}

    error: crate::Error
}

impl<'a> Request<'a> {
    /// Creates a new `Request` with the given user ID, room ID and typing state.
    pub fn new(user_id: &'a UserId, room_id: &'a RoomId, state: Typing) -> Self {
        Self { user_id, room_id, state }
    }
}

impl Response {
    /// Creates an empty `Response`.
    pub fn new() -> Self {
        Self
    }
}

/// A mark for whether the user is typing within a length of time or not.
#[derive(Clone, Copy, Debug, Serialize)]
#[serde(into = "TypingInner")]
pub enum Typing {
    /// Not typing.
    No,

    /// Typing during the specified length of time.
    Yes(Duration),
}

#[derive(Deserialize, Serialize)]
struct TypingInner {
    typing: bool,

    #[serde(
        with = "ruma_serde::duration::opt_ms",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    timeout: Option<Duration>,
}

impl From<Typing> for TypingInner {
    fn from(typing: Typing) -> Self {
        match typing {
            Typing::No => Self { typing: false, timeout: None },
            Typing::Yes(time) => Self { typing: true, timeout: Some(time) },
        }
    }
}

impl<'de> Deserialize<'de> for Typing {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let inner = TypingInner::deserialize(deserializer)?;

        match (inner.typing, inner.timeout) {
            (false, _) => Ok(Self::No),
            (true, Some(time)) => Ok(Self::Yes(time)),
            _ => Err(D::Error::missing_field("timeout")),
        }
    }
}
<|endoftext|>


<commit_before>//! Shim which is passed to Cargo as "rustc" when running the bootstrap.
//!
//! This shim will take care of some various tasks that our build process
//! requires that Cargo can't quite do through normal configuration:
//!
//! 1. When compiling build scripts and build dependencies, we need a guaranteed
//!    full standard library available. The only compiler which actually has
//!    this is the snapshot, so we detect this situation and always compile with
//!    the snapshot compiler.
//! 2. We pass a bunch of `--cfg` and other flags based on what we're compiling
//!    (and this slightly differs based on a whether we're using a snapshot or
//!    not), so we do that all here.
//!
//! This may one day be replaced by RUSTFLAGS, but the dynamic nature of
//! switching compilers for the bootstrap and for build scripts will probably
//! never get replaced.

use std::env;
use std::io;
use std::path::PathBuf;
use std::process::Command;
use std::str::FromStr;
use std::time::Instant;

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

    // Detect whether or not we're a build script depending on whether --target
    // is passed (a bit janky...)
    let target = args.windows(2).find(|w| &*w[0] == "--target").and_then(|w| w[1].to_str());
    let version = args.iter().find(|w| &**w == "-vV");

    let verbose = match env::var("RUSTC_VERBOSE") {
        Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"),
        Err(_) => 0,
    };

    // Use a different compiler for build scripts, since there may not yet be a
    // libstd for the real compiler to use. However, if Cargo is attempting to
    // determine the version of the compiler, the real compiler needs to be
    // used. Currently, these two states are differentiated based on whether
    // --target and -vV is/isn't passed.
    let (rustc, libdir) = if target.is_none() && version.is_none() {
        ("RUSTC_SNAPSHOT", "RUSTC_SNAPSHOT_LIBDIR")
    } else {
        ("RUSTC_REAL", "RUSTC_LIBDIR")
    };
    let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
    let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
    let on_fail = env::var_os("RUSTC_ON_FAIL").map(Command::new);

    let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
    let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
    let mut dylib_path = bootstrap::util::dylib_path();
    dylib_path.insert(0, PathBuf::from(&libdir));

    let mut cmd = Command::new(rustc);
    cmd.args(&args).env(bootstrap::util::dylib_path_var(), env::join_paths(&dylib_path).unwrap());

    // Get the name of the crate we're compiling, if any.
    let crate_name =
        args.windows(2).find(|args| args[0] == "--crate-name").and_then(|args| args[1].to_str());

    if let Some(crate_name) = crate_name {
        if let Some(target) = env::var_os("RUSTC_TIME") {
            if target == "all"
                || target.into_string().unwrap().split(',').any(|c| c.trim() == crate_name)
            {
                cmd.arg("-Ztime");
            }
        }
    }

    // Print backtrace in case of ICE
    if env::var("RUSTC_BACKTRACE_ON_ICE").is_ok() && env::var("RUST_BACKTRACE").is_err() {
        cmd.env("RUST_BACKTRACE", "1");
    }

    if let Ok(lint_flags) = env::var("RUSTC_LINT_FLAGS") {
        cmd.args(lint_flags.split_whitespace());
    }

    if target.is_some() {
        // The stage0 compiler has a special sysroot distinct from what we
        // actually downloaded, so we just always pass the `--sysroot` option,
        // unless one is already set.
        if !args.iter().any(|arg| arg == "--sysroot") {
            cmd.arg("--sysroot").arg(&sysroot);
        }

        // If we're compiling specifically the `panic_abort` crate then we pass
        // the `-C panic=abort` option. Note that we do not do this for any
        // other crate intentionally as this is the only crate for now that we
        // ship with panic=abort.
        //
        // This... is a bit of a hack how we detect this. Ideally this
        // information should be encoded in the crate I guess? Would likely
        // require an RFC amendment to RFC 1513, however.
        //
        // `compiler_builtins` are unconditionally compiled with panic=abort to
        // workaround undefined references to `rust_eh_unwind_resume` generated
        // otherwise, see issue https://github.com/rust-lang/rust/issues/43095.
        if crate_name == Some("panic_abort")
            || crate_name == Some("compiler_builtins") && stage != "0"
        {
            cmd.arg("-C").arg("panic=abort");
        }
    } else {
        // FIXME(rust-lang/cargo#5754) we shouldn't be using special env vars
        // here, but rather Cargo should know what flags to pass rustc itself.

        // Override linker if necessary.
        if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") {
            cmd.arg(format!("-Clinker={}", host_linker));
        }

        if let Ok(s) = env::var("RUSTC_HOST_CRT_STATIC") {
            if s == "true" {
                cmd.arg("-C").arg("target-feature=+crt-static");
            }
            if s == "false" {
                cmd.arg("-C").arg("target-feature=-crt-static");
            }
        }
    }

    if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") {
        cmd.arg("--remap-path-prefix").arg(&map);
    }

    // Force all crates compiled by this compiler to (a) be unstable and (b)
    // allow the `rustc_private` feature to link to other unstable crates
    // also in the sysroot. We also do this for host crates, since those
    // may be proc macros, in which case we might ship them.
    if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() && (stage != "0" || target.is_some()) {
        cmd.arg("-Z").arg("force-unstable-if-unmarked");
    }

    if verbose > 1 {
        eprintln!(
            "rustc command: {:?}={:?} {:?}",
            bootstrap::util::dylib_path_var(),
            env::join_paths(&dylib_path).unwrap(),
            cmd,
        );
        eprintln!("sysroot: {:?}", sysroot);
        eprintln!("libdir: {:?}", libdir);
    }

    if let Some(mut on_fail) = on_fail {
        let e = match cmd.status() {
            Ok(s) if s.success() => std::process::exit(0),
            e => e,
        };
        println!("\nDid not run successfully: {:?}\n{:?}\n-------------", e, cmd);
        status_code(&mut on_fail).expect("could not run the backup command");
        std::process::exit(1);
    }

    if env::var_os("RUSTC_PRINT_STEP_TIMINGS").is_some() {
        if let Some(crate_name) = crate_name {
            let start = Instant::now();
            let status = cmd.status().unwrap_or_else(|_| panic!("\n\n failed to run {:?}", cmd));
            let dur = start.elapsed();

            let is_test = args.iter().any(|a| a == "--test");
            eprintln!(
                "[RUSTC-TIMING] {} test:{} {}.{:03}",
                crate_name,
                is_test,
                dur.as_secs(),
                dur.subsec_millis()
            );

            match status.code() {
                Some(i) => std::process::exit(i),
                None => {
                    eprintln!("rustc exited with {}", status);
                    std::process::exit(0xfe);
                }
            }
        }
    }

    let code = status_code(&mut cmd).unwrap_or_else(|_| panic!("\n\n failed to run {:?}", cmd));
    std::process::exit(code);
}

fn status_code(cmd: &mut Command) -> io::Result<i32> {
    cmd.status().map(|status| status.code().unwrap())
}
<commit_msg>Auto merge of #74841 - infinity0:fix-exec, r=Mark-Simulacrum<commit_after>//! Shim which is passed to Cargo as "rustc" when running the bootstrap.
//!
//! This shim will take care of some various tasks that our build process
//! requires that Cargo can't quite do through normal configuration:
//!
//! 1. When compiling build scripts and build dependencies, we need a guaranteed
//!    full standard library available. The only compiler which actually has
//!    this is the snapshot, so we detect this situation and always compile with
//!    the snapshot compiler.
//! 2. We pass a bunch of `--cfg` and other flags based on what we're compiling
//!    (and this slightly differs based on a whether we're using a snapshot or
//!    not), so we do that all here.
//!
//! This may one day be replaced by RUSTFLAGS, but the dynamic nature of
//! switching compilers for the bootstrap and for build scripts will probably
//! never get replaced.

use std::env;
use std::path::PathBuf;
use std::process::Command;
use std::str::FromStr;
use std::time::Instant;

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

    // Detect whether or not we're a build script depending on whether --target
    // is passed (a bit janky...)
    let target = args.windows(2).find(|w| &*w[0] == "--target").and_then(|w| w[1].to_str());
    let version = args.iter().find(|w| &**w == "-vV");

    let verbose = match env::var("RUSTC_VERBOSE") {
        Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"),
        Err(_) => 0,
    };

    // Use a different compiler for build scripts, since there may not yet be a
    // libstd for the real compiler to use. However, if Cargo is attempting to
    // determine the version of the compiler, the real compiler needs to be
    // used. Currently, these two states are differentiated based on whether
    // --target and -vV is/isn't passed.
    let (rustc, libdir) = if target.is_none() && version.is_none() {
        ("RUSTC_SNAPSHOT", "RUSTC_SNAPSHOT_LIBDIR")
    } else {
        ("RUSTC_REAL", "RUSTC_LIBDIR")
    };
    let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
    let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
    let on_fail = env::var_os("RUSTC_ON_FAIL").map(Command::new);

    let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
    let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
    let mut dylib_path = bootstrap::util::dylib_path();
    dylib_path.insert(0, PathBuf::from(&libdir));

    let mut cmd = Command::new(rustc);
    cmd.args(&args).env(bootstrap::util::dylib_path_var(), env::join_paths(&dylib_path).unwrap());

    // Get the name of the crate we're compiling, if any.
    let crate_name =
        args.windows(2).find(|args| args[0] == "--crate-name").and_then(|args| args[1].to_str());

    if let Some(crate_name) = crate_name {
        if let Some(target) = env::var_os("RUSTC_TIME") {
            if target == "all"
                || target.into_string().unwrap().split(',').any(|c| c.trim() == crate_name)
            {
                cmd.arg("-Ztime");
            }
        }
    }

    // Print backtrace in case of ICE
    if env::var("RUSTC_BACKTRACE_ON_ICE").is_ok() && env::var("RUST_BACKTRACE").is_err() {
        cmd.env("RUST_BACKTRACE", "1");
    }

    if let Ok(lint_flags) = env::var("RUSTC_LINT_FLAGS") {
        cmd.args(lint_flags.split_whitespace());
    }

    if target.is_some() {
        // The stage0 compiler has a special sysroot distinct from what we
        // actually downloaded, so we just always pass the `--sysroot` option,
        // unless one is already set.
        if !args.iter().any(|arg| arg == "--sysroot") {
            cmd.arg("--sysroot").arg(&sysroot);
        }

        // If we're compiling specifically the `panic_abort` crate then we pass
        // the `-C panic=abort` option. Note that we do not do this for any
        // other crate intentionally as this is the only crate for now that we
        // ship with panic=abort.
        //
        // This... is a bit of a hack how we detect this. Ideally this
        // information should be encoded in the crate I guess? Would likely
        // require an RFC amendment to RFC 1513, however.
        //
        // `compiler_builtins` are unconditionally compiled with panic=abort to
        // workaround undefined references to `rust_eh_unwind_resume` generated
        // otherwise, see issue https://github.com/rust-lang/rust/issues/43095.
        if crate_name == Some("panic_abort")
            || crate_name == Some("compiler_builtins") && stage != "0"
        {
            cmd.arg("-C").arg("panic=abort");
        }
    } else {
        // FIXME(rust-lang/cargo#5754) we shouldn't be using special env vars
        // here, but rather Cargo should know what flags to pass rustc itself.

        // Override linker if necessary.
        if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") {
            cmd.arg(format!("-Clinker={}", host_linker));
        }

        if let Ok(s) = env::var("RUSTC_HOST_CRT_STATIC") {
            if s == "true" {
                cmd.arg("-C").arg("target-feature=+crt-static");
            }
            if s == "false" {
                cmd.arg("-C").arg("target-feature=-crt-static");
            }
        }
    }

    if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") {
        cmd.arg("--remap-path-prefix").arg(&map);
    }

    // Force all crates compiled by this compiler to (a) be unstable and (b)
    // allow the `rustc_private` feature to link to other unstable crates
    // also in the sysroot. We also do this for host crates, since those
    // may be proc macros, in which case we might ship them.
    if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() && (stage != "0" || target.is_some()) {
        cmd.arg("-Z").arg("force-unstable-if-unmarked");
    }

    if verbose > 1 {
        eprintln!(
            "rustc command: {:?}={:?} {:?}",
            bootstrap::util::dylib_path_var(),
            env::join_paths(&dylib_path).unwrap(),
            cmd,
        );
        eprintln!("sysroot: {:?}", sysroot);
        eprintln!("libdir: {:?}", libdir);
    }

    let start = Instant::now();
    let status = {
        let errmsg = format!("\nFailed to run:\n{:?}\n-------------", cmd);
        cmd.status().expect(&errmsg)
    };

    if env::var_os("RUSTC_PRINT_STEP_TIMINGS").is_some() {
        if let Some(crate_name) = crate_name {
            let dur = start.elapsed();
            let is_test = args.iter().any(|a| a == "--test");
            eprintln!(
                "[RUSTC-TIMING] {} test:{} {}.{:03}",
                crate_name,
                is_test,
                dur.as_secs(),
                dur.subsec_millis()
            );
        }
    }

    if status.success() {
        std::process::exit(0);
        // note: everything below here is unreachable. do not put code that
        // should run on success, after this block.
    }
    println!("\nDid not run successfully: {}\n{:?}\n-------------", status, cmd);

    if let Some(mut on_fail) = on_fail {
        on_fail.status().expect("Could not run the on_fail command");
    }

    // Preserve the exit code. In case of signal, exit with 0xfe since it's
    // awkward to preserve this status in a cross-platform way.
    match status.code() {
        Some(i) => std::process::exit(i),
        None => {
            eprintln!("rustc exited with {}", status);
            std::process::exit(0xfe);
        }
    }
}
<|endoftext|>


<commit_before>use std::os;
use std::io::{mod, fs, File};
use std::io::fs::PathExtensions;

use git2::Config;

use util::{GitRepo, HgRepo, CargoResult, human, ChainError, config, internal};
use core::shell::MultiShell;

pub struct NewOptions<'a> {
    pub no_git: bool,
    pub git: bool,
    pub hg: bool,
    pub travis: bool,
    pub bin: bool,
    pub path: &'a str,
}

struct CargoNewConfig {
    name: Option<String>,
    email: Option<String>,
    git: Option<bool>,
}

pub fn new(opts: NewOptions, _shell: &mut MultiShell) -> CargoResult<()> {
    let path = os::getcwd().join(opts.path);
    if path.exists() {
        return Err(human(format!("Destination `{}` already exists",
                                 path.display())))
    }
    let name = path.filename_str().unwrap();
    for c in name.chars() {
        if c.is_alphanumeric() { continue }
        if c == '_' || c == '-' { continue }
        return Err(human(format!("Invalid character `{}` in crate name: `{}`",
                                 c, name).as_slice()));
    }
    mk(&path, name, &opts).chain_error(|| {
        human(format!("Failed to create project `{}` at `{}`",
                      name, path.display()))
    })
}

fn existing_git_repo(path: &Path) -> bool {
    GitRepo::discover(path).is_ok()
}

fn mk(path: &Path, name: &str, opts: &NewOptions) -> CargoResult<()> {
    let cfg = try!(global_config());
    let mut ignore = "/target\n".to_string();
    let no_git = !opts.git && (opts.no_git || cfg.git == Some(false));
    let in_existing_git_repo = existing_git_repo(&path.dir_path());
    if !opts.bin {
        ignore.push_str("/Cargo.lock\n");
    }

    if opts.hg {
        try!(HgRepo::init(path));
        try!(File::create(&path.join(".hgignore")).write(ignore.as_bytes()));
    } else if no_git || in_existing_git_repo {
        try!(fs::mkdir(path, io::USER_RWX));
    } else {
        try!(GitRepo::init(path));
        try!(File::create(&path.join(".gitignore")).write(ignore.as_bytes()));
    }

    let (author_name, email) = try!(discover_author());
    // Hoo boy, sure glad we've got exhaustivenes checking behind us.
    let author = match (cfg.name, cfg.email, author_name, email) {
        (Some(name), Some(email), _, _) |
        (Some(name), None, _, Some(email)) |
        (None, Some(email), name, _) |
        (None, None, name, Some(email)) => format!("{} <{}>", name, email),
        (Some(name), None, _, None) |
        (None, None, name, None) => name,
    };

    if opts.travis {
        try!(File::create(&path.join(".travis.yml")).write_str("language: rust\n"));
    }

    try!(File::create(&path.join("Cargo.toml")).write_str(format!(
r#"[package]

name = "{}"
version = "0.0.1"
authors = ["{}"]
"#, name, author).as_slice()));

    try!(fs::mkdir(&path.join("src"), io::USER_RWX));

    if opts.bin {
        try!(File::create(&path.join("src/main.rs")).write_str("\
fn main() {
    println!(\"Hello, world!\")
}
"));
    } else {
        try!(File::create(&path.join("src/lib.rs")).write_str("\
#[test]
fn it_works() {
}
"));
    }

    Ok(())
}

fn discover_author() -> CargoResult<(String, Option<String>)> {
    let git_config = Config::open_default().ok();
    let git_config = git_config.as_ref();
    let name = git_config.and_then(|g| g.get_str("user.name").ok())
                         .map(|s| s.to_string())
                         .or_else(|| os::getenv("USER"))      // unix
                         .or_else(|| os::getenv("USERNAME")); // windows
    let name = match name {
        Some(name) => name,
        None => {
            let username_var = if cfg!(windows) {"USERNAME"} else {"USER"};
            return Err(human(format!("could not determine the current \
                                      user, please set ${}", username_var)))
        }
    };
    let email = git_config.and_then(|g| g.get_str("user.email").ok());

    let name = name.as_slice().trim().to_string();
    let email = email.map(|s| s.as_slice().trim().to_string());

    Ok((name, email))
}

fn global_config() -> CargoResult<CargoNewConfig> {
    let user_configs = try!(config::all_configs(os::getcwd()));
    let mut cfg = CargoNewConfig {
        name: None,
        email: None,
        git: None,
    };
    let cargo_new = match user_configs.find_equiv("cargo-new") {
        None => return Ok(cfg),
        Some(target) => try!(target.table().chain_error(|| {
            internal("invalid configuration for the key `cargo-new`")
        })),
    };
    cfg.name = match cargo_new.find_equiv("name") {
        None => None,
        Some(name) => {
            Some(try!(name.string().chain_error(|| {
                internal("invalid configuration for key `cargo-new.name`")
            })).ref0().to_string())
        }
    };
    cfg.email = match cargo_new.find_equiv("email") {
        None => None,
        Some(email) => {
            Some(try!(email.string().chain_error(|| {
                internal("invalid configuration for key `cargo-new.email`")
            })).ref0().to_string())
        }
    };
    cfg.git = match cargo_new.find_equiv("git") {
        None => None,
        Some(git) => {
            Some(try!(git.boolean().chain_error(|| {
                internal("invalid configuration for key `cargo-new.git`")
            })).val0())
        }
    };

    Ok(cfg)
}
<commit_msg>Add the semicolon missing from the generated main.rs contents.<commit_after>use std::os;
use std::io::{mod, fs, File};
use std::io::fs::PathExtensions;

use git2::Config;

use util::{GitRepo, HgRepo, CargoResult, human, ChainError, config, internal};
use core::shell::MultiShell;

pub struct NewOptions<'a> {
    pub no_git: bool,
    pub git: bool,
    pub hg: bool,
    pub travis: bool,
    pub bin: bool,
    pub path: &'a str,
}

struct CargoNewConfig {
    name: Option<String>,
    email: Option<String>,
    git: Option<bool>,
}

pub fn new(opts: NewOptions, _shell: &mut MultiShell) -> CargoResult<()> {
    let path = os::getcwd().join(opts.path);
    if path.exists() {
        return Err(human(format!("Destination `{}` already exists",
                                 path.display())))
    }
    let name = path.filename_str().unwrap();
    for c in name.chars() {
        if c.is_alphanumeric() { continue }
        if c == '_' || c == '-' { continue }
        return Err(human(format!("Invalid character `{}` in crate name: `{}`",
                                 c, name).as_slice()));
    }
    mk(&path, name, &opts).chain_error(|| {
        human(format!("Failed to create project `{}` at `{}`",
                      name, path.display()))
    })
}

fn existing_git_repo(path: &Path) -> bool {
    GitRepo::discover(path).is_ok()
}

fn mk(path: &Path, name: &str, opts: &NewOptions) -> CargoResult<()> {
    let cfg = try!(global_config());
    let mut ignore = "/target\n".to_string();
    let no_git = !opts.git && (opts.no_git || cfg.git == Some(false));
    let in_existing_git_repo = existing_git_repo(&path.dir_path());
    if !opts.bin {
        ignore.push_str("/Cargo.lock\n");
    }

    if opts.hg {
        try!(HgRepo::init(path));
        try!(File::create(&path.join(".hgignore")).write(ignore.as_bytes()));
    } else if no_git || in_existing_git_repo {
        try!(fs::mkdir(path, io::USER_RWX));
    } else {
        try!(GitRepo::init(path));
        try!(File::create(&path.join(".gitignore")).write(ignore.as_bytes()));
    }

    let (author_name, email) = try!(discover_author());
    // Hoo boy, sure glad we've got exhaustivenes checking behind us.
    let author = match (cfg.name, cfg.email, author_name, email) {
        (Some(name), Some(email), _, _) |
        (Some(name), None, _, Some(email)) |
        (None, Some(email), name, _) |
        (None, None, name, Some(email)) => format!("{} <{}>", name, email),
        (Some(name), None, _, None) |
        (None, None, name, None) => name,
    };

    if opts.travis {
        try!(File::create(&path.join(".travis.yml")).write_str("language: rust\n"));
    }

    try!(File::create(&path.join("Cargo.toml")).write_str(format!(
r#"[package]

name = "{}"
version = "0.0.1"
authors = ["{}"]
"#, name, author).as_slice()));

    try!(fs::mkdir(&path.join("src"), io::USER_RWX));

    if opts.bin {
        try!(File::create(&path.join("src/main.rs")).write_str("\
fn main() {
    println!(\"Hello, world!\");
}
"));
    } else {
        try!(File::create(&path.join("src/lib.rs")).write_str("\
#[test]
fn it_works() {
}
"));
    }

    Ok(())
}

fn discover_author() -> CargoResult<(String, Option<String>)> {
    let git_config = Config::open_default().ok();
    let git_config = git_config.as_ref();
    let name = git_config.and_then(|g| g.get_str("user.name").ok())
                         .map(|s| s.to_string())
                         .or_else(|| os::getenv("USER"))      // unix
                         .or_else(|| os::getenv("USERNAME")); // windows
    let name = match name {
        Some(name) => name,
        None => {
            let username_var = if cfg!(windows) {"USERNAME"} else {"USER"};
            return Err(human(format!("could not determine the current \
                                      user, please set ${}", username_var)))
        }
    };
    let email = git_config.and_then(|g| g.get_str("user.email").ok());

    let name = name.as_slice().trim().to_string();
    let email = email.map(|s| s.as_slice().trim().to_string());

    Ok((name, email))
}

fn global_config() -> CargoResult<CargoNewConfig> {
    let user_configs = try!(config::all_configs(os::getcwd()));
    let mut cfg = CargoNewConfig {
        name: None,
        email: None,
        git: None,
    };
    let cargo_new = match user_configs.find_equiv("cargo-new") {
        None => return Ok(cfg),
        Some(target) => try!(target.table().chain_error(|| {
            internal("invalid configuration for the key `cargo-new`")
        })),
    };
    cfg.name = match cargo_new.find_equiv("name") {
        None => None,
        Some(name) => {
            Some(try!(name.string().chain_error(|| {
                internal("invalid configuration for key `cargo-new.name`")
            })).ref0().to_string())
        }
    };
    cfg.email = match cargo_new.find_equiv("email") {
        None => None,
        Some(email) => {
            Some(try!(email.string().chain_error(|| {
                internal("invalid configuration for key `cargo-new.email`")
            })).ref0().to_string())
        }
    };
    cfg.git = match cargo_new.find_equiv("git") {
        None => None,
        Some(git) => {
            Some(try!(git.boolean().chain_error(|| {
                internal("invalid configuration for key `cargo-new.git`")
            })).val0())
        }
    };

    Ok(cfg)
}
<|endoftext|>


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

pub use windowing;

use constellation::SendableFrameTree;
use windowing::{ApplicationMethods, WindowMethods};
use platform::Application;

use azure::azure_hl::{SourceSurfaceMethods, Color};
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use layers::platform::surface::{NativeCompositingGraphicsContext, NativeGraphicsMetadata};
use servo_msg::compositor_msg::{Epoch, LayerBufferSet, LayerId, LayerMetadata, ReadyState};
use servo_msg::compositor_msg::{RenderListener, RenderState, ScriptListener, ScrollPolicy};
use servo_msg::constellation_msg::{ConstellationChan, PipelineId};
use servo_util::opts::Opts;
use servo_util::time::ProfilerChan;
use std::comm::{channel, Sender, Receiver};

use url::Url;

#[cfg(target_os="linux")]
use azure::azure_hl;

mod quadtree;
mod compositor_layer;

mod compositor;
mod headless;

/// The implementation of the layers-based compositor.
#[deriving(Clone)]
pub struct CompositorChan {
    /// A channel on which messages can be sent to the compositor.
    pub chan: Sender<Msg>,
}

/// Implementation of the abstract `ScriptListener` interface.
impl ScriptListener for CompositorChan {
    fn set_ready_state(&self, ready_state: ReadyState) {
        let msg = ChangeReadyState(ready_state);
        self.chan.send(msg);
    }

    fn scroll_fragment_point(&self,
                             pipeline_id: PipelineId,
                             layer_id: LayerId,
                             point: Point2D<f32>) {
	    self.chan.send(ScrollFragmentPoint(pipeline_id, layer_id, point));
    }

    fn close(&self) {
        let (chan, port) = channel();
        self.chan.send(Exit(chan));
        port.recv();
    }

    fn dup(&self) -> ~ScriptListener {
        ~self.clone() as ~ScriptListener
    }
}

/// Implementation of the abstract `RenderListener` interface.
impl RenderListener for CompositorChan {
    fn get_graphics_metadata(&self) -> Option<NativeGraphicsMetadata> {
        let (chan, port) = channel();
        self.chan.send(GetGraphicsMetadata(chan));
        port.recv()
    }

    fn paint(&self,
             pipeline_id: PipelineId,
             layer_id: LayerId,
             layer_buffer_set: ~LayerBufferSet,
             epoch: Epoch) {
        self.chan.send(Paint(pipeline_id, layer_id, layer_buffer_set, epoch))
    }

    fn initialize_layers_for_pipeline(&self,
                                      pipeline_id: PipelineId,
                                      metadata: Vec<LayerMetadata>,
                                      epoch: Epoch) {
        // FIXME(#2004, pcwalton): This assumes that the first layer determines the page size, and
        // that all other layers are immediate children of it. This is sufficient to handle
        // `position: fixed` but will not be sufficient to handle `overflow: scroll` or transforms.
        let mut first = true;
        for metadata in metadata.iter() {
            let origin = Point2D(metadata.position.origin.x as f32,
                                 metadata.position.origin.y as f32);
            let size = Size2D(metadata.position.size.width as f32,
                              metadata.position.size.height as f32);
            let rect = Rect(origin, size);
            if first {
                self.chan.send(CreateRootCompositorLayerIfNecessary(pipeline_id,
                                                                    metadata.id,
                                                                    size));
                first = false
            } else {
                self.chan
                    .send(CreateDescendantCompositorLayerIfNecessary(pipeline_id,
                                                                     metadata.id,
                                                                     rect,
                                                                     metadata.scroll_policy));
            }

            self.chan.send(SetUnRenderedColor(pipeline_id,
                                              metadata.id,
                                              metadata.background_color));
            self.chan.send(SetLayerPageSize(pipeline_id, metadata.id, size, epoch));
        }
    }

    fn set_layer_clip_rect(&self,
                           pipeline_id: PipelineId,
                           layer_id: LayerId,
                           new_rect: Rect<uint>) {
        let new_rect = Rect(Point2D(new_rect.origin.x as f32,
                                    new_rect.origin.y as f32),
                            Size2D(new_rect.size.width as f32,
                                   new_rect.size.height as f32));
        self.chan.send(SetLayerClipRect(pipeline_id, layer_id, new_rect))
    }

    fn delete_layer_group(&self, id: PipelineId) {
        self.chan.send(DeleteLayerGroup(id))
    }

    fn set_render_state(&self, render_state: RenderState) {
        self.chan.send(ChangeRenderState(render_state))
    }
}

impl CompositorChan {
    pub fn new() -> (Receiver<Msg>, CompositorChan) {
        let (chan, port) = channel();
        let compositor_chan = CompositorChan {
            chan: chan,
        };
        (port, compositor_chan)
    }

    pub fn send(&self, msg: Msg) {
        self.chan.send(msg);
    }
}
/// Messages from the painting task and the constellation task to the compositor task.
pub enum Msg {
    /// Requests that the compositor shut down.
    Exit(Sender<()>),

    /// Informs the compositor that the constellation has completed shutdown.
    /// Required because the constellation can have pending calls to make (e.g. SetIds)
    /// at the time that we send it an ExitMsg.
    ShutdownComplete,

    /// Requests the compositor's graphics metadata. Graphics metadata is what the renderer needs
    /// to create surfaces that the compositor can see. On Linux this is the X display; on Mac this
    /// is the pixel format.
    ///
    /// The headless compositor returns `None`.
    GetGraphicsMetadata(Sender<Option<NativeGraphicsMetadata>>),

    /// Tells the compositor to create the root layer for a pipeline if necessary (i.e. if no layer
    /// with that ID exists).
    CreateRootCompositorLayerIfNecessary(PipelineId, LayerId, Size2D<f32>),
    /// Tells the compositor to create a descendant layer for a pipeline if necessary (i.e. if no
    /// layer with that ID exists).
    CreateDescendantCompositorLayerIfNecessary(PipelineId, LayerId, Rect<f32>, ScrollPolicy),
    /// Alerts the compositor that the specified layer has changed size.
    SetLayerPageSize(PipelineId, LayerId, Size2D<f32>, Epoch),
    /// Alerts the compositor that the specified layer's clipping rect has changed.
    SetLayerClipRect(PipelineId, LayerId, Rect<f32>),
    /// Alerts the compositor that the specified pipeline has been deleted.
    DeleteLayerGroup(PipelineId),
    /// Scroll a page in a window
    ScrollFragmentPoint(PipelineId, LayerId, Point2D<f32>),
    /// Requests that the compositor paint the given layer buffer set for the given page size.
    Paint(PipelineId, LayerId, ~LayerBufferSet, Epoch),
    /// Alerts the compositor to the current status of page loading.
    ChangeReadyState(ReadyState),
    /// Alerts the compositor to the current status of rendering.
    ChangeRenderState(RenderState),
    /// Sets the channel to the current layout and render tasks, along with their id
    SetIds(SendableFrameTree, Sender<()>, ConstellationChan),
    /// Sets the color of unrendered content for a layer.
    SetUnRenderedColor(PipelineId, LayerId, Color),
    /// The load of a page for a given URL has completed.
    LoadComplete(PipelineId, Url),
}

pub enum CompositorMode {
    Windowed(Application),
    Headless
}

pub struct CompositorTask {
    pub mode: CompositorMode,
}

impl CompositorTask {
    fn new(is_headless: bool) -> CompositorTask {
        let mode: CompositorMode = if is_headless {
            Headless
        } else {
            Windowed(ApplicationMethods::new())
        };

        CompositorTask {
            mode: mode
        }
    }

    /// Creates a graphics context. Platform-specific.
    ///
    /// FIXME(pcwalton): Probably could be less platform-specific, using the metadata abstraction.
    #[cfg(target_os="linux")]
    fn create_graphics_context() -> NativeCompositingGraphicsContext {
        NativeCompositingGraphicsContext::from_display(azure_hl::current_display())
    }
    #[cfg(not(target_os="linux"))]
    fn create_graphics_context() -> NativeCompositingGraphicsContext {
        NativeCompositingGraphicsContext::new()
    }

    pub fn create(opts: Opts,
                  port: Receiver<Msg>,
                  constellation_chan: ConstellationChan,
                  profiler_chan: ProfilerChan) {

        let compositor = CompositorTask::new(opts.headless);

        match compositor.mode {
            Windowed(ref app) => {
                compositor::IOCompositor::create(app,
                                                 opts,
                                                 port,
                                                 constellation_chan.clone(),
                                                 profiler_chan)
            }
            Headless => {
                headless::NullCompositor::create(port,
                                                 constellation_chan.clone(),
                                                 profiler_chan)
            }
        };
    }
}
<commit_msg>Update compositor clip rect when page size changes. Fixes #2161.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

pub use windowing;

use constellation::SendableFrameTree;
use windowing::{ApplicationMethods, WindowMethods};
use platform::Application;

use azure::azure_hl::{SourceSurfaceMethods, Color};
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use layers::platform::surface::{NativeCompositingGraphicsContext, NativeGraphicsMetadata};
use servo_msg::compositor_msg::{Epoch, LayerBufferSet, LayerId, LayerMetadata, ReadyState};
use servo_msg::compositor_msg::{RenderListener, RenderState, ScriptListener, ScrollPolicy};
use servo_msg::constellation_msg::{ConstellationChan, PipelineId};
use servo_util::opts::Opts;
use servo_util::time::ProfilerChan;
use std::comm::{channel, Sender, Receiver};

use url::Url;

#[cfg(target_os="linux")]
use azure::azure_hl;

mod quadtree;
mod compositor_layer;

mod compositor;
mod headless;

/// The implementation of the layers-based compositor.
#[deriving(Clone)]
pub struct CompositorChan {
    /// A channel on which messages can be sent to the compositor.
    pub chan: Sender<Msg>,
}

/// Implementation of the abstract `ScriptListener` interface.
impl ScriptListener for CompositorChan {
    fn set_ready_state(&self, ready_state: ReadyState) {
        let msg = ChangeReadyState(ready_state);
        self.chan.send(msg);
    }

    fn scroll_fragment_point(&self,
                             pipeline_id: PipelineId,
                             layer_id: LayerId,
                             point: Point2D<f32>) {
	    self.chan.send(ScrollFragmentPoint(pipeline_id, layer_id, point));
    }

    fn close(&self) {
        let (chan, port) = channel();
        self.chan.send(Exit(chan));
        port.recv();
    }

    fn dup(&self) -> ~ScriptListener {
        ~self.clone() as ~ScriptListener
    }
}

/// Implementation of the abstract `RenderListener` interface.
impl RenderListener for CompositorChan {
    fn get_graphics_metadata(&self) -> Option<NativeGraphicsMetadata> {
        let (chan, port) = channel();
        self.chan.send(GetGraphicsMetadata(chan));
        port.recv()
    }

    fn paint(&self,
             pipeline_id: PipelineId,
             layer_id: LayerId,
             layer_buffer_set: ~LayerBufferSet,
             epoch: Epoch) {
        self.chan.send(Paint(pipeline_id, layer_id, layer_buffer_set, epoch))
    }

    fn initialize_layers_for_pipeline(&self,
                                      pipeline_id: PipelineId,
                                      metadata: Vec<LayerMetadata>,
                                      epoch: Epoch) {
        // FIXME(#2004, pcwalton): This assumes that the first layer determines the page size, and
        // that all other layers are immediate children of it. This is sufficient to handle
        // `position: fixed` but will not be sufficient to handle `overflow: scroll` or transforms.
        let mut first = true;
        for metadata in metadata.iter() {
            let origin = Point2D(metadata.position.origin.x as f32,
                                 metadata.position.origin.y as f32);
            let size = Size2D(metadata.position.size.width as f32,
                              metadata.position.size.height as f32);
            let rect = Rect(origin, size);
            if first {
                self.chan.send(CreateRootCompositorLayerIfNecessary(pipeline_id,
                                                                    metadata.id,
                                                                    size));
                first = false
            } else {
                self.chan
                    .send(CreateDescendantCompositorLayerIfNecessary(pipeline_id,
                                                                     metadata.id,
                                                                     rect,
                                                                     metadata.scroll_policy));
            }

            self.chan.send(SetUnRenderedColor(pipeline_id,
                                              metadata.id,
                                              metadata.background_color));
            self.chan.send(SetLayerPageSize(pipeline_id, metadata.id, size, epoch));
            self.chan.send(SetLayerClipRect(pipeline_id, metadata.id, rect));
        }
    }

    fn set_layer_clip_rect(&self,
                           pipeline_id: PipelineId,
                           layer_id: LayerId,
                           new_rect: Rect<uint>) {
        let new_rect = Rect(Point2D(new_rect.origin.x as f32,
                                    new_rect.origin.y as f32),
                            Size2D(new_rect.size.width as f32,
                                   new_rect.size.height as f32));
        self.chan.send(SetLayerClipRect(pipeline_id, layer_id, new_rect))
    }

    fn delete_layer_group(&self, id: PipelineId) {
        self.chan.send(DeleteLayerGroup(id))
    }

    fn set_render_state(&self, render_state: RenderState) {
        self.chan.send(ChangeRenderState(render_state))
    }
}

impl CompositorChan {
    pub fn new() -> (Receiver<Msg>, CompositorChan) {
        let (chan, port) = channel();
        let compositor_chan = CompositorChan {
            chan: chan,
        };
        (port, compositor_chan)
    }

    pub fn send(&self, msg: Msg) {
        self.chan.send(msg);
    }
}
/// Messages from the painting task and the constellation task to the compositor task.
pub enum Msg {
    /// Requests that the compositor shut down.
    Exit(Sender<()>),

    /// Informs the compositor that the constellation has completed shutdown.
    /// Required because the constellation can have pending calls to make (e.g. SetIds)
    /// at the time that we send it an ExitMsg.
    ShutdownComplete,

    /// Requests the compositor's graphics metadata. Graphics metadata is what the renderer needs
    /// to create surfaces that the compositor can see. On Linux this is the X display; on Mac this
    /// is the pixel format.
    ///
    /// The headless compositor returns `None`.
    GetGraphicsMetadata(Sender<Option<NativeGraphicsMetadata>>),

    /// Tells the compositor to create the root layer for a pipeline if necessary (i.e. if no layer
    /// with that ID exists).
    CreateRootCompositorLayerIfNecessary(PipelineId, LayerId, Size2D<f32>),
    /// Tells the compositor to create a descendant layer for a pipeline if necessary (i.e. if no
    /// layer with that ID exists).
    CreateDescendantCompositorLayerIfNecessary(PipelineId, LayerId, Rect<f32>, ScrollPolicy),
    /// Alerts the compositor that the specified layer has changed size.
    SetLayerPageSize(PipelineId, LayerId, Size2D<f32>, Epoch),
    /// Alerts the compositor that the specified layer's clipping rect has changed.
    SetLayerClipRect(PipelineId, LayerId, Rect<f32>),
    /// Alerts the compositor that the specified pipeline has been deleted.
    DeleteLayerGroup(PipelineId),
    /// Scroll a page in a window
    ScrollFragmentPoint(PipelineId, LayerId, Point2D<f32>),
    /// Requests that the compositor paint the given layer buffer set for the given page size.
    Paint(PipelineId, LayerId, ~LayerBufferSet, Epoch),
    /// Alerts the compositor to the current status of page loading.
    ChangeReadyState(ReadyState),
    /// Alerts the compositor to the current status of rendering.
    ChangeRenderState(RenderState),
    /// Sets the channel to the current layout and render tasks, along with their id
    SetIds(SendableFrameTree, Sender<()>, ConstellationChan),
    /// Sets the color of unrendered content for a layer.
    SetUnRenderedColor(PipelineId, LayerId, Color),
    /// The load of a page for a given URL has completed.
    LoadComplete(PipelineId, Url),
}

pub enum CompositorMode {
    Windowed(Application),
    Headless
}

pub struct CompositorTask {
    pub mode: CompositorMode,
}

impl CompositorTask {
    fn new(is_headless: bool) -> CompositorTask {
        let mode: CompositorMode = if is_headless {
            Headless
        } else {
            Windowed(ApplicationMethods::new())
        };

        CompositorTask {
            mode: mode
        }
    }

    /// Creates a graphics context. Platform-specific.
    ///
    /// FIXME(pcwalton): Probably could be less platform-specific, using the metadata abstraction.
    #[cfg(target_os="linux")]
    fn create_graphics_context() -> NativeCompositingGraphicsContext {
        NativeCompositingGraphicsContext::from_display(azure_hl::current_display())
    }
    #[cfg(not(target_os="linux"))]
    fn create_graphics_context() -> NativeCompositingGraphicsContext {
        NativeCompositingGraphicsContext::new()
    }

    pub fn create(opts: Opts,
                  port: Receiver<Msg>,
                  constellation_chan: ConstellationChan,
                  profiler_chan: ProfilerChan) {

        let compositor = CompositorTask::new(opts.headless);

        match compositor.mode {
            Windowed(ref app) => {
                compositor::IOCompositor::create(app,
                                                 opts,
                                                 port,
                                                 constellation_chan.clone(),
                                                 profiler_chan)
            }
            Headless => {
                headless::NullCompositor::create(port,
                                                 constellation_chan.clone(),
                                                 profiler_chan)
            }
        };
    }
}
<|endoftext|>


<commit_before>/*
 * This is a copy of the sync_wrapper crate.
 */
//! A mutual exclusion primitive that relies on static type information only
//!
//! This library is inspired by [this discussion](https://internals.rust-lang.org/t/what-shall-sync-mean-across-an-await/12020/2).
#![doc(html_logo_url = "https://developer.actyx.com/img/logo.svg")]
#![doc(html_favicon_url = "https://developer.actyx.com/img/favicon.ico")]

/// A mutual exclusion primitive that relies on static type information only
///
/// In some cases synchronization can be proven statically: whenever you hold an exclusive `&mut`
/// reference, the Rust type system ensures that no other part of the program can hold another
/// reference to the data. Therefore it is safe to access it even if the current thread obtained
/// this reference via a channel. Whenever this is the case, the overhead of allocating and locking
/// a [`Mutex`] can be avoided by using this static version.
///
/// One example where this is often applicable is [`Future`], which requires an exclusive reference
/// for its [`poll`] method: While a given `Future` implementation may not be safe to access by
/// multiple threads concurrently, the executor can only run the `Future` on one thread at any
/// given time, making it [`Sync`] in practice as long as the implementation is `Send`. You can
/// therefore use the sync wrapper to prove that your data structure is `Sync` even though it
/// contains such a `Future`.
///
/// # Example
///
/// ```ignore
/// use hyper::common::sync_wrapper::SyncWrapper;
/// use std::future::Future;
///
/// struct MyThing {
///     future: SyncWrapper<Box<dyn Future<Output = String> + Send>>,
/// }
///
/// impl MyThing {
///     // all accesses to `self.future` now require an exclusive reference or ownership
/// }
///
/// fn assert_sync<T: Sync>() {}
///
/// assert_sync::<MyThing>();
/// ```
///
/// [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html
/// [`Future`]: https://doc.rust-lang.org/std/future/trait.Future.html
/// [`poll`]: https://doc.rust-lang.org/std/future/trait.Future.html#method.poll
/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
#[repr(transparent)]
pub(crate) struct SyncWrapper<T>(T);

impl<T> SyncWrapper<T> {
    /// Creates a new SyncWrapper containing the given value.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use hyper::common::sync_wrapper::SyncWrapper;
    ///
    /// let wrapped = SyncWrapper::new(42);
    /// ```
    pub(crate) fn new(value: T) -> Self {
        Self(value)
    }

    /// Acquires a reference to the protected value.
    ///
    /// This is safe because it requires an exclusive reference to the wrapper. Therefore this method
    /// neither panics nor does it return an error. This is in contrast to [`Mutex::get_mut`] which
    /// returns an error if another thread panicked while holding the lock. It is not recommended
    /// to send an exclusive reference to a potentially damaged value to another thread for further
    /// processing.
    ///
    /// [`Mutex::get_mut`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#method.get_mut
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use hyper::common::sync_wrapper::SyncWrapper;
    ///
    /// let mut wrapped = SyncWrapper::new(42);
    /// let value = wrapped.get_mut();
    /// *value = 0;
    /// assert_eq!(*wrapped.get_mut(), 0);
    /// ```
    pub(crate) fn get_mut(&mut self) -> &mut T {
        &mut self.0
    }

    /// Consumes this wrapper, returning the underlying data.
    ///
    /// This is safe because it requires ownership of the wrapper, aherefore this method will neither
    /// panic nor does it return an error. This is in contrast to [`Mutex::into_inner`] which
    /// returns an error if another thread panicked while holding the lock. It is not recommended
    /// to send an exclusive reference to a potentially damaged value to another thread for further
    /// processing.
    ///
    /// [`Mutex::into_inner`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#method.into_inner
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use hyper::common::sync_wrapper::SyncWrapper;
    ///
    /// let mut wrapped = SyncWrapper::new(42);
    /// assert_eq!(wrapped.into_inner(), 42);
    /// ```
    #[allow(dead_code)]
    pub(crate) fn into_inner(self) -> T {
        self.0
    }
}

// this is safe because the only operations permitted on this data structure require exclusive
// access or ownership
unsafe impl<T: Send> Sync for SyncWrapper<T> {}
<commit_msg>docs(common): remove favicon doc from sync_wrapper module (#2548)<commit_after>/*
 * This is a copy of the sync_wrapper crate.
 */

/// A mutual exclusion primitive that relies on static type information only
///
/// In some cases synchronization can be proven statically: whenever you hold an exclusive `&mut`
/// reference, the Rust type system ensures that no other part of the program can hold another
/// reference to the data. Therefore it is safe to access it even if the current thread obtained
/// this reference via a channel. Whenever this is the case, the overhead of allocating and locking
/// a [`Mutex`] can be avoided by using this static version.
///
/// One example where this is often applicable is [`Future`], which requires an exclusive reference
/// for its [`poll`] method: While a given `Future` implementation may not be safe to access by
/// multiple threads concurrently, the executor can only run the `Future` on one thread at any
/// given time, making it [`Sync`] in practice as long as the implementation is `Send`. You can
/// therefore use the sync wrapper to prove that your data structure is `Sync` even though it
/// contains such a `Future`.
///
/// # Example
///
/// ```ignore
/// use hyper::common::sync_wrapper::SyncWrapper;
/// use std::future::Future;
///
/// struct MyThing {
///     future: SyncWrapper<Box<dyn Future<Output = String> + Send>>,
/// }
///
/// impl MyThing {
///     // all accesses to `self.future` now require an exclusive reference or ownership
/// }
///
/// fn assert_sync<T: Sync>() {}
///
/// assert_sync::<MyThing>();
/// ```
///
/// [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html
/// [`Future`]: https://doc.rust-lang.org/std/future/trait.Future.html
/// [`poll`]: https://doc.rust-lang.org/std/future/trait.Future.html#method.poll
/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
#[repr(transparent)]
pub(crate) struct SyncWrapper<T>(T);

impl<T> SyncWrapper<T> {
    /// Creates a new SyncWrapper containing the given value.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use hyper::common::sync_wrapper::SyncWrapper;
    ///
    /// let wrapped = SyncWrapper::new(42);
    /// ```
    pub(crate) fn new(value: T) -> Self {
        Self(value)
    }

    /// Acquires a reference to the protected value.
    ///
    /// This is safe because it requires an exclusive reference to the wrapper. Therefore this method
    /// neither panics nor does it return an error. This is in contrast to [`Mutex::get_mut`] which
    /// returns an error if another thread panicked while holding the lock. It is not recommended
    /// to send an exclusive reference to a potentially damaged value to another thread for further
    /// processing.
    ///
    /// [`Mutex::get_mut`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#method.get_mut
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use hyper::common::sync_wrapper::SyncWrapper;
    ///
    /// let mut wrapped = SyncWrapper::new(42);
    /// let value = wrapped.get_mut();
    /// *value = 0;
    /// assert_eq!(*wrapped.get_mut(), 0);
    /// ```
    pub(crate) fn get_mut(&mut self) -> &mut T {
        &mut self.0
    }

    /// Consumes this wrapper, returning the underlying data.
    ///
    /// This is safe because it requires ownership of the wrapper, aherefore this method will neither
    /// panic nor does it return an error. This is in contrast to [`Mutex::into_inner`] which
    /// returns an error if another thread panicked while holding the lock. It is not recommended
    /// to send an exclusive reference to a potentially damaged value to another thread for further
    /// processing.
    ///
    /// [`Mutex::into_inner`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#method.into_inner
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use hyper::common::sync_wrapper::SyncWrapper;
    ///
    /// let mut wrapped = SyncWrapper::new(42);
    /// assert_eq!(wrapped.into_inner(), 42);
    /// ```
    #[allow(dead_code)]
    pub(crate) fn into_inner(self) -> T {
        self.0
    }
}

// this is safe because the only operations permitted on this data structure require exclusive
// access or ownership
unsafe impl<T: Send> Sync for SyncWrapper<T> {}
<|endoftext|>


<commit_before>use std::sync::atomic::AtomicBool;

use parking_lot::{RwLockReadGuard, RwLockWriteGuard};

use super::*;

#[derive(Default)]
pub(crate) struct ConcurrencyControl {
    necessary: AtomicBool,
    upgrade_complete: AtomicBool,
    rw: RwLock<()>,
}

pub(crate) enum Protector<'a> {
    Write(RwLockWriteGuard<'a, ()>),
    Read(RwLockReadGuard<'a, ()>),
    None,
}

impl ConcurrencyControl {
    fn enable(&self) {
        if !self.necessary.load(Acquire) && !self.necessary.swap(true, SeqCst) {
            // upgrade the system to using transactional
            // concurrency control, which is a little
            // more expensive for every operation.
            let (tx, rx) = std::sync::mpsc::channel();

            let guard = pin();
            guard.defer(move || tx.send(()).unwrap());
            guard.flush();
            drop(guard);

            rx.recv().unwrap();
            self.upgrade_complete.store(true, Release);
        }
    }

    pub(crate) fn read<'a>(&'a self, _: &'a Guard) -> Protector<'a> {
        if self.necessary.load(Acquire) {
            Protector::Read(self.rw.read())
        } else {
            Protector::None
        }
    }

    pub(crate) fn write(&self) -> Protector<'_> {
        self.enable();
        while !self.upgrade_complete.load(Acquire) {
            std::sync::atomic::spin_loop_hint()
        }
        Protector::Write(self.rw.write())
    }
}
<commit_msg>Don't rely on EBR dropping for upgrading the transaction CC<commit_after>use std::sync::atomic::AtomicBool;

use parking_lot::{RwLockReadGuard, RwLockWriteGuard};

use super::*;

#[derive(Default)]
pub(crate) struct ConcurrencyControl {
    necessary: AtomicBool,
    active_non_lockers: AtomicUsize,
    upgrade_complete: AtomicBool,
    rw: RwLock<()>,
}

pub(crate) enum Protector<'a> {
    Write(RwLockWriteGuard<'a, ()>),
    Read(RwLockReadGuard<'a, ()>),
    None(&'a AtomicUsize),
}

impl<'a> Drop for Protector<'a> {
    fn drop(&mut self) {
        match self {
            Protector::None(active_non_lockers) => {
                active_non_lockers.fetch_sub(1, Release);
            }
            _ => {}
        }
    }
}

impl ConcurrencyControl {
    fn enable(&self) {
        if !self.necessary.load(Acquire) && !self.necessary.swap(true, SeqCst) {
            while self.active_non_lockers.load(Acquire) != 0 {
                std::sync::atomic::spin_loop_hint()
            }
            self.upgrade_complete.store(true, Release);
        }
    }

    pub(crate) fn read<'a>(&'a self, _: &'a Guard) -> Protector<'a> {
        if self.necessary.load(Acquire) {
            Protector::Read(self.rw.read())
        } else {
            self.active_non_lockers.fetch_add(1, Release);
            Protector::None(&self.active_non_lockers)
        }
    }

    pub(crate) fn write(&self) -> Protector<'_> {
        self.enable();
        while !self.upgrade_complete.load(Acquire) {
            std::sync::atomic::spin_loop_hint()
        }
        Protector::Write(self.rw.write())
    }
}
<|endoftext|>


<commit_before>// Lumol, an extensible molecular simulation engine
// Copyright (C) Lumol's contributors — BSD license

//! Primitives for energy computation.
//!
//! This module provides simple function to compute separated components of the
//! potential energy of an `System`.
use sys::System;
use std::f64::consts::PI;

/// An helper struct to evaluate energy components of a system.
pub struct EnergyEvaluator<'a> {
    system: &'a System,
}

impl<'a> EnergyEvaluator<'a> {
    /// Create a new `EnergyEvaluator` acting on the given `system`.
    pub fn new(system: &'a System) -> EnergyEvaluator<'a> {
        EnergyEvaluator {
            system: system,
        }
    }
}

impl<'a> EnergyEvaluator<'a> {
    /// Compute the energy associated with the pair of particles `i, j` at
    /// distance `r`
    #[inline]
    pub fn pair(&self, r: f64, i: usize, j: usize) -> f64 {
        let distance = self.system.bond_distance(i, j);
        let mut energy = 0.0;
        for potential in self.system.pair_potentials(i, j) {
            let info = potential.restriction().information(distance);
            if !info.excluded {
                energy += info.scaling * potential.energy(r);
            }
        }
        return energy;
    }

    /// Compute the energy of all the pairs in the system
    pub fn pairs(&self) -> f64 {
        let mut energy = 0.0;
        for i in 0..self.system.size() {
            for j in (i+1)..self.system.size() {
                let r = self.system.nearest_image(i, j).norm();
                energy += self.pair(r, i, j);
            }
        }
        return energy;
    }

    /// Compute the energy due to long range corrections for the pairs
    #[inline]
    pub fn pairs_tail(&self) -> f64 {
        if self.system.cell().is_infinite() {
            return 0.0;
        }
        let mut energy = 0.0;
        let volume = self.system.volume();
        let composition = self.system.composition();
        for i in self.system.particle_kinds() {
            let ni = composition[i] as f64;
            for j in self.system.particle_kinds() {
                let nj = composition[j] as f64;
                let potentials = self.system.interactions().pairs(i, j);
                for potential in potentials {
                    energy += 2.0 * PI * ni * nj * potential.tail_energy() / volume;
                }
            }
        }
        return energy;
    }

    /// Compute the energy associated with the bonded particles `i, j` at
    /// distance `r`
    #[inline]
    pub fn bond(&self, r: f64, i: usize, j: usize) -> f64 {
        let mut energy = 0.0;
        for potential in self.system.bond_potentials(i, j) {
            energy += potential.energy(r);
        }
        return energy;
    }

    /// Compute the energy of all the bonds in the system
    pub fn bonds(&self) -> f64 {
        let mut energy = 0.0;
        for molecule in self.system.molecules() {
            for bond in molecule.bonds() {
                let (i, j) = (bond.i(), bond.j());
                let r = self.system.nearest_image(i, j).norm();
                energy += self.bond(r, i, j);
            }
        }
        return energy;
    }

    /// Compute the energy associated with the angle `i, j, k` at angle `theta`
    #[inline]
    pub fn angle(&self, theta: f64, i: usize, j: usize, k: usize) -> f64 {
        let mut energy = 0.0;
        for potential in self.system.angle_potentials(i, j, k) {
            energy += potential.energy(theta);
        }
        return energy;
    }

    /// Compute the energy of all the angles in the system
    pub fn angles(&self) -> f64 {
        let mut energy = 0.0;
        for molecule in self.system.molecules() {
            for angle in molecule.angles() {
                let (i, j, k) = (angle.i(), angle.j(), angle.k());
                let theta = self.system.angle(i, j, k);
                energy += self.angle(theta, i, j, k);
            }
        }
        return energy;
    }

    /// Compute the energy associated with the dihedral angle `i, j, k, m` at
    /// angle `phi`
    #[inline]
    pub fn dihedral(&self, phi: f64, i: usize, j: usize, k: usize, m: usize) -> f64 {
        let mut energy = 0.0;
        for potential in self.system.dihedral_potentials(i, j, k, m) {
            energy += potential.energy(phi);
        }
        return energy;
    }

    /// Compute the energy of all the dihedral angles in the system
    pub fn dihedrals(&self) -> f64 {
        let mut energy = 0.0;
        for molecule in self.system.molecules() {
            for dihedral in molecule.dihedrals() {
                let (i, j, k, m) = (dihedral.i(), dihedral.j(), dihedral.k(), dihedral.m());
                let phi = self.system.dihedral(i, j, k, m);
                energy += self.dihedral(phi, i, j, k, m);
            }
        }
        return energy;
    }

    /// Compute the energy of the electrostatic interactions
    #[inline]
    pub fn coulomb(&self) -> f64 {
        if let Some(coulomb) = self.system.interactions().coulomb() {
            coulomb.energy(self.system)
        } else {
            0.0
        }
    }

    /// Compute the energy of the global potentials
    #[inline]
    pub fn global(&self) -> f64 {
        let mut energy = 0.0;
        for global in self.system.interactions().globals() {
            energy += global.energy(self.system);
        }
        return energy;
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use sys::{System, Particle, UnitCell};
    use energy::{Harmonic, LennardJones, NullPotential, PairInteraction};
    use types::Vector3D;
    use utils::unit_from;

    fn testing_system() -> System {
        let mut system = System::from_cell(UnitCell::cubic(10.0));;
        system.add_particle(Particle::new("F"));
        system[0].position = Vector3D::new(0.0, 0.0, 0.0);
        system.add_particle(Particle::new("F"));
        system[1].position = Vector3D::new(1.0, 0.0, 0.0);
        system.add_particle(Particle::new("F"));
        system[2].position = Vector3D::new(1.0, 1.0, 0.0);
        system.add_particle(Particle::new("F"));
        system[3].position = Vector3D::new(2.0, 1.0, 0.0);

        assert!(system.add_bond(0, 1).is_empty());
        assert!(system.add_bond(1, 2).is_empty());
        assert!(system.add_bond(2, 3).is_empty());

        let mut pair = PairInteraction::new(Box::new(LennardJones {
            epsilon: unit_from(100.0, "kJ/mol/A^2"),
            sigma: unit_from(0.8, "A")
        }), 5.0);
        pair.enable_tail_corrections();

        system.interactions_mut().add_pair("F", "F", pair);

        system.interactions_mut().add_bond("F", "F",
            Box::new(Harmonic{
                k: unit_from(100.0, "kJ/mol/A^2"),
                x0: unit_from(2.0, "A")
        }));

        system.interactions_mut().add_angle("F", "F", "F",
            Box::new(Harmonic{
                k: unit_from(100.0, "kJ/mol/deg^2"),
                x0: unit_from(88.0, "deg")
        }));

        system.interactions_mut().add_dihedral("F", "F", "F", "F",
            Box::new(Harmonic{
                k: unit_from(100.0, "kJ/mol/deg^2"),
                x0: unit_from(185.0, "deg")
        }));

        /// unused interaction to check that we do handle this right
        system.interactions_mut().add_pair("H", "O",
            PairInteraction::new(Box::new(NullPotential), 0.0)
        );

        return system;
    }

    #[test]
    fn pairs() {
        let system = testing_system();
        let evaluator = EnergyEvaluator::new(&system);
        assert_ulps_eq!(evaluator.pairs(), unit_from(-258.3019360389957, "kJ/mol"));
        assert_ulps_eq!(evaluator.pairs_tail(), -0.0000028110338032153973);
    }

    #[test]
    fn pairs_tail_infinite_cell() {
        let mut system = testing_system();
        system.set_cell(UnitCell::new());

        let evaluator = EnergyEvaluator::new(&system);
        assert_eq!(evaluator.pairs_tail(), 0.0);
    }

    #[test]
    fn bonds() {
        let system = testing_system();
        let evaluator = EnergyEvaluator::new(&system);
        assert_ulps_eq!(evaluator.bonds(), unit_from(150.0, "kJ/mol"));
    }

    #[test]
    fn angles() {
        let system = testing_system();
        let evaluator = EnergyEvaluator::new(&system);
        assert_ulps_eq!(evaluator.angles(), unit_from(400.0, "kJ/mol"));
    }

    #[test]
    fn dihedrals() {
        let system = testing_system();
        let evaluator = EnergyEvaluator::new(&system);
        assert_ulps_eq!(evaluator.dihedrals(), unit_from(1250.0, "kJ/mol"), max_ulps=15);
    }
}
<commit_msg>Parallelize EnergyEvaluator::pairs<commit_after>// Lumol, an extensible molecular simulation engine
// Copyright (C) Lumol's contributors — BSD license

//! Primitives for energy computation.
//!
//! This module provides simple function to compute separated components of the
//! potential energy of an `System`.
use sys::System;
use std::f64::consts::PI;

use rayon::prelude::*;

/// An helper struct to evaluate energy components of a system.
pub struct EnergyEvaluator<'a> {
    system: &'a System,
}

impl<'a> EnergyEvaluator<'a> {
    /// Create a new `EnergyEvaluator` acting on the given `system`.
    pub fn new(system: &'a System) -> EnergyEvaluator<'a> {
        EnergyEvaluator {
            system: system,
        }
    }
}

impl<'a> EnergyEvaluator<'a> {
    /// Compute the energy associated with the pair of particles `i, j` at
    /// distance `r`
    #[inline]
    pub fn pair(&self, r: f64, i: usize, j: usize) -> f64 {
        let distance = self.system.bond_distance(i, j);
        let mut energy = 0.0;
        for potential in self.system.pair_potentials(i, j) {
            let info = potential.restriction().information(distance);
            if !info.excluded {
                energy += info.scaling * potential.energy(r);
            }
        }
        return energy;
    }

    /// Compute the energy of all the pairs in the system
    pub fn pairs(&self) -> f64 {

        (0..self.system.size()).into_par_iter().map(|i| {
            let mut energy = 0.0;

            for j in (i+1)..self.system.size() {
                let r = self.system.nearest_image(i, j).norm();
                energy += self.pair(r, i, j);
            }
            energy
        }).sum()
    }

    /// Compute the energy due to long range corrections for the pairs
    #[inline]
    pub fn pairs_tail(&self) -> f64 {
        if self.system.cell().is_infinite() {
            return 0.0;
        }
        let mut energy = 0.0;
        let volume = self.system.volume();
        let composition = self.system.composition();
        for i in self.system.particle_kinds() {
            let ni = composition[i] as f64;
            for j in self.system.particle_kinds() {
                let nj = composition[j] as f64;
                let potentials = self.system.interactions().pairs(i, j);
                for potential in potentials {
                    energy += 2.0 * PI * ni * nj * potential.tail_energy() / volume;
                }
            }
        }
        return energy;
    }

    /// Compute the energy associated with the bonded particles `i, j` at
    /// distance `r`
    #[inline]
    pub fn bond(&self, r: f64, i: usize, j: usize) -> f64 {
        let mut energy = 0.0;
        for potential in self.system.bond_potentials(i, j) {
            energy += potential.energy(r);
        }
        return energy;
    }

    /// Compute the energy of all the bonds in the system
    pub fn bonds(&self) -> f64 {
        let mut energy = 0.0;
        for molecule in self.system.molecules() {
            for bond in molecule.bonds() {
                let (i, j) = (bond.i(), bond.j());
                let r = self.system.nearest_image(i, j).norm();
                energy += self.bond(r, i, j);
            }
        }
        return energy;
    }

    /// Compute the energy associated with the angle `i, j, k` at angle `theta`
    #[inline]
    pub fn angle(&self, theta: f64, i: usize, j: usize, k: usize) -> f64 {
        let mut energy = 0.0;
        for potential in self.system.angle_potentials(i, j, k) {
            energy += potential.energy(theta);
        }
        return energy;
    }

    /// Compute the energy of all the angles in the system
    pub fn angles(&self) -> f64 {
        let mut energy = 0.0;
        for molecule in self.system.molecules() {
            for angle in molecule.angles() {
                let (i, j, k) = (angle.i(), angle.j(), angle.k());
                let theta = self.system.angle(i, j, k);
                energy += self.angle(theta, i, j, k);
            }
        }
        return energy;
    }

    /// Compute the energy associated with the dihedral angle `i, j, k, m` at
    /// angle `phi`
    #[inline]
    pub fn dihedral(&self, phi: f64, i: usize, j: usize, k: usize, m: usize) -> f64 {
        let mut energy = 0.0;
        for potential in self.system.dihedral_potentials(i, j, k, m) {
            energy += potential.energy(phi);
        }
        return energy;
    }

    /// Compute the energy of all the dihedral angles in the system
    pub fn dihedrals(&self) -> f64 {
        let mut energy = 0.0;
        for molecule in self.system.molecules() {
            for dihedral in molecule.dihedrals() {
                let (i, j, k, m) = (dihedral.i(), dihedral.j(), dihedral.k(), dihedral.m());
                let phi = self.system.dihedral(i, j, k, m);
                energy += self.dihedral(phi, i, j, k, m);
            }
        }
        return energy;
    }

    /// Compute the energy of the electrostatic interactions
    #[inline]
    pub fn coulomb(&self) -> f64 {
        if let Some(coulomb) = self.system.interactions().coulomb() {
            coulomb.energy(self.system)
        } else {
            0.0
        }
    }

    /// Compute the energy of the global potentials
    #[inline]
    pub fn global(&self) -> f64 {
        let mut energy = 0.0;
        for global in self.system.interactions().globals() {
            energy += global.energy(self.system);
        }
        return energy;
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use sys::{System, Particle, UnitCell};
    use energy::{Harmonic, LennardJones, NullPotential, PairInteraction};
    use types::Vector3D;
    use utils::unit_from;

    fn testing_system() -> System {
        let mut system = System::from_cell(UnitCell::cubic(10.0));;
        system.add_particle(Particle::new("F"));
        system[0].position = Vector3D::new(0.0, 0.0, 0.0);
        system.add_particle(Particle::new("F"));
        system[1].position = Vector3D::new(1.0, 0.0, 0.0);
        system.add_particle(Particle::new("F"));
        system[2].position = Vector3D::new(1.0, 1.0, 0.0);
        system.add_particle(Particle::new("F"));
        system[3].position = Vector3D::new(2.0, 1.0, 0.0);

        assert!(system.add_bond(0, 1).is_empty());
        assert!(system.add_bond(1, 2).is_empty());
        assert!(system.add_bond(2, 3).is_empty());

        let mut pair = PairInteraction::new(Box::new(LennardJones {
            epsilon: unit_from(100.0, "kJ/mol/A^2"),
            sigma: unit_from(0.8, "A")
        }), 5.0);
        pair.enable_tail_corrections();

        system.interactions_mut().add_pair("F", "F", pair);

        system.interactions_mut().add_bond("F", "F",
            Box::new(Harmonic{
                k: unit_from(100.0, "kJ/mol/A^2"),
                x0: unit_from(2.0, "A")
        }));

        system.interactions_mut().add_angle("F", "F", "F",
            Box::new(Harmonic{
                k: unit_from(100.0, "kJ/mol/deg^2"),
                x0: unit_from(88.0, "deg")
        }));

        system.interactions_mut().add_dihedral("F", "F", "F", "F",
            Box::new(Harmonic{
                k: unit_from(100.0, "kJ/mol/deg^2"),
                x0: unit_from(185.0, "deg")
        }));

        /// unused interaction to check that we do handle this right
        system.interactions_mut().add_pair("H", "O",
            PairInteraction::new(Box::new(NullPotential), 0.0)
        );

        return system;
    }

    #[test]
    fn pairs() {
        let system = testing_system();
        let evaluator = EnergyEvaluator::new(&system);
        assert_ulps_eq!(evaluator.pairs(), unit_from(-258.3019360389957, "kJ/mol"));
        assert_ulps_eq!(evaluator.pairs_tail(), -0.0000028110338032153973);
    }

    #[test]
    fn pairs_tail_infinite_cell() {
        let mut system = testing_system();
        system.set_cell(UnitCell::new());

        let evaluator = EnergyEvaluator::new(&system);
        assert_eq!(evaluator.pairs_tail(), 0.0);
    }

    #[test]
    fn bonds() {
        let system = testing_system();
        let evaluator = EnergyEvaluator::new(&system);
        assert_ulps_eq!(evaluator.bonds(), unit_from(150.0, "kJ/mol"));
    }

    #[test]
    fn angles() {
        let system = testing_system();
        let evaluator = EnergyEvaluator::new(&system);
        assert_ulps_eq!(evaluator.angles(), unit_from(400.0, "kJ/mol"));
    }

    #[test]
    fn dihedrals() {
        let system = testing_system();
        let evaluator = EnergyEvaluator::new(&system);
        assert_ulps_eq!(evaluator.dihedrals(), unit_from(1250.0, "kJ/mol"), max_ulps=15);
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt::Error as FmtError;
use std::fmt::{Display, Formatter};

generate_error_types!(StoreError, StoreErrorKind,
    BackendError      => "Backend Error",
    NoCommandlineCall => "No commandline call"
);

<commit_msg>imag-store: Replace error module imports with macro helper<commit_after>generate_error_imports!();

generate_error_types!(StoreError, StoreErrorKind,
    BackendError      => "Backend Error",
    NoCommandlineCall => "No commandline call"
);

<|endoftext|>