<commit_before>// xfail-boot
// based on:
// http://shootout.alioth.debian.org/u32/benchmark.php?test=nbody&lang=java

fn main() {

    log "foo";

    let vec[int] inputs = vec(
        50000
        //these segfault :(
        //500000,
        //5000000,
        //50000000
        );

    let vec[Body.props] bodies = NBodySystem.MakeNBodySystem();

    for (int n in inputs) {
        // TODO: make #fmt handle floats?
        log NBodySystem.energy(bodies);

        let int i = 0;
        while (i < n) {
            bodies = NBodySystem.advance(bodies, 0.01);
            i = i+1;
        }
        log NBodySystem.energy(bodies);
    }
}

// making a native call to sqrt
native "rust" mod rustrt {
    fn squareroot(&float input, &mutable float output);
}

// Body.props is a record of floats, so
// vec[Body.props] is a vector of records of floats

mod NBodySystem {

    fn MakeNBodySystem() -> vec[Body.props] {
        // can't iterate over a record?  how about a vector, then?
        let vec[Body.props] bodies = vec(
            // these each return a Body.props
            Body.sun(),
            Body.jupiter(),
            Body.saturn(),
            Body.uranus(),
            Body.neptune());

        let float px = 0.0;
        let float py = 0.0;
        let float pz = 0.0;

        for (Body.props body in bodies) {
            px += body.vx * body.mass;
            py += body.vy * body.mass;
            pz += body.vz * body.mass;
        }

        // side-effecting
        Body.offsetMomentum(bodies.(0), px, py, pz);

        ret bodies;
    }

    fn advance(vec[Body.props] bodies, float dt) -> vec[Body.props] {
        for (Body.props ibody in bodies) {

            let Body.props iBody = ibody;

            for (Body.props jbody in bodies) {
                let float dx = iBody.x - jbody.x;
                let float dy = iBody.y - jbody.y;
                let float dz = iBody.z - jbody.z;

                let float dSquared = dx * dx + dy * dy + dz * dz;

                let float distance;
                rustrt.squareroot(dSquared, distance);
                let float mag = dt / (dSquared * distance);

                iBody.vx -= dx * jbody.mass * mag;
                iBody.vy -= dy * jbody.mass * mag;
                iBody.vz -= dz * jbody.mass * mag;

                jbody.vx += dx * iBody.mass * mag;
                jbody.vy += dy * iBody.mass * mag;
                jbody.vz += dz * iBody.mass * mag;
            }
        }

        for (Body.props body in bodies) {
            body.x += dt * body.vx;
            body.y += dt * body.vy;
            body.z += dt * body.vz;
        }

        ret bodies;
    }

    fn energy(vec[Body.props] bodies) -> float {
        let float dx;
        let float dy;
        let float dz;
        let float distance;
        let float e = 0.0;

        for (Body.props ibody in bodies) {

            // do we need this?
            let Body.props iBody = ibody;

            e += 0.5 * iBody.mass *
                ( iBody.vx * iBody.vx
                  + iBody.vy * iBody.vy
                  + iBody.vz * iBody.vz );

            for (Body.props jbody in bodies) {

                // do we need this?
                let Body.props jBody = jbody;

                dx = iBody.x - jBody.x;
                dy = iBody.y - jBody.y;
                dz = iBody.z - jBody.z;

                rustrt.squareroot(dx*dx + dy*dy + dz*dz, distance);
                e -= (iBody.mass * jBody.mass) / distance;
            }
        }
        ret e;
    }

}

mod Body {

    const float PI = 3.14;
    const float SOLAR_MASS = 39.47; // was 4 * PI * PI originally
    const float DAYS_PER_YEAR = 365.24;

    type props = rec(float x,
                     float y,
                     float z,
                     float vx,
                     float vy,
                     float vz,
                     float mass);

    fn jupiter() -> Body.props {
        // current limitation of the float lexer: decimal part has to
        // fit into a 32-bit int.

        let Body.props p;
        p.x    =  4.84e+00;
        p.y    = -1.16e+00;
        p.z    = -1.03e-01;
        p.vx   =  1.66e-03 * DAYS_PER_YEAR;
        p.vy   =  7.69e-03 * DAYS_PER_YEAR;
        p.vz   = -6.90e-05 * DAYS_PER_YEAR;
        p.mass =  9.54e-04 * SOLAR_MASS;
        ret p;
    }

    fn saturn() -> Body.props {
        let Body.props p;
        p.x    =  8.34e+00;
        p.y    =  4.12e+00;
        p.z    = -4.03e-01;
        p.vx   = -2.76e-03 * DAYS_PER_YEAR;
        p.vy   =  4.99e-03 * DAYS_PER_YEAR;
        p.vz   =  2.30e-05 * DAYS_PER_YEAR;
        p.mass =  2.85e-04 * SOLAR_MASS;
        ret p;
   }

    fn uranus() -> Body.props {
        let Body.props p;
        p.x    =  1.28e+01;
        p.y    = -1.51e+01;
        p.z    = -2.23e-01;
        p.vx   =  2.96e-03 * DAYS_PER_YEAR;
        p.vy   =  2.37e-03 * DAYS_PER_YEAR;
        p.vz   = -2.96e-05 * DAYS_PER_YEAR;
        p.mass =  4.36e-05 * SOLAR_MASS;
        ret p;
    }

    fn neptune() -> Body.props {
        let Body.props p;
        p.x    =  1.53e+01;
        p.y    = -2.59e+01;
        p.z    =  1.79e-01;
        p.vx   =  2.68e-03 * DAYS_PER_YEAR;
        p.vy   =  1.62e-03 * DAYS_PER_YEAR;
        p.vz   = -9.51e-05 * DAYS_PER_YEAR;
        p.mass =  5.15e-05 * SOLAR_MASS;
        ret p;
   }

   fn sun() -> Body.props {
        let Body.props p;
        p.mass = SOLAR_MASS;
        ret p;
   }

   impure fn offsetMomentum(mutable Body.props props,
                     float px,
                     float py,
                     float pz) -> Body.props {

       props.vx = -px / SOLAR_MASS;
       props.vy = -py / SOLAR_MASS;
       props.vz = -pz / SOLAR_MASS;
   }

}
<commit_msg>Got the nbody demo working, and hopefully faster, too!<commit_after>// xfail-boot
// based on:
// http://shootout.alioth.debian.org/u32/benchmark.php?test=nbody&lang=java

fn main() {

    let vec[int] inputs = vec(
        50000
        //these segfault :(
        //500000,
        //5000000,
        //50000000
        );

    let vec[Body.props] bodies = NBodySystem.MakeNBodySystem();

    for (int n in inputs) {
        log NBodySystem.energy(bodies);

        let int i = 0;
        while (i < n) {
            NBodySystem.advance(bodies, 0.01);
            i += 1;
        }
        log NBodySystem.energy(bodies);
    }
}

// making a native call to sqrt
native "rust" mod rustrt {
    fn squareroot(&float input, &mutable float output);
}

// Body.props is a record of floats, so
// vec[Body.props] is a vector of records of floats

mod NBodySystem {

    fn MakeNBodySystem() -> vec[Body.props] {
        let vec[Body.props] bodies = vec(
            // these each return a Body.props
            Body.sun(),
            Body.jupiter(),
            Body.saturn(),
            Body.uranus(),
            Body.neptune());

        let float px = 0.0;
        let float py = 0.0;
        let float pz = 0.0;

        let int i = 0;
        while (i < 5) {
            px += bodies.(i).vx * bodies.(i).mass;
            py += bodies.(i).vy * bodies.(i).mass;
            pz += bodies.(i).vz * bodies.(i).mass;

            i += 1;
        }

        // side-effecting
        Body.offsetMomentum(bodies.(0), px, py, pz);

        ret bodies;
    }

    fn advance(vec[Body.props] bodies, float dt) -> () {

        let int i = 0;
        while (i < 5) {
            let int j = i+1;
            while (j < 5) {
                let float dx = bodies.(i).x - bodies.(j).x;
                let float dy = bodies.(i).y - bodies.(j).y;
                let float dz = bodies.(i).z - bodies.(j).z;

                let float dSquared = dx * dx + dy * dy + dz * dz;

                let float distance;
                rustrt.squareroot(dSquared, distance);
                let float mag = dt / (dSquared * distance);

                bodies.(i).vx -= dx * bodies.(j).mass * mag;
                bodies.(i).vy -= dy * bodies.(j).mass * mag;
                bodies.(i).vz -= dz * bodies.(j).mass * mag;

                bodies.(j).vx += dx * bodies.(i).mass * mag;
                bodies.(j).vy += dy * bodies.(i).mass * mag;
                bodies.(j).vz += dz * bodies.(i).mass * mag;

                j += 1;

            }

            i += 1;
        }

        i = 0;
        while (i < 5) {

            bodies.(i).x += dt * bodies.(i).vx;
            bodies.(i).y += dt * bodies.(i).vy;
            bodies.(i).z += dt * bodies.(i).vz;

            i += 1;
        }
    }

    fn energy(vec[Body.props] bodies) -> float {
        let float dx;
        let float dy;
        let float dz;
        let float distance;
        let float e = 0.0;

        let int i = 0;
        while (i < 5) {
            e += 0.5 * bodies.(i).mass *
                (  bodies.(i).vx * bodies.(i).vx
                 + bodies.(i).vy * bodies.(i).vy
                 + bodies.(i).vz * bodies.(i).vz );

            let int j = i+1;
            while (j < 5) {
                dx = bodies.(i).x - bodies.(j).x;
                dy = bodies.(i).y - bodies.(j).y;
                dz = bodies.(i).z - bodies.(j).z;

                rustrt.squareroot(dx*dx + dy*dy + dz*dz, distance);
                e -= (bodies.(i).mass * bodies.(j).mass) / distance;

                j += 1;
            }

            i += 1;
        }
        ret e;

    }
}

mod Body {

    const float PI = 3.141592653589793;
    const float SOLAR_MASS = 39.478417604357432; // was 4 * PI * PI originally
    const float DAYS_PER_YEAR = 365.24;

    type props = rec(mutable float x,
                     mutable float y,
                     mutable float z,
                     mutable float vx,
                     mutable float vy,
                     mutable float vz,
                     float mass);

    fn jupiter() -> Body.props {
        ret rec(
            mutable x  =  4.84143144246472090e+00,
            mutable y  = -1.16032004402742839e+00,
            mutable z  = -1.03622044471123109e-01,
            mutable vx =  1.66007664274403694e-03 * DAYS_PER_YEAR,
            mutable vy =  7.69901118419740425e-03 * DAYS_PER_YEAR,
            mutable vz = -6.90460016972063023e-05 * DAYS_PER_YEAR,
            mass       =  9.54791938424326609e-04 * SOLAR_MASS
            );
    }

    fn saturn() -> Body.props {
        ret rec(
            mutable x  =  8.34336671824457987e+00,
            mutable y  =  4.12479856412430479e+00,
            mutable z  = -4.03523417114321381e-01,
            mutable vx = -2.76742510726862411e-03 * DAYS_PER_YEAR,
            mutable vy =  4.99852801234917238e-03 * DAYS_PER_YEAR,
            mutable vz =  2.30417297573763929e-05 * DAYS_PER_YEAR,
            mass       =  2.85885980666130812e-04 * SOLAR_MASS
            );
   }

    fn uranus() -> Body.props {
        ret rec(
            mutable x  =  1.28943695621391310e+01,
            mutable y  = -1.51111514016986312e+01,
            mutable z  = -2.23307578892655734e-01,
            mutable vx =  2.96460137564761618e-03 * DAYS_PER_YEAR,
            mutable vy =  2.37847173959480950e-03 * DAYS_PER_YEAR,
            mutable vz = -2.96589568540237556e-05 * DAYS_PER_YEAR,
            mass       =  4.36624404335156298e-05 * SOLAR_MASS
            );
    }

    fn neptune() -> Body.props {
        ret rec(
            mutable x  =  1.53796971148509165e+01,
            mutable y  = -2.59193146099879641e+01,
            mutable z  =  1.79258772950371181e-01,
            mutable vx =  2.68067772490389322e-03 * DAYS_PER_YEAR,
            mutable vy =  1.62824170038242295e-03 * DAYS_PER_YEAR,
            mutable vz = -9.51592254519715870e-05 * DAYS_PER_YEAR,
            mass       =  5.15138902046611451e-05 * SOLAR_MASS
            );
   }

   fn sun() -> Body.props {
       ret rec(
           mutable x  =  0.0,
           mutable y  =  0.0,
           mutable z  =  0.0,
           mutable vx =  0.0,
           mutable vy =  0.0,
           mutable vz =  0.0,
           mass       =  SOLAR_MASS
           );
   }

   impure fn offsetMomentum(&Body.props props,
                            float px,
                            float py,
                            float pz) -> () {
       props.vx = -px / SOLAR_MASS;
       props.vy = -py / SOLAR_MASS;
       props.vz = -pz / SOLAR_MASS;
   }

}
<|endoftext|>


<commit_before>// Copyright 2018 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

#![feature(
    weak_counts,
    non_exhaustive,
    integer_atomics,
    try_trait,
    arbitrary_self_types,
    async_await,
    trait_alias,
    async_closure,
)]
#![deny(missing_docs, missing_debug_implementations)]

//! An RPC framework providing client and server.
//!
//! Features:
//! * RPC deadlines, both client- and server-side.
//! * Cascading cancellation (works with multiple hops).
//! * Configurable limits
//!    * In-flight requests, both client and server-side.
//!        * Server-side limit is per-connection.
//!        * When the server reaches the in-flight request maximum, it returns a throttled error
//!          to the client.
//!        * When the client reaches the in-flight request max, messages are buffered up to a
//!          configurable maximum, beyond which the requests are back-pressured.
//!    * Server connections.
//!        * Total and per-IP limits.
//!        * When an incoming connection is accepted, if already at maximum, the connection is
//!          dropped.
//! * Transport agnostic.

pub mod client;
pub mod context;
pub mod server;
pub mod transport;
pub(crate) mod util;

pub use crate::{client::Client, server::Server, transport::Transport};

use futures::{
    task::{Poll, Spawn, SpawnError, SpawnExt},
    Future,
};
use once_cell::sync::OnceCell;
use std::{cell::RefCell, io, time::SystemTime};

/// A message from a client to a server.
#[derive(Debug)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum ClientMessage<T> {
    /// A request initiated by a user. The server responds to a request by invoking a
    /// service-provided request handler.  The handler completes with a [`response`](Response), which
    /// the server sends back to the client.
    Request(Request<T>),
    /// A command to cancel an in-flight request, automatically sent by the client when a response
    /// future is dropped.
    ///
    /// When received, the server will immediately cancel the main task (top-level future) of the
    /// request handler for the associated request. Any tasks spawned by the request handler will
    /// not be canceled, because the framework layer does not
    /// know about them.
    Cancel {
        /// The trace context associates the message with a specific chain of causally-related actions,
        /// possibly orchestrated across many distributed systems.
        #[cfg_attr(feature = "serde", serde(default))]
        trace_context: trace::Context,
        /// The ID of the request to cancel.
        request_id: u64,
    },
}

/// A request from a client to a server.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub struct Request<T> {
    /// Trace context, deadline, and other cross-cutting concerns.
    pub context: context::Context,
    /// Uniquely identifies the request across all requests sent over a single channel.
    pub id: u64,
    /// The request body.
    pub message: T,
}

/// A response from a server to a client.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub struct Response<T> {
    /// The ID of the request being responded to.
    pub request_id: u64,
    /// The response body, or an error if the request failed.
    pub message: Result<T, ServerError>,
}

/// An error response from a server to a client.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub struct ServerError {
    #[cfg_attr(
        feature = "serde1",
        serde(serialize_with = "util::serde::serialize_io_error_kind_as_u32")
    )]
    #[cfg_attr(
        feature = "serde1",
        serde(deserialize_with = "util::serde::deserialize_io_error_kind_from_u32")
    )]
    /// The type of error that occurred to fail the request.
    pub kind: io::ErrorKind,
    /// A message describing more detail about the error that occurred.
    pub detail: Option<String>,
}

impl From<ServerError> for io::Error {
    fn from(e: ServerError) -> io::Error {
        io::Error::new(e.kind, e.detail.unwrap_or_default())
    }
}

impl<T> Request<T> {
    /// Returns the deadline for this request.
    pub fn deadline(&self) -> &SystemTime {
        &self.context.deadline
    }
}

pub(crate) type PollIo<T> = Poll<Option<io::Result<T>>>;

static SEED_SPAWN: OnceCell<Box<dyn CloneSpawn + Send + Sync>> = OnceCell::new();

thread_local! {
    static SPAWN: RefCell<Box<dyn CloneSpawn>> =
        RefCell::new(SEED_SPAWN.get().expect("init() must be called.").box_clone());
}

/// Initializes the RPC library with a mechanism to spawn futures on the user's runtime.
/// Client stubs and servers both use the initialized spawn.
///
/// Init only has an effect the first time it is called. If called previously, successive calls to
/// init are noops.
pub fn init(spawn: impl Spawn + Clone + Send + Sync + 'static) {
    let _ = SEED_SPAWN.set(Box::new(spawn));
}

pub(crate) fn spawn(future: impl Future<Output = ()> + Send + 'static) -> Result<(), SpawnError> {
    SPAWN.with(|spawn| spawn.borrow_mut().spawn(future))
}

trait CloneSpawn: Spawn {
    fn box_clone(&self) -> Box<dyn CloneSpawn>;
}

impl<S: Spawn + Clone + 'static> CloneSpawn for S {
    fn box_clone(&self) -> Box<dyn CloneSpawn> {
        Box::new(self.clone())
    }
}
<commit_msg>Remove unused unstable feature 'integer_atomics'<commit_after>// Copyright 2018 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

#![feature(
    weak_counts,
    non_exhaustive,
    try_trait,
    arbitrary_self_types,
    async_await,
    trait_alias,
    async_closure,
)]
#![deny(missing_docs, missing_debug_implementations)]

//! An RPC framework providing client and server.
//!
//! Features:
//! * RPC deadlines, both client- and server-side.
//! * Cascading cancellation (works with multiple hops).
//! * Configurable limits
//!    * In-flight requests, both client and server-side.
//!        * Server-side limit is per-connection.
//!        * When the server reaches the in-flight request maximum, it returns a throttled error
//!          to the client.
//!        * When the client reaches the in-flight request max, messages are buffered up to a
//!          configurable maximum, beyond which the requests are back-pressured.
//!    * Server connections.
//!        * Total and per-IP limits.
//!        * When an incoming connection is accepted, if already at maximum, the connection is
//!          dropped.
//! * Transport agnostic.

pub mod client;
pub mod context;
pub mod server;
pub mod transport;
pub(crate) mod util;

pub use crate::{client::Client, server::Server, transport::Transport};

use futures::{
    task::{Poll, Spawn, SpawnError, SpawnExt},
    Future,
};
use once_cell::sync::OnceCell;
use std::{cell::RefCell, io, time::SystemTime};

/// A message from a client to a server.
#[derive(Debug)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum ClientMessage<T> {
    /// A request initiated by a user. The server responds to a request by invoking a
    /// service-provided request handler.  The handler completes with a [`response`](Response), which
    /// the server sends back to the client.
    Request(Request<T>),
    /// A command to cancel an in-flight request, automatically sent by the client when a response
    /// future is dropped.
    ///
    /// When received, the server will immediately cancel the main task (top-level future) of the
    /// request handler for the associated request. Any tasks spawned by the request handler will
    /// not be canceled, because the framework layer does not
    /// know about them.
    Cancel {
        /// The trace context associates the message with a specific chain of causally-related actions,
        /// possibly orchestrated across many distributed systems.
        #[cfg_attr(feature = "serde", serde(default))]
        trace_context: trace::Context,
        /// The ID of the request to cancel.
        request_id: u64,
    },
}

/// A request from a client to a server.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub struct Request<T> {
    /// Trace context, deadline, and other cross-cutting concerns.
    pub context: context::Context,
    /// Uniquely identifies the request across all requests sent over a single channel.
    pub id: u64,
    /// The request body.
    pub message: T,
}

/// A response from a server to a client.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub struct Response<T> {
    /// The ID of the request being responded to.
    pub request_id: u64,
    /// The response body, or an error if the request failed.
    pub message: Result<T, ServerError>,
}

/// An error response from a server to a client.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub struct ServerError {
    #[cfg_attr(
        feature = "serde1",
        serde(serialize_with = "util::serde::serialize_io_error_kind_as_u32")
    )]
    #[cfg_attr(
        feature = "serde1",
        serde(deserialize_with = "util::serde::deserialize_io_error_kind_from_u32")
    )]
    /// The type of error that occurred to fail the request.
    pub kind: io::ErrorKind,
    /// A message describing more detail about the error that occurred.
    pub detail: Option<String>,
}

impl From<ServerError> for io::Error {
    fn from(e: ServerError) -> io::Error {
        io::Error::new(e.kind, e.detail.unwrap_or_default())
    }
}

impl<T> Request<T> {
    /// Returns the deadline for this request.
    pub fn deadline(&self) -> &SystemTime {
        &self.context.deadline
    }
}

pub(crate) type PollIo<T> = Poll<Option<io::Result<T>>>;

static SEED_SPAWN: OnceCell<Box<dyn CloneSpawn + Send + Sync>> = OnceCell::new();

thread_local! {
    static SPAWN: RefCell<Box<dyn CloneSpawn>> =
        RefCell::new(SEED_SPAWN.get().expect("init() must be called.").box_clone());
}

/// Initializes the RPC library with a mechanism to spawn futures on the user's runtime.
/// Client stubs and servers both use the initialized spawn.
///
/// Init only has an effect the first time it is called. If called previously, successive calls to
/// init are noops.
pub fn init(spawn: impl Spawn + Clone + Send + Sync + 'static) {
    let _ = SEED_SPAWN.set(Box::new(spawn));
}

pub(crate) fn spawn(future: impl Future<Output = ()> + Send + 'static) -> Result<(), SpawnError> {
    SPAWN.with(|spawn| spawn.borrow_mut().spawn(future))
}

trait CloneSpawn: Spawn {
    fn box_clone(&self) -> Box<dyn CloneSpawn>;
}

impl<S: Spawn + Clone + 'static> CloneSpawn for S {
    fn box_clone(&self) -> Box<dyn CloneSpawn> {
        Box::new(self.clone())
    }
}
<|endoftext|>


<commit_before>pub type XMM_SAVE_AREA32 = XSAVE_FORMAT;

s_no_extra_traits! {
    #[repr(align(16))]
    pub union __c_anonymous_CONTEXT_FP {
        pub FltSave: ::XMM_SAVE_AREA32,
        pub Xmm: __c_anonymous_CONTEXT_XMM,
    }
}

cfg_if! {
    if #[cfg(feature = "extra_traits")] {
        impl PartialEq for __c_anonymous_CONTEXT_FP {
            fn eq(&self, other: &__c_anonymous_CONTEXT_FP) -> bool {
                unsafe {
                    self.FltSave == other.FltSave ||
                        self.Xmm == other.Xmm
                }
            }
        }
        impl Eq for __c_anonymous_CONTEXT_FP {}
        impl ::fmt::Debug for __c_anonymous_CONTEXT_FP {
            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
                unsafe {
                    f.debug_struct("__c_anonymous_CONTEXT_FP")
                        .field("FltSave", &self.FltSave)
                        .finish()
                }
            }
        }
        impl ::hash::Hash for __c_anonymous_CONTEXT_FP {
            fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
                unsafe {
                    self.FltSave.hash(state);
                    self.Xmm.hash(state);
                }
            }
        }
    }
}

s! {
    #[repr(align(16))]
    pub struct M128A {
        pub Low: ::c_ulonglong,
        pub High: ::c_longlong,
    }

    #[repr(align(16))]
    pub struct XSAVE_FORMAT {
        pub ControlWord: ::c_ushort,
        pub StatusWord: ::c_ushort,
        pub TagWord: ::c_uchar,
        _Reserved1: ::c_uchar,
        pub ErrorOpcode: ::c_ushort,
        pub ErrorOffset: ::c_ulong,
        pub ErrorSelector: ::c_ushort,
        _Reserved2: ::c_ushort,
        pub DataOffset: ::c_ulong,
        pub DataSelector: ::c_ushort,
        _Reserved3: ::c_ushort,
        pub MxCsr: ::c_ulong,
        pub MxCsr_Mask: ::c_ulong,
        pub FloatRegisters: [M128A; 8],
        pub XmmRegisters: [M128A; 16],
        _Reserved4: [[::c_uchar; 16]; 6],
    }

    #[repr(align(16))]
    pub struct __c_anonymous_CONTEXT_XMM {
        pub Header: [M128A; 2],
        pub Legacy: [M128A; 8],
        pub Xmm0: M128A,
        pub Xmm1: M128A,
        pub Xmm2: M128A,
        pub Xmm3: M128A,
        pub Xmm4: M128A,
        pub Xmm5: M128A,
        pub Xmm6: M128A,
        pub Xmm7: M128A,
        pub Xmm8: M128A,
        pub Xmm9: M128A,
        pub Xmm10: M128A,
        pub Xmm11: M128A,
        pub Xmm12: M128A,
        pub Xmm13: M128A,
        pub Xmm14: M128A,
        pub Xmm15: M128A,
    }

    #[repr(align(16))]
    pub struct CONTEXT {
        pub P1Home: u64,
        pub P2Home: u64,
        pub P3Home: u64,
        pub P4Home: u64,
        pub P5Home: u64,
        pub P6Home: u64,
        pub ContextFlags: ::c_ulong,
        pub MxCsr: ::c_ulong,
        pub SegCs: ::c_ushort,
        pub SegDs: ::c_ushort,
        pub SegEs: ::c_ushort,
        pub SegFs: ::c_ushort,
        pub SegGs: ::c_ushort,
        pub SegSs: ::c_ushort,
        pub EFlags: ::c_ulong,
        pub Dr0: u64,
        pub Dr1: u64,
        pub Dr2: u64,
        pub Dr3: u64,
        pub Dr6: u64,
        pub Dr7: u64,
        pub Rax: u64,
        pub Rcx: u64,
        pub Rdx: u64,
        pub Rbx: u64,
        pub Rsp: u64,
        pub Rbp: u64,
        pub Rsi: u64,
        pub Rdi: u64,
        pub R8: u64,
        pub R9: u64,
        pub R10: u64,
        pub R11: u64,
        pub R12: u64,
        pub R13: u64,
        pub R14: u64,
        pub R15: u64,
        pub Rip: u64,
        pub Fp: __c_anonymous_CONTEXT_FP,
        pub VectorRegister: [M128A; 26],
        pub VectorControl: u64,
        pub DebugControl: u64,
        pub LastBranchToRip: u64,
        pub LastBranchFromRip: u64,
        pub LastExceptionToRip: u64,
        pub LastExceptionFromRip: u64,
    }
}
<commit_msg>windows deprecate CONTEXT and related types.<commit_after>#[allow(deprecated)]
pub type XMM_SAVE_AREA32 = XSAVE_FORMAT;

s_no_extra_traits! {
    #[repr(align(16))]
    pub union __c_anonymous_CONTEXT_FP {
        pub FltSave: ::XMM_SAVE_AREA32,
        pub Xmm: __c_anonymous_CONTEXT_XMM,
    }
}

cfg_if! {
    if #[cfg(feature = "extra_traits")] {
        impl PartialEq for __c_anonymous_CONTEXT_FP {
            fn eq(&self, other: &__c_anonymous_CONTEXT_FP) -> bool {
                unsafe {
                    self.FltSave == other.FltSave ||
                        self.Xmm == other.Xmm
                }
            }
        }
        impl Eq for __c_anonymous_CONTEXT_FP {}
        impl ::fmt::Debug for __c_anonymous_CONTEXT_FP {
            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
                unsafe {
                    f.debug_struct("__c_anonymous_CONTEXT_FP")
                        .field("FltSave", &self.FltSave)
                        .finish()
                }
            }
        }
        impl ::hash::Hash for __c_anonymous_CONTEXT_FP {
            fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
                unsafe {
                    self.FltSave.hash(state);
                    self.Xmm.hash(state);
                }
            }
        }
    }
}

s! {
    #[doc(hidden)]
    #[deprecated(since = "0.2.104", note = "use the `winapi` crate instead; we're going to
remove it in a future release")]
    #[repr(align(16))]
    pub struct M128A {
        pub Low: ::c_ulonglong,
        pub High: ::c_longlong,
    }

    #[doc(hidden)]
    #[deprecated(since = "0.2.104", note = "use the `winapi` crate instead; we're going to
remove it in a future release")]
    #[repr(align(16))]
    pub struct XSAVE_FORMAT {
        pub ControlWord: ::c_ushort,
        pub StatusWord: ::c_ushort,
        pub TagWord: ::c_uchar,
        _Reserved1: ::c_uchar,
        pub ErrorOpcode: ::c_ushort,
        pub ErrorOffset: ::c_ulong,
        pub ErrorSelector: ::c_ushort,
        _Reserved2: ::c_ushort,
        pub DataOffset: ::c_ulong,
        pub DataSelector: ::c_ushort,
        _Reserved3: ::c_ushort,
        pub MxCsr: ::c_ulong,
        pub MxCsr_Mask: ::c_ulong,
        pub FloatRegisters: [M128A; 8],
        pub XmmRegisters: [M128A; 16],
        _Reserved4: [[::c_uchar; 16]; 6],
    }

    #[repr(align(16))]
    pub struct __c_anonymous_CONTEXT_XMM {
        pub Header: [M128A; 2],
        pub Legacy: [M128A; 8],
        pub Xmm0: M128A,
        pub Xmm1: M128A,
        pub Xmm2: M128A,
        pub Xmm3: M128A,
        pub Xmm4: M128A,
        pub Xmm5: M128A,
        pub Xmm6: M128A,
        pub Xmm7: M128A,
        pub Xmm8: M128A,
        pub Xmm9: M128A,
        pub Xmm10: M128A,
        pub Xmm11: M128A,
        pub Xmm12: M128A,
        pub Xmm13: M128A,
        pub Xmm14: M128A,
        pub Xmm15: M128A,
    }

    #[doc(hidden)]
    #[deprecated(since = "0.2.104", note = "use the `winapi` crate instead; we're going to
remove it in a future release")]
    #[repr(align(16))]
    pub struct CONTEXT {
        pub P1Home: u64,
        pub P2Home: u64,
        pub P3Home: u64,
        pub P4Home: u64,
        pub P5Home: u64,
        pub P6Home: u64,
        pub ContextFlags: ::c_ulong,
        pub MxCsr: ::c_ulong,
        pub SegCs: ::c_ushort,
        pub SegDs: ::c_ushort,
        pub SegEs: ::c_ushort,
        pub SegFs: ::c_ushort,
        pub SegGs: ::c_ushort,
        pub SegSs: ::c_ushort,
        pub EFlags: ::c_ulong,
        pub Dr0: u64,
        pub Dr1: u64,
        pub Dr2: u64,
        pub Dr3: u64,
        pub Dr6: u64,
        pub Dr7: u64,
        pub Rax: u64,
        pub Rcx: u64,
        pub Rdx: u64,
        pub Rbx: u64,
        pub Rsp: u64,
        pub Rbp: u64,
        pub Rsi: u64,
        pub Rdi: u64,
        pub R8: u64,
        pub R9: u64,
        pub R10: u64,
        pub R11: u64,
        pub R12: u64,
        pub R13: u64,
        pub R14: u64,
        pub R15: u64,
        pub Rip: u64,
        pub Fp: __c_anonymous_CONTEXT_FP,
        pub VectorRegister: [M128A; 26],
        pub VectorControl: u64,
        pub DebugControl: u64,
        pub LastBranchToRip: u64,
        pub LastBranchFromRip: u64,
        pub LastExceptionToRip: u64,
        pub LastExceptionFromRip: u64,
    }
}
<|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/. */

use euclid::length::Length;
use ipc_channel::ipc::{self, IpcSender};
use ipc_channel::router::ROUTER;
use script_traits::{MsDuration, NsDuration, precise_time_ms, precise_time_ns};
use script_traits::{TimerEvent, TimerEventRequest};
use std::cell::RefCell;
use std::cmp::{self, Ord};
use std::collections::BinaryHeap;
use std::sync::Arc;
use std::sync::atomic::{self, AtomicBool};
use std::sync::mpsc::{channel, Receiver, Select};
use std::thread::{self, spawn, Thread};
use std::time::Duration;
use util::thread::spawn_named;

/// A quick hack to work around the removal of [`std::old_io::timer::Timer`](
/// http://doc.rust-lang.org/1.0.0-beta/std/old_io/timer/struct.Timer.html )
struct CancelableOneshotTimer {
    thread: Thread,
    canceled: Arc<AtomicBool>,
    port: Receiver<()>,
}

impl CancelableOneshotTimer {
    fn new(duration: MsDuration) -> CancelableOneshotTimer {
        let (tx, rx) = channel();
        let canceled = Arc::new(AtomicBool::new(false));
        let canceled_clone = canceled.clone();

        let thread = spawn(move || {
            let due_time = precise_time_ms() + duration;

            let mut park_time = duration;

            loop {
                thread::park_timeout(Duration::from_millis(park_time.get()));

                if canceled_clone.load(atomic::Ordering::Relaxed) {
                    return;
                }

                // park_timeout_ms does not guarantee parking for the
                // given amout. We might have woken up early.
                let current_time = precise_time_ms();
                if current_time >= due_time {
                    let _ = tx.send(());
                    return;
                }
                park_time = due_time - current_time;
            }
        }).thread().clone();

        CancelableOneshotTimer {
            thread: thread,
            canceled: canceled,
            port: rx,
        }
    }

    fn port(&self) -> &Receiver<()> {
        &self.port
    }

    fn cancel(&self) {
        self.canceled.store(true, atomic::Ordering::Relaxed);
        self.thread.unpark();
    }
}

pub struct TimerScheduler {
    port: Receiver<TimerEventRequest>,

    scheduled_events: RefCell<BinaryHeap<ScheduledEvent>>,

    timer: RefCell<Option<CancelableOneshotTimer>>,
}

struct ScheduledEvent {
    request: TimerEventRequest,
    for_time: NsDuration,
}

impl Ord for ScheduledEvent {
    fn cmp(&self, other: &ScheduledEvent) -> cmp::Ordering {
        self.for_time.cmp(&other.for_time).reverse()
    }
}

impl PartialOrd for ScheduledEvent {
    fn partial_cmp(&self, other: &ScheduledEvent) -> Option<cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl Eq for ScheduledEvent {}
impl PartialEq for ScheduledEvent {
    fn eq(&self, other: &ScheduledEvent) -> bool {
        self as *const ScheduledEvent == other as *const ScheduledEvent
    }
}

enum Task {
    HandleRequest(TimerEventRequest),
    DispatchDueEvents,
}

impl TimerScheduler {
    pub fn start() -> IpcSender<TimerEventRequest> {
        let (chan, port) = ipc::channel().unwrap();

        let timer_scheduler = TimerScheduler {
            port: ROUTER.route_ipc_receiver_to_new_mpsc_receiver(port),

            scheduled_events: RefCell::new(BinaryHeap::new()),

            timer: RefCell::new(None),
        };

        spawn_named("TimerScheduler".to_owned(), move || {
            timer_scheduler.run_event_loop();
        });

        chan
    }

    fn run_event_loop(&self) {
        while let Some(thread) = self.receive_next_task() {
            match thread {
                Task::HandleRequest(request) => self.handle_request(request),
                Task::DispatchDueEvents => self.dispatch_due_events(),
            }
        }
    }

    #[allow(unsafe_code)]
    fn receive_next_task(&self) -> Option<Task> {
        let port = &self.port;
        let timer = self.timer.borrow();
        let timer_port = timer.as_ref().map(|timer| timer.port());

        if let Some(ref timer_port) = timer_port {
            let sel = Select::new();
            let mut scheduler_handle = sel.handle(port);
            let mut timer_handle = sel.handle(timer_port);

            unsafe {
                scheduler_handle.add();
                timer_handle.add();
            }

            let ret = sel.wait();
            if ret == scheduler_handle.id() {
                port.recv().ok().map(Task::HandleRequest)
            } else if ret == timer_handle.id() {
                timer_port.recv().ok().map(|_| Task::DispatchDueEvents)
            } else {
                panic!("unexpected select result!")
            }
        } else {
            port.recv().ok().map(Task::HandleRequest)
        }
    }

    fn handle_request(&self, request: TimerEventRequest) {
        let TimerEventRequest(_, _, _, duration_ms) = request;
        let duration_ns = Length::new(duration_ms.get() * 1000 * 1000);
        let schedule_for = precise_time_ns() + duration_ns;

        let previously_earliest = self.scheduled_events.borrow().peek()
                .map_or(Length::new(u64::max_value()), |scheduled| scheduled.for_time);

        self.scheduled_events.borrow_mut().push(ScheduledEvent {
            request: request,
            for_time: schedule_for,
        });

        if schedule_for < previously_earliest {
            self.start_timer_for_next_event();
        }
    }

    fn dispatch_due_events(&self) {
        let now = precise_time_ns();

        {
            let mut events = self.scheduled_events.borrow_mut();

            while !events.is_empty() && events.peek().as_ref().unwrap().for_time <= now {
                let event = events.pop().unwrap();
                let TimerEventRequest(chan, source, id, _) = event.request;

                let _ = chan.send(TimerEvent(source, id));
            }
        }

        self.start_timer_for_next_event();
    }

    fn start_timer_for_next_event(&self) {
        let events = self.scheduled_events.borrow();
        let next_event = events.peek();

        let mut timer = self.timer.borrow_mut();

        if let Some(ref mut timer) = *timer {
            timer.cancel();
        }

        *timer = next_event.map(|next_event| {
            let delay_ns = next_event.for_time.get().saturating_sub(precise_time_ns().get());
            // Round up, we'd rather be late than early…
            let delay_ms = Length::new(delay_ns.saturating_add(999999) / (1000 * 1000));

            CancelableOneshotTimer::new(delay_ms)
        });
    }
}
<commit_msg>Replace the one-thread-per-timeout model by a two-thread model of timeouts.<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/. */

use ipc_channel::ipc::{self, IpcSender};
use script_traits::{TimerEvent, TimerEventRequest};
use std::cmp::{self, Ord};
use std::collections::BinaryHeap;
use std::sync::mpsc;
use std::sync::mpsc::TryRecvError::{Disconnected, Empty};
use std::thread;
use std::time::{Duration, Instant};

pub struct TimerScheduler;

struct ScheduledEvent {
    request: TimerEventRequest,
    for_time: Instant,
}

impl Ord for ScheduledEvent {
    fn cmp(&self, other: &ScheduledEvent) -> cmp::Ordering {
        self.for_time.cmp(&other.for_time).reverse()
    }
}

impl PartialOrd for ScheduledEvent {
    fn partial_cmp(&self, other: &ScheduledEvent) -> Option<cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl Eq for ScheduledEvent {}
impl PartialEq for ScheduledEvent {
    fn eq(&self, other: &ScheduledEvent) -> bool {
        self as *const ScheduledEvent == other as *const ScheduledEvent
    }
}

impl TimerScheduler {
    pub fn start() -> IpcSender<TimerEventRequest> {
        let (req_ipc_sender, req_ipc_receiver) = ipc::channel().unwrap();
        let (req_sender, req_receiver) = mpsc::sync_channel(1);

        // We could do this much more directly with recv_timeout
        // (https://github.com/rust-lang/rfcs/issues/962).

        // util::thread doesn't give us access to the JoinHandle, which we need for park/unpark,
        // so we use the builder directly.
        let timeout_thread = thread::Builder::new()
            .name(String::from("TimerScheduler"))
            .spawn(move || {
                // We maintain a priority queue of future events, sorted by due time.
                let mut scheduled_events = BinaryHeap::<ScheduledEvent>::new();
                loop {
                    let now = Instant::now();
                    // Dispatch any events whose due time is past
                    loop {
                        match scheduled_events.peek() {
                            // Dispatch the event if its due time is past
                            Some(event) if event.for_time <= now => {
                                let TimerEventRequest(ref sender, source, id, _) = event.request;
                                let _ = sender.send(TimerEvent(source, id));
                            },
                            // Otherwise, we're done dispatching events
                            _ => break,
                        }
                        // Remove the event from the priority queue
                        // (Note this only executes when the first event has been dispatched
                        scheduled_events.pop();
                    }
                    // Look to see if there are any incoming events
                    match req_receiver.try_recv() {
                        // If there is an event, add it to the priority queue
                        Ok(req) => {
                            let TimerEventRequest(_, _, _, delay) = req;
                            let schedule = Instant::now() + Duration::from_millis(delay.get());
                            let event = ScheduledEvent { request: req, for_time: schedule };
                            scheduled_events.push(event);
                        },
                        // If there is no incoming event, park the thread,
                        // it will either be unparked when a new event arrives,
                        // or by a timeout.
                        Err(Empty) => match scheduled_events.peek() {
                            None => thread::park(),
                            Some(event) => thread::park_timeout(event.for_time - now),
                        },
                        // If the channel is closed, we are done.
                        Err(Disconnected) => break,
                    }
                }
                // This thread can terminate if the req_ipc_sender is dropped.
                warn!("TimerScheduler thread terminated.");
            })
            .unwrap()
            .thread()
            .clone();

        // A proxy that just routes incoming IPC requests over the MPSC channel to the timeout thread,
        // and unparks the timeout thread each time. Note that if unpark is called while the timeout
        // thread isn't parked, this causes the next call to thread::park by the timeout thread
        // not to block. This means that the timeout thread won't park when there is a request
        // waiting in the MPSC channel buffer.
        thread::Builder::new()
            .name(String::from("TimerProxy"))
            .spawn(move || {
                while let Ok(req) = req_ipc_receiver.recv() {
                    req_sender.send(req).unwrap();
                    timeout_thread.unpark();
                }
                // This thread can terminate if the req_ipc_sender is dropped.
                warn!("TimerProxy thread terminated.");
            })
            .unwrap();

        // Return the IPC sender
        req_ipc_sender
    }
}
<|endoftext|>


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

#![deny(missing_docs)]

//! Graphics device. Not meant for direct use.

use std::{fmt, mem};
use std::hash::Hash;

pub use draw_state::target;
pub use draw_state::state;

pub mod attrib;
pub mod command;
pub mod draw;
pub mod dummy;
pub mod handle;
pub mod mapping;
pub mod shade;
pub mod tex;

mod arc;

/// Draw vertex count.
pub type VertexCount = u32;
/// Draw number of instances
pub type InstanceCount = u32;
/// Index of a uniform block.
pub type UniformBlockIndex = u8;
/// Slot for an attribute.
pub type AttributeSlot = u8;
/// Slot for a uniform buffer object.
pub type UniformBufferSlot = u8;
/// Slot a texture can be bound to.
pub type TextureSlot = u8;

/// Generic error for features that are not supported
/// by the device capabilities.
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct NotSupported;

/// Treat a given slice as `&[u8]` for the given function call
pub fn as_byte_slice<T>(slice: &[T]) -> &[u8] {
    use std::slice;
    let len = mem::size_of::<T>() * slice.len();
    unsafe {
        slice::from_raw_parts(slice.as_ptr() as *const u8, len)
    }
}

/// Features that the device supports.
#[derive(Copy, Clone, Debug)]
#[allow(missing_docs)] // pretty self-explanatory fields!
pub struct Capabilities {
    pub shader_model: shade::ShaderModel,

    pub max_vertex_count: usize,
    pub max_index_count: usize,
    pub max_draw_buffers: usize,
    pub max_texture_size: usize,
    pub max_vertex_attributes: usize,

    /// In GLES it is not allowed to re-bind a buffer to a different
    /// target than the one it was initialized with.
    pub buffer_role_change_allowed: bool,

    pub array_buffer_supported: bool,
    pub fragment_output_supported: bool,
    pub immutable_storage_supported: bool,
    pub instance_base_supported: bool,
    pub instance_call_supported: bool,
    pub instance_rate_supported: bool,
    pub render_targets_supported: bool,
    pub sampler_objects_supported: bool,
    pub srgb_color_supported: bool,
    pub uniform_block_supported: bool,
    pub vertex_base_supported: bool,
}

/// Specifies the access allowed to a buffer mapping.
#[derive(Copy, Clone)]
pub enum MapAccess {
    /// Only allow reads.
    Readable,
    /// Only allow writes.
    Writable,
    /// Allow full access.
    RW
}

/// Describes what geometric primitives are created from vertex data.
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum PrimitiveType {
    /// Each vertex represents a single point.
    Point,
    /// Each pair of vertices represent a single line segment. For example, with `[a, b, c, d,
    /// e]`, `a` and `b` form a line, `c` and `d` form a line, and `e` is discarded.
    Line,
    /// Every two consecutive vertices represent a single line segment. Visually forms a "path" of
    /// lines, as they are all connected. For example, with `[a, b, c]`, `a` and `b` form a line
    /// line, and `b` and `c` form a line.
    LineStrip,
    /// Each triplet of vertices represent a single triangle. For example, with `[a, b, c, d, e]`,
    /// `a`, `b`, and `c` form a triangle, `d` and `e` are discarded.
    TriangleList,
    /// Every three consecutive vertices represent a single triangle. For example, with `[a, b, c,
    /// d]`, `a`, `b`, and `c` form a triangle, and `b`, `c`, and `d` form a triangle.
    TriangleStrip,
    /// The first vertex with the last two are forming a triangle. For example, with `[a, b, c, d
    /// ]`, `a` , `b`, and `c` form a triangle, and `a`, `c`, and `d` form a triangle.
    TriangleFan,
    //Quad,
}

/// A type of each index value in the mesh's index buffer
pub type IndexType = attrib::IntSize;

/// Role of the memory buffer. GLES doesn't chaning bind points for buffers.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
#[repr(u8)]
pub enum BufferRole {
    /// Generic vertex buffer
    Vertex,
    /// Index buffer
    Index,
    /// Uniform block buffer
    Uniform,
}

/// A hint as to how this buffer will be used.
///
/// The nature of these hints make them very implementation specific. Different drivers on
/// different hardware will handle them differently. Only careful profiling will tell which is the
/// best to use for a specific buffer.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
#[repr(u8)]
pub enum BufferUsage {
    /// Once uploaded, this buffer will rarely change, but will be read from often.
    Static,
    /// This buffer will be updated "frequently", and will be read from multiple times between
    /// updates.
    Dynamic,
    /// This buffer always or almost always be updated after each read.
    Stream,
}

/// An information block that is immutable and associated with each buffer
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct BufferInfo {
    /// Role
    pub role: BufferRole,
    /// Usage hint
    pub usage: BufferUsage,
    /// Size in bytes
    pub size: usize,
}

/// An error happening on buffer updates.
#[derive(Clone, PartialEq, Debug)]
pub enum BufferUpdateError {
    /// Trying to change the contents outside of the allocation.
    OutOfBounds,
}

/// Resources pertaining to a specific API.
#[allow(missing_docs)]
pub trait Resources:           Clone + Hash + fmt::Debug + Eq + PartialEq {
    type Buffer:        Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync;
    type ArrayBuffer:   Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync;
    type Shader:        Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync;
    type Program:       Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync;
    type FrameBuffer:   Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync;
    type Surface:       Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync;
    type Texture:       Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync;
    type Sampler:       Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync;
    type Fence:         Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync;
}

#[allow(missing_docs)]
pub trait Factory<R: Resources> {
    /// Associated mapper type
    type Mapper: Clone + mapping::Raw;

    /// Returns the capabilities available to the specific API implementation
    fn get_capabilities<'a>(&'a self) -> &'a Capabilities;

    // resource creation
    fn create_buffer_raw(&mut self, size: usize, BufferRole, BufferUsage) -> handle::RawBuffer<R>;
    fn create_buffer_static_raw(&mut self, data: &[u8], BufferRole) -> handle::RawBuffer<R>;
    fn create_buffer_static<T>(&mut self, data: &[T], role: BufferRole) -> handle::Buffer<R, T> {
        handle::Buffer::from_raw(
            self.create_buffer_static_raw(as_byte_slice(data), role))
    }
    fn create_buffer_dynamic<T>(&mut self, num: usize, role: BufferRole) -> handle::Buffer<R, T> {
        handle::Buffer::from_raw(
            self.create_buffer_raw(num * mem::size_of::<T>(), role, BufferUsage::Stream))
    }

    fn create_array_buffer(&mut self) -> Result<handle::ArrayBuffer<R>, NotSupported>;
    fn create_shader(&mut self, stage: shade::Stage, code: &[u8]) ->
                     Result<handle::Shader<R>, shade::CreateShaderError>;
    fn create_program(&mut self, shaders: &[handle::Shader<R>], targets: Option<&[&str]>)
                      -> Result<handle::Program<R>, shade::CreateProgramError>;
    fn create_frame_buffer(&mut self) -> Result<handle::FrameBuffer<R>, NotSupported>;
    fn create_surface(&mut self, tex::SurfaceInfo) -> Result<handle::Surface<R>, tex::SurfaceError>;
    fn create_texture(&mut self, tex::TextureInfo) -> Result<handle::Texture<R>, tex::TextureError>;
    fn create_sampler(&mut self, tex::SamplerInfo) -> handle::Sampler<R>;

    /// Update the information stored in a specific buffer
    fn update_buffer_raw(&mut self, buf: &handle::RawBuffer<R>, data: &[u8], offset_bytes: usize)
                         -> Result<(), BufferUpdateError>;
    fn update_buffer<T>(&mut self, buf: &handle::Buffer<R, T>, data: &[T], offset_elements: usize)
                        -> Result<(), BufferUpdateError> {
        self.update_buffer_raw(buf.raw(), as_byte_slice(data), mem::size_of::<T>() * offset_elements)
    }
    fn map_buffer_raw(&mut self, &handle::RawBuffer<R>, MapAccess) -> Self::Mapper;
    fn unmap_buffer_raw(&mut self, Self::Mapper);
    fn map_buffer_readable<T: Copy>(&mut self, &handle::Buffer<R, T>) -> mapping::Readable<T, R, Self>;
    fn map_buffer_writable<T: Copy>(&mut self, &handle::Buffer<R, T>) -> mapping::Writable<T, R, Self>;
    fn map_buffer_rw<T: Copy>(&mut self, &handle::Buffer<R, T>) -> mapping::RW<T, R, Self>;

    /// Update the information stored in a texture
    fn update_texture_raw(&mut self, tex: &handle::Texture<R>,
                          img: &tex::ImageInfo, data: &[u8],
                          kind: Option<tex::Kind>) -> Result<(), tex::TextureError>;

    fn update_texture<T>(&mut self, tex: &handle::Texture<R>,
                         img: &tex::ImageInfo, data: &[T],
                         kind: Option<tex::Kind>) -> Result<(), tex::TextureError> {
        self.update_texture_raw(tex, img, as_byte_slice(data), kind)
    }

    fn generate_mipmap(&mut self, &handle::Texture<R>);

    /// Create a new texture with given data
    fn create_texture_static<T>(&mut self, info: tex::TextureInfo, data: &[T])
                             -> Result<handle::Texture<R>, tex::TextureError> {
        let image_info = info.into();
        match self.create_texture(info) {
            Ok(handle) => self.update_texture(&handle, &image_info, data, None)
                              .map(|_| handle),
            Err(e) => Err(e),
        }
    }
}

/// All the data needed simultaneously for submitting a command buffer for
/// execution on a device.
pub type SubmitInfo<'a, D: Device> = (
    &'a D::CommandBuffer,
    &'a draw::DataBuffer,
    &'a handle::Manager<D::Resources>
);

/// An interface for performing draw calls using a specific graphics API
pub trait Device {
    /// Associated resources type.
    type Resources: Resources;
    /// Associated command buffer type.
    type CommandBuffer: draw::CommandBuffer<Self::Resources>;

    /// Returns the capabilities available to the specific API implementation.
    fn get_capabilities<'a>(&'a self) -> &'a Capabilities;

    /// Reset all the states to disabled/default.
    fn reset_state(&mut self);

    /// Submit a command buffer for execution.
    fn submit(&mut self, SubmitInfo<Self>);

    /// Cleanup unused resources, to be called between frames.
    fn cleanup(&mut self);
}

/// Extension to the Device that allows for submitting of commands
/// around a fence
pub trait DeviceFence<R: Resources>: Device<Resources=R> {
    /// Submit a command buffer to the stream creating a fence
    /// the fence is signaled after the GPU has executed all commands
    /// in the buffer
    fn fenced_submit(&mut self, SubmitInfo<Self>, after: Option<handle::Fence<R>>) -> handle::Fence<R>;

    /// Wait on the supplied fence stalling the current thread until
    /// the fence is satisfied
    fn fence_wait(&mut self, fence: &handle::Fence<R>);
}
<commit_msg>Auto merge of #795 - csherratt:lifetime, r=csherratt<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![deny(missing_docs)]

//! Graphics device. Not meant for direct use.

use std::{fmt, mem};
use std::hash::Hash;

pub use draw_state::target;
pub use draw_state::state;

pub mod attrib;
pub mod command;
pub mod draw;
pub mod dummy;
pub mod handle;
pub mod mapping;
pub mod shade;
pub mod tex;

mod arc;

/// Draw vertex count.
pub type VertexCount = u32;
/// Draw number of instances
pub type InstanceCount = u32;
/// Index of a uniform block.
pub type UniformBlockIndex = u8;
/// Slot for an attribute.
pub type AttributeSlot = u8;
/// Slot for a uniform buffer object.
pub type UniformBufferSlot = u8;
/// Slot a texture can be bound to.
pub type TextureSlot = u8;

/// Generic error for features that are not supported
/// by the device capabilities.
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct NotSupported;

/// Treat a given slice as `&[u8]` for the given function call
pub fn as_byte_slice<T>(slice: &[T]) -> &[u8] {
    use std::slice;
    let len = mem::size_of::<T>() * slice.len();
    unsafe {
        slice::from_raw_parts(slice.as_ptr() as *const u8, len)
    }
}

/// Features that the device supports.
#[derive(Copy, Clone, Debug)]
#[allow(missing_docs)] // pretty self-explanatory fields!
pub struct Capabilities {
    pub shader_model: shade::ShaderModel,

    pub max_vertex_count: usize,
    pub max_index_count: usize,
    pub max_draw_buffers: usize,
    pub max_texture_size: usize,
    pub max_vertex_attributes: usize,

    /// In GLES it is not allowed to re-bind a buffer to a different
    /// target than the one it was initialized with.
    pub buffer_role_change_allowed: bool,

    pub array_buffer_supported: bool,
    pub fragment_output_supported: bool,
    pub immutable_storage_supported: bool,
    pub instance_base_supported: bool,
    pub instance_call_supported: bool,
    pub instance_rate_supported: bool,
    pub render_targets_supported: bool,
    pub sampler_objects_supported: bool,
    pub srgb_color_supported: bool,
    pub uniform_block_supported: bool,
    pub vertex_base_supported: bool,
}

/// Specifies the access allowed to a buffer mapping.
#[derive(Copy, Clone)]
pub enum MapAccess {
    /// Only allow reads.
    Readable,
    /// Only allow writes.
    Writable,
    /// Allow full access.
    RW
}

/// Describes what geometric primitives are created from vertex data.
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum PrimitiveType {
    /// Each vertex represents a single point.
    Point,
    /// Each pair of vertices represent a single line segment. For example, with `[a, b, c, d,
    /// e]`, `a` and `b` form a line, `c` and `d` form a line, and `e` is discarded.
    Line,
    /// Every two consecutive vertices represent a single line segment. Visually forms a "path" of
    /// lines, as they are all connected. For example, with `[a, b, c]`, `a` and `b` form a line
    /// line, and `b` and `c` form a line.
    LineStrip,
    /// Each triplet of vertices represent a single triangle. For example, with `[a, b, c, d, e]`,
    /// `a`, `b`, and `c` form a triangle, `d` and `e` are discarded.
    TriangleList,
    /// Every three consecutive vertices represent a single triangle. For example, with `[a, b, c,
    /// d]`, `a`, `b`, and `c` form a triangle, and `b`, `c`, and `d` form a triangle.
    TriangleStrip,
    /// The first vertex with the last two are forming a triangle. For example, with `[a, b, c, d
    /// ]`, `a` , `b`, and `c` form a triangle, and `a`, `c`, and `d` form a triangle.
    TriangleFan,
    //Quad,
}

/// A type of each index value in the mesh's index buffer
pub type IndexType = attrib::IntSize;

/// Role of the memory buffer. GLES doesn't chaning bind points for buffers.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
#[repr(u8)]
pub enum BufferRole {
    /// Generic vertex buffer
    Vertex,
    /// Index buffer
    Index,
    /// Uniform block buffer
    Uniform,
}

/// A hint as to how this buffer will be used.
///
/// The nature of these hints make them very implementation specific. Different drivers on
/// different hardware will handle them differently. Only careful profiling will tell which is the
/// best to use for a specific buffer.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
#[repr(u8)]
pub enum BufferUsage {
    /// Once uploaded, this buffer will rarely change, but will be read from often.
    Static,
    /// This buffer will be updated "frequently", and will be read from multiple times between
    /// updates.
    Dynamic,
    /// This buffer always or almost always be updated after each read.
    Stream,
}

/// An information block that is immutable and associated with each buffer
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct BufferInfo {
    /// Role
    pub role: BufferRole,
    /// Usage hint
    pub usage: BufferUsage,
    /// Size in bytes
    pub size: usize,
}

/// An error happening on buffer updates.
#[derive(Clone, PartialEq, Debug)]
pub enum BufferUpdateError {
    /// Trying to change the contents outside of the allocation.
    OutOfBounds,
}

/// Resources pertaining to a specific API.
#[allow(missing_docs)]
pub trait Resources:           Clone + Hash + fmt::Debug + Eq + PartialEq {
    type Buffer:        Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync + 'static;
    type ArrayBuffer:   Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync + 'static;
    type Shader:        Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync + 'static;
    type Program:       Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync + 'static;
    type FrameBuffer:   Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync + 'static;
    type Surface:       Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync + 'static;
    type Texture:       Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync + 'static;
    type Sampler:       Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync + 'static;
    type Fence:         Copy + Clone + Hash + fmt::Debug + Eq + PartialEq + Send + Sync + 'static;
}

#[allow(missing_docs)]
pub trait Factory<R: Resources> {
    /// Associated mapper type
    type Mapper: Clone + mapping::Raw;

    /// Returns the capabilities available to the specific API implementation
    fn get_capabilities<'a>(&'a self) -> &'a Capabilities;

    // resource creation
    fn create_buffer_raw(&mut self, size: usize, BufferRole, BufferUsage) -> handle::RawBuffer<R>;
    fn create_buffer_static_raw(&mut self, data: &[u8], BufferRole) -> handle::RawBuffer<R>;
    fn create_buffer_static<T>(&mut self, data: &[T], role: BufferRole) -> handle::Buffer<R, T> {
        handle::Buffer::from_raw(
            self.create_buffer_static_raw(as_byte_slice(data), role))
    }
    fn create_buffer_dynamic<T>(&mut self, num: usize, role: BufferRole) -> handle::Buffer<R, T> {
        handle::Buffer::from_raw(
            self.create_buffer_raw(num * mem::size_of::<T>(), role, BufferUsage::Stream))
    }

    fn create_array_buffer(&mut self) -> Result<handle::ArrayBuffer<R>, NotSupported>;
    fn create_shader(&mut self, stage: shade::Stage, code: &[u8]) ->
                     Result<handle::Shader<R>, shade::CreateShaderError>;
    fn create_program(&mut self, shaders: &[handle::Shader<R>], targets: Option<&[&str]>)
                      -> Result<handle::Program<R>, shade::CreateProgramError>;
    fn create_frame_buffer(&mut self) -> Result<handle::FrameBuffer<R>, NotSupported>;
    fn create_surface(&mut self, tex::SurfaceInfo) -> Result<handle::Surface<R>, tex::SurfaceError>;
    fn create_texture(&mut self, tex::TextureInfo) -> Result<handle::Texture<R>, tex::TextureError>;
    fn create_sampler(&mut self, tex::SamplerInfo) -> handle::Sampler<R>;

    /// Update the information stored in a specific buffer
    fn update_buffer_raw(&mut self, buf: &handle::RawBuffer<R>, data: &[u8], offset_bytes: usize)
                         -> Result<(), BufferUpdateError>;
    fn update_buffer<T>(&mut self, buf: &handle::Buffer<R, T>, data: &[T], offset_elements: usize)
                        -> Result<(), BufferUpdateError> {
        self.update_buffer_raw(buf.raw(), as_byte_slice(data), mem::size_of::<T>() * offset_elements)
    }
    fn map_buffer_raw(&mut self, &handle::RawBuffer<R>, MapAccess) -> Self::Mapper;
    fn unmap_buffer_raw(&mut self, Self::Mapper);
    fn map_buffer_readable<T: Copy>(&mut self, &handle::Buffer<R, T>) -> mapping::Readable<T, R, Self>;
    fn map_buffer_writable<T: Copy>(&mut self, &handle::Buffer<R, T>) -> mapping::Writable<T, R, Self>;
    fn map_buffer_rw<T: Copy>(&mut self, &handle::Buffer<R, T>) -> mapping::RW<T, R, Self>;

    /// Update the information stored in a texture
    fn update_texture_raw(&mut self, tex: &handle::Texture<R>,
                          img: &tex::ImageInfo, data: &[u8],
                          kind: Option<tex::Kind>) -> Result<(), tex::TextureError>;

    fn update_texture<T>(&mut self, tex: &handle::Texture<R>,
                         img: &tex::ImageInfo, data: &[T],
                         kind: Option<tex::Kind>) -> Result<(), tex::TextureError> {
        self.update_texture_raw(tex, img, as_byte_slice(data), kind)
    }

    fn generate_mipmap(&mut self, &handle::Texture<R>);

    /// Create a new texture with given data
    fn create_texture_static<T>(&mut self, info: tex::TextureInfo, data: &[T])
                             -> Result<handle::Texture<R>, tex::TextureError> {
        let image_info = info.into();
        match self.create_texture(info) {
            Ok(handle) => self.update_texture(&handle, &image_info, data, None)
                              .map(|_| handle),
            Err(e) => Err(e),
        }
    }
}

/// All the data needed simultaneously for submitting a command buffer for
/// execution on a device.
pub type SubmitInfo<'a, D: Device> = (
    &'a D::CommandBuffer,
    &'a draw::DataBuffer,
    &'a handle::Manager<D::Resources>
);

/// An interface for performing draw calls using a specific graphics API
pub trait Device {
    /// Associated resources type.
    type Resources: Resources;
    /// Associated command buffer type.
    type CommandBuffer: draw::CommandBuffer<Self::Resources>;

    /// Returns the capabilities available to the specific API implementation.
    fn get_capabilities<'a>(&'a self) -> &'a Capabilities;

    /// Reset all the states to disabled/default.
    fn reset_state(&mut self);

    /// Submit a command buffer for execution.
    fn submit(&mut self, SubmitInfo<Self>);

    /// Cleanup unused resources, to be called between frames.
    fn cleanup(&mut self);
}

/// Extension to the Device that allows for submitting of commands
/// around a fence
pub trait DeviceFence<R: Resources>: Device<Resources=R> {
    /// Submit a command buffer to the stream creating a fence
    /// the fence is signaled after the GPU has executed all commands
    /// in the buffer
    fn fenced_submit(&mut self, SubmitInfo<Self>, after: Option<handle::Fence<R>>) -> handle::Fence<R>;

    /// Wait on the supplied fence stalling the current thread until
    /// the fence is satisfied
    fn fence_wait(&mut self, fence: &handle::Fence<R>);
}
<|endoftext|>


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

use std::rc::Rc;
use std::iter::FromIterator;
use syntax::ast;
use syntax::ptr::P;
use syntax::ast_util::empty_generics;
use syntax::codemap::{DUMMY_SP, dummy_spanned};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::parse::token;

use node;
use super::Builder;
use super::utils;

enum RegOrPadding<'a> {
  /// A register
  Reg(&'a node::Reg),
  /// A given number of bytes of padding
  Pad(uint)
}

/// An iterator which takes a potentially unsorted list of registers,
/// sorts them, and adds padding to make offsets correct
struct PaddedRegsIterator<'a> {
  sorted_regs: &'a Vec<node::Reg>,
  index: uint,
  last_offset: uint,
}

impl<'a> PaddedRegsIterator<'a> {
  fn new(regs: &'a mut Vec<node::Reg>) -> PaddedRegsIterator<'a> {
    regs.sort_by(|r1,r2| r1.offset.cmp(&r2.offset));
    PaddedRegsIterator {
      sorted_regs: regs,
      index: 0,
      last_offset: 0,
    }
  }
}

impl<'a> Iterator<RegOrPadding<'a>> for PaddedRegsIterator<'a> {
  fn next(&mut self) -> Option<RegOrPadding<'a>> {
    if self.index >= self.sorted_regs.len() {
      None
    } else {
      let ref reg = self.sorted_regs[self.index];
      if reg.offset > self.last_offset {
        let pad_length = reg.offset - self.last_offset;
        self.last_offset = reg.offset + reg.size();
        Some(Pad(pad_length))
      } else {
        self.index += 1;
        self.last_offset += reg.size();
        Some(Reg(reg))
      }
    }
  }
}

/// Build types for `RegUnions`
pub struct BuildUnionTypes<'a> {
  builder: &'a mut Builder,
  cx: &'a ExtCtxt<'a>
}

impl<'a> BuildUnionTypes<'a> {
  pub fn new(builder: &'a mut Builder, cx: &'a ExtCtxt<'a>)
      -> BuildUnionTypes<'a> {
    BuildUnionTypes { builder: builder, cx: cx }
  }
}

/// Returns the type of the field representing the given register
/// within a `RegGroup` struct
fn reg_struct_type(cx: &ExtCtxt, path: &Vec<String>, reg: &node::Reg)
                   -> P<ast::Ty> {
  let base_ty_path = cx.path_ident(DUMMY_SP, utils::path_ident(cx, path));
  let base_ty: P<ast::Ty> = cx.ty_path(base_ty_path, None);
  match reg.count.node {
    1 => base_ty,
    n =>
      cx.ty(DUMMY_SP,
            ast::TyFixedLengthVec(base_ty,
                                  cx.expr_uint(DUMMY_SP, n))),
  }
}

impl<'a> node::RegVisitor for BuildUnionTypes<'a> {
  fn visit_union_reg<'a>(&'a mut self, path: &Vec<String>, reg: &'a node::Reg,
                         subregs: Rc<Vec<node::Reg>>) {
    let union_type = self.build_union_type(path, reg, &*subregs);
    self.builder.push_item(union_type);
  }
}

impl<'a> BuildUnionTypes<'a> {
  /// Produce a field for the given register in a `RegUnion` struct
  fn build_reg_union_field(&self, path: &Vec<String>, reg: &node::Reg)
                           -> ast::StructField {
    let attrs = match reg.docstring {
      Some(doc) => vec!(utils::doc_attribute(self.cx, token::get_ident(doc.node))),
      None => Vec::new(),
    };
    let mut field_path = path.clone();
    field_path.push(reg.name.node.clone());
    dummy_spanned(
      ast::StructField_ {
        kind: ast::NamedField(
          self.cx.ident_of(reg.name.node.as_slice()),
          ast::Public),
        id: ast::DUMMY_NODE_ID,
        ty: reg_struct_type(self.cx, &field_path, reg),
        attrs: attrs,
      }
    )
  }

  /// Build field for padding or a register
  fn build_pad_or_reg(&self, path: &Vec<String>, reg_or_pad: RegOrPadding,
                      index: uint) -> ast::StructField {
    match reg_or_pad {
      Reg(reg) => self.build_reg_union_field(path, reg),
      Pad(length) => {
        let u8_path = self.cx.path_ident(
          DUMMY_SP,
          self.cx.ident_of("u8"));
        let u8_ty: P<ast::Ty> = self.cx.ty_path(u8_path, None);
        let ty: P<ast::Ty> =
          self.cx.ty(
            DUMMY_SP,
            ast::TyFixedLengthVec(u8_ty,
                                  self.cx.expr_uint(DUMMY_SP, length)));
        dummy_spanned(
          ast::StructField_ {
            kind: ast::NamedField(
              self.cx.ident_of(format!("_pad{}", index).as_slice()),
              ast::Inherited),
            id: ast::DUMMY_NODE_ID,
            ty: ty,
            attrs: Vec::new(),
          },
        )
      },
    }
  }

  /// Build the type associated with a register group
  fn build_union_type(&self, path: &Vec<String>, reg: &node::Reg,
                      regs: &Vec<node::Reg>) -> P<ast::Item> {
    let name = String::from_str(
        token::get_ident(utils::path_ident(self.cx, path)).get());
    // Registers are already sorted by parser
    let mut regs = regs.clone();
    let padded_regs = PaddedRegsIterator::new(&mut regs);
    let fields =
      padded_regs.enumerate().map(|(n,r)| self.build_pad_or_reg(path, r, n));
    let struct_def = ast::StructDef {
      fields: FromIterator::from_iter(fields),
      ctor_id: None,
    };
    let mut attrs: Vec<ast::Attribute> = vec!(
      utils::list_attribute(self.cx, "allow",
                            vec!("non_camel_case_types",
                                 "dead_code",
                                 "missing_doc")),
    );
    match reg.docstring {
      Some(docstring) =>
        attrs.push(
          utils::doc_attribute(self.cx, token::get_ident(docstring.node))),
      None => (),
    }
    P(ast::Item {
      ident: self.cx.ident_of(name.as_slice()),
      attrs: attrs,
      id: ast::DUMMY_NODE_ID,
      node: ast::ItemStruct(P(struct_def), empty_generics()),
      vis: ast::Public,
      span: reg.name.span,
    })
  }
}
<commit_msg>ioreg: Fix incorrect calculation of gaps<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Ben Gamari <bgamari@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::rc::Rc;
use std::iter::FromIterator;
use syntax::ast;
use syntax::ptr::P;
use syntax::ast_util::empty_generics;
use syntax::codemap::{DUMMY_SP, dummy_spanned};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::parse::token;

use node;
use super::Builder;
use super::utils;

enum RegOrPadding<'a> {
  /// A register
  Reg(&'a node::Reg),
  /// A given number of bytes of padding
  Pad(uint)
}

/// An iterator which takes a potentially unsorted list of registers,
/// sorts them, and adds padding to make offsets correct
struct PaddedRegsIterator<'a> {
  sorted_regs: &'a Vec<node::Reg>,
  index: uint,
  last_offset: uint,
}

impl<'a> PaddedRegsIterator<'a> {
  fn new(regs: &'a mut Vec<node::Reg>) -> PaddedRegsIterator<'a> {
    regs.sort_by(|r1,r2| r1.offset.cmp(&r2.offset));
    PaddedRegsIterator {
      sorted_regs: regs,
      index: 0,
      last_offset: 0,
    }
  }
}

impl<'a> Iterator<RegOrPadding<'a>> for PaddedRegsIterator<'a> {
  fn next(&mut self) -> Option<RegOrPadding<'a>> {
    if self.index >= self.sorted_regs.len() {
      None
    } else {
      let ref reg = self.sorted_regs[self.index];
      if reg.offset > self.last_offset {
        let pad_length = reg.offset - self.last_offset;
        self.last_offset = reg.offset;
        Some(Pad(pad_length))
      } else {
        self.index += 1;
        self.last_offset += reg.size();
        Some(Reg(reg))
      }
    }
  }
}

/// Build types for `RegUnions`
pub struct BuildUnionTypes<'a> {
  builder: &'a mut Builder,
  cx: &'a ExtCtxt<'a>
}

impl<'a> BuildUnionTypes<'a> {
  pub fn new(builder: &'a mut Builder, cx: &'a ExtCtxt<'a>)
      -> BuildUnionTypes<'a> {
    BuildUnionTypes { builder: builder, cx: cx }
  }
}

/// Returns the type of the field representing the given register
/// within a `RegGroup` struct
fn reg_struct_type(cx: &ExtCtxt, path: &Vec<String>, reg: &node::Reg)
                   -> P<ast::Ty> {
  let base_ty_path = cx.path_ident(DUMMY_SP, utils::path_ident(cx, path));
  let base_ty: P<ast::Ty> = cx.ty_path(base_ty_path, None);
  match reg.count.node {
    1 => base_ty,
    n =>
      cx.ty(DUMMY_SP,
            ast::TyFixedLengthVec(base_ty,
                                  cx.expr_uint(DUMMY_SP, n))),
  }
}

impl<'a> node::RegVisitor for BuildUnionTypes<'a> {
  fn visit_union_reg<'a>(&'a mut self, path: &Vec<String>, reg: &'a node::Reg,
                         subregs: Rc<Vec<node::Reg>>) {
    let union_type = self.build_union_type(path, reg, &*subregs);
    self.builder.push_item(union_type);
  }
}

impl<'a> BuildUnionTypes<'a> {
  /// Produce a field for the given register in a `RegUnion` struct
  fn build_reg_union_field(&self, path: &Vec<String>, reg: &node::Reg)
                           -> ast::StructField {
    let attrs = match reg.docstring {
      Some(doc) => vec!(utils::doc_attribute(self.cx, token::get_ident(doc.node))),
      None => Vec::new(),
    };
    let mut field_path = path.clone();
    field_path.push(reg.name.node.clone());
    dummy_spanned(
      ast::StructField_ {
        kind: ast::NamedField(
          self.cx.ident_of(reg.name.node.as_slice()),
          ast::Public),
        id: ast::DUMMY_NODE_ID,
        ty: reg_struct_type(self.cx, &field_path, reg),
        attrs: attrs,
      }
    )
  }

  /// Build field for padding or a register
  fn build_pad_or_reg(&self, path: &Vec<String>, reg_or_pad: RegOrPadding,
                      index: uint) -> ast::StructField {
    match reg_or_pad {
      Reg(reg) => self.build_reg_union_field(path, reg),
      Pad(length) => {
        let u8_path = self.cx.path_ident(
          DUMMY_SP,
          self.cx.ident_of("u8"));
        let u8_ty: P<ast::Ty> = self.cx.ty_path(u8_path, None);
        let ty: P<ast::Ty> =
          self.cx.ty(
            DUMMY_SP,
            ast::TyFixedLengthVec(u8_ty,
                                  self.cx.expr_uint(DUMMY_SP, length)));
        dummy_spanned(
          ast::StructField_ {
            kind: ast::NamedField(
              self.cx.ident_of(format!("_pad{}", index).as_slice()),
              ast::Inherited),
            id: ast::DUMMY_NODE_ID,
            ty: ty,
            attrs: Vec::new(),
          },
        )
      },
    }
  }

  /// Build the type associated with a register group
  fn build_union_type(&self, path: &Vec<String>, reg: &node::Reg,
                      regs: &Vec<node::Reg>) -> P<ast::Item> {
    let name = String::from_str(
        token::get_ident(utils::path_ident(self.cx, path)).get());
    // Registers are already sorted by parser
    let mut regs = regs.clone();
    let padded_regs = PaddedRegsIterator::new(&mut regs);
    let fields =
      padded_regs.enumerate().map(|(n,r)| self.build_pad_or_reg(path, r, n));
    let struct_def = ast::StructDef {
      fields: FromIterator::from_iter(fields),
      ctor_id: None,
    };
    let mut attrs: Vec<ast::Attribute> = vec!(
      utils::list_attribute(self.cx, "allow",
                            vec!("non_camel_case_types",
                                 "dead_code",
                                 "missing_doc")),
    );
    match reg.docstring {
      Some(docstring) =>
        attrs.push(
          utils::doc_attribute(self.cx, token::get_ident(docstring.node))),
      None => (),
    }
    P(ast::Item {
      ident: self.cx.ident_of(name.as_slice()),
      attrs: attrs,
      id: ast::DUMMY_NODE_ID,
      node: ast::ItemStruct(P(struct_def), empty_generics()),
      vis: ast::Public,
      span: reg.name.span,
    })
  }
}
<|endoftext|>


<commit_before>//! 32-bit specific definitions for linux-like values on platforms that aren't
//! MIPS or android

pub type blkcnt_t = i32;
pub type blksize_t = i32;
pub type dev_t = u64;
pub type mode_t = u32;
pub type nlink_t = u32;

s! {
    pub struct stat {
        pub st_dev: dev_t,
        __pad1: c_short,
        pub st_ino: ino_t,
        pub st_mode: mode_t,
        pub st_nlink: nlink_t,
        pub st_uid: uid_t,
        pub st_gid: gid_t,
        pub st_rdev: dev_t,
        __pad2: c_short,
        pub st_size: off_t,
        pub st_blksize: blksize_t,
        pub st_blocks: blkcnt_t,
        pub st_atime: time_t,
        pub st_atime_nsec: c_long,
        pub st_mtime: time_t,
        pub st_mtime_nsec: c_long,
        pub st_ctime: time_t,
        pub st_ctime_nsec: c_long,
        __unused4: c_long,
        __unused5: c_long,
    }

    pub struct pthread_attr_t {
        __size: [u32; 9]
    }
}
<commit_msg>Fix compile on linux-32<commit_after>//! 32-bit specific definitions for linux-like values on platforms that aren't
//! MIPS or android

pub type blkcnt_t = i32;
pub type blksize_t = i32;
pub type dev_t = u64;
pub type mode_t = u32;
pub type nlink_t = u32;

s! {
    pub struct stat {
        pub st_dev: ::dev_t,
        __pad1: ::c_short,
        pub st_ino: ::ino_t,
        pub st_mode: ::mode_t,
        pub st_nlink: ::nlink_t,
        pub st_uid: ::uid_t,
        pub st_gid: ::gid_t,
        pub st_rdev: ::dev_t,
        __pad2: ::c_short,
        pub st_size: ::off_t,
        pub st_blksize: ::blksize_t,
        pub st_blocks: ::blkcnt_t,
        pub st_atime: ::time_t,
        pub st_atime_nsec: ::c_long,
        pub st_mtime: ::time_t,
        pub st_mtime_nsec: ::c_long,
        pub st_ctime: ::time_t,
        pub st_ctime_nsec: ::c_long,
        __unused4: ::c_long,
        __unused5: ::c_long,
    }

    pub struct pthread_attr_t {
        __size: [u32; 9]
    }
}
<|endoftext|>


<commit_before>use std::iter::repeat;

use graph::{Graph, Edge};
use bit_vector::BitVector;

// maximal_independent_set processes vertices in order and returns the resulting maximal independent
// set in g.
pub fn maximal_independent_set(g: &Graph, vertices: &Vec<usize>) -> Vec<usize> {
    let mut adjacency_list: Vec<_> = repeat(BitVector::new()).take(g.vertex_count).collect();
    for &Edge { x, y } in &g.edges {
        adjacency_list[x].set(y);
        adjacency_list[y].set(x);
    }

    let mut maximal_set = BitVector::new();
    for &x in vertices {
        let neighbors = &adjacency_list[x];
        if maximal_set.intersect(&neighbors).is_empty() {
            // x is not adjacent to any set vertices. This means x is eligible to join the set.
            maximal_set.set(x)
        }
    }

    maximal_set.to_vec()
}

// maximum_independent_set returns an independent set that is hopefully the maximum independent set
// in g.
pub fn maximum_independent_set(g: &Graph) -> Vec<usize> {
    let mut degrees: Vec<_> = vec![0; g.vertex_count];
    for &Edge { x, y } in &g.edges {
        degrees[x] += 1;
        degrees[y] += 1;
    }

    let mut vertices_sorted_by_increasing_degree: Vec<_> = (0..g.vertex_count).collect();
    vertices_sorted_by_increasing_degree.sort_by(|&x, &y| degrees[x].cmp(&degrees[y]));

    maximal_independent_set(g, &vertices_sorted_by_increasing_degree)
}
<commit_msg>[independent_set/rust] Remove unneeded type declaration<commit_after>use std::iter::repeat;

use graph::{Graph, Edge};
use bit_vector::BitVector;

// maximal_independent_set processes vertices in order and returns the resulting maximal independent
// set in g.
pub fn maximal_independent_set(g: &Graph, vertices: &Vec<usize>) -> Vec<usize> {
    let mut adjacency_list: Vec<_> = repeat(BitVector::new()).take(g.vertex_count).collect();
    for &Edge { x, y } in &g.edges {
        adjacency_list[x].set(y);
        adjacency_list[y].set(x);
    }

    let mut maximal_set = BitVector::new();
    for &x in vertices {
        let neighbors = &adjacency_list[x];
        if maximal_set.intersect(&neighbors).is_empty() {
            // x is not adjacent to any set vertices. This means x is eligible to join the set.
            maximal_set.set(x)
        }
    }

    maximal_set.to_vec()
}

// maximum_independent_set returns an independent set that is hopefully the maximum independent set
// in g.
pub fn maximum_independent_set(g: &Graph) -> Vec<usize> {
    let mut degrees = vec![0; g.vertex_count];
    for &Edge { x, y } in &g.edges {
        degrees[x] += 1;
        degrees[y] += 1;
    }

    let mut vertices_sorted_by_increasing_degree: Vec<_> = (0..g.vertex_count).collect();
    vertices_sorted_by_increasing_degree.sort_by(|&x, &y| degrees[x].cmp(&degrees[y]));

    maximal_independent_set(g, &vertices_sorted_by_increasing_degree)
}
<|endoftext|>


<commit_before>use memory::paging::entry::*;
use memory::paging::ENTRY_COUNT;
use memory::FrameAllocator;

use core::ops::{Index, IndexMut};
use core::marker::PhantomData;

pub const P4: *mut Table<Level4> = 0xffffffff_fffff000 as *mut _;

pub trait TableLevel {}

pub enum Level4 {}
pub enum Level3 {}
pub enum Level2 {}
pub enum Level1 {}

impl TableLevel for Level4 {}
impl TableLevel for Level3 {}
impl TableLevel for Level2 {}
impl TableLevel for Level1 {}

trait HierarchicalLevel: TableLevel {
    type NextLevel: TableLevel;
}

impl HierarchicalLevel for Level4 {
    type NextLevel = Level3;
}

impl HierarchicalLevel for Level3 {
    type NextLevel = Level2;
}

impl HierarchicalLevel for Level2 {
    type NextLevel = Level1;
}

pub struct Table<L: TableLevel> {
    entries: [Entry; ENTRY_COUNT],
    level: PhantomData<L>,
}

impl<L> Table<L>  where L: TableLevel {
    pub fn zero(&mut self) {
	    for entry in self.entries.iter_mut() {
	        entry.set_unused();
	    }
	}
}

impl<L> Table<L>  where L: HierarchicalLevel {
	pub fn next_table(&self, index: usize) -> Option<&Table<L::NextLevel>> {
	    self.next_table_address(index)
	        .map(|address| unsafe { &*(address as *const _) })
	}

	pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table<L::NextLevel>> {
	    self.next_table_address(index)
	        .map(|address| unsafe { &mut *(address as *mut _) })
	}

	pub fn next_table_create<A>(&mut self, index: usize, allocator: &mut A) -> &mut Table<L::NextLevel>
    	where A: FrameAllocator {
	    if self.next_table(index).is_none() {
	        assert!(!self.entries[index].flags().contains(HUGE_PAGE),
	                "mapping code does not support huge pages");
	        let frame = allocator.allocate_frame().expect("no frames available");
	        self.entries[index].set(frame, PRESENT | WRITABLE);
	        self.next_table_mut(index).unwrap().zero();
	    }
	    self.next_table_mut(index).unwrap()
	}

	fn next_table_address(&self, index: usize) -> Option<usize> {
	    let entry_flags = self[index].flags();
	    if entry_flags.contains(PRESENT) && !entry_flags.contains(HUGE_PAGE) {
	        let table_address = self as *const _ as usize;
	        Some((table_address << 9) | (index << 12))
	    } else {
	        None
	    }
	}
}

impl<L> Index<usize> for Table<L> where L: TableLevel {
    type Output = Entry;

    fn index(&self, index: usize) -> &Entry {
        &self.entries[index]
    }
}

impl<L> IndexMut<usize> for Table<L> where L: TableLevel {
    fn index_mut(&mut self, index: usize) -> &mut Entry {
        &mut self.entries[index]
    }
}
<commit_msg>Fix private trait in public interface errors<commit_after>use memory::paging::entry::*;
use memory::paging::ENTRY_COUNT;
use memory::FrameAllocator;

use core::ops::{Index, IndexMut};
use core::marker::PhantomData;

pub const P4: *mut Table<Level4> = 0xffffffff_fffff000 as *mut _;

pub trait TableLevel {}

pub enum Level4 {}
pub enum Level3 {}
pub enum Level2 {}
pub enum Level1 {}

impl TableLevel for Level4 {}
impl TableLevel for Level3 {}
impl TableLevel for Level2 {}
impl TableLevel for Level1 {}

pub trait HierarchicalLevel: TableLevel {
    type NextLevel: TableLevel;
}

impl HierarchicalLevel for Level4 {
    type NextLevel = Level3;
}

impl HierarchicalLevel for Level3 {
    type NextLevel = Level2;
}

impl HierarchicalLevel for Level2 {
    type NextLevel = Level1;
}

pub struct Table<L: TableLevel> {
    entries: [Entry; ENTRY_COUNT],
    level: PhantomData<L>,
}

impl<L> Table<L>  where L: TableLevel {
    pub fn zero(&mut self) {
	    for entry in self.entries.iter_mut() {
	        entry.set_unused();
	    }
	}
}

impl<L> Table<L>  where L: HierarchicalLevel {
	pub fn next_table(&self, index: usize) -> Option<&Table<L::NextLevel>> {
	    self.next_table_address(index)
	        .map(|address| unsafe { &*(address as *const _) })
	}

	pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table<L::NextLevel>> {
	    self.next_table_address(index)
	        .map(|address| unsafe { &mut *(address as *mut _) })
	}

	pub fn next_table_create<A>(&mut self, index: usize, allocator: &mut A) -> &mut Table<L::NextLevel>
    	where A: FrameAllocator {
	    if self.next_table(index).is_none() {
	        assert!(!self.entries[index].flags().contains(HUGE_PAGE),
	                "mapping code does not support huge pages");
	        let frame = allocator.allocate_frame().expect("no frames available");
	        self.entries[index].set(frame, PRESENT | WRITABLE);
	        self.next_table_mut(index).unwrap().zero();
	    }
	    self.next_table_mut(index).unwrap()
	}

	fn next_table_address(&self, index: usize) -> Option<usize> {
	    let entry_flags = self[index].flags();
	    if entry_flags.contains(PRESENT) && !entry_flags.contains(HUGE_PAGE) {
	        let table_address = self as *const _ as usize;
	        Some((table_address << 9) | (index << 12))
	    } else {
	        None
	    }
	}
}

impl<L> Index<usize> for Table<L> where L: TableLevel {
    type Output = Entry;

    fn index(&self, index: usize) -> &Entry {
        &self.entries[index]
    }
}

impl<L> IndexMut<usize> for Table<L> where L: TableLevel {
    fn index_mut(&mut self, index: usize) -> &mut Entry {
        &mut self.entries[index]
    }
}
<|endoftext|>