<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 num_lib;
use std::cmp::{self, max, min};
use std::fmt;
use std::iter;
use std::marker::PhantomData;
use std::num;
use std::ops;

pub trait Int:
    Copy
    + ops::Add<Self, Output=Self>
    + ops::Sub<Self, Output=Self>
    + cmp::Ord
{
    fn zero() -> Self;
    fn one() -> Self;
    fn max_value() -> Self;
    fn from_usize(n: usize) -> Option<Self>;
}
impl Int for isize {
    fn zero() -> isize { 0 }
    fn one() -> isize { 1 }
    fn max_value() -> isize { ::std::isize::MAX }
    fn from_usize(n: usize) -> Option<isize> { num_lib::NumCast::from(n) }
}
impl Int for usize {
    fn zero() -> usize { 0 }
    fn one() -> usize { 1 }
    fn max_value() -> usize { ::std::usize::MAX }
    fn from_usize(n: usize) -> Option<usize> { Some(n) }
}

/// An index type to be used by a `Range`
pub trait RangeIndex: Int + fmt::Debug {
    type Index;
    fn new(x: Self::Index) -> Self;
    fn get(self) -> Self::Index;
}

impl RangeIndex for isize {
    type Index = isize;
    #[inline]
    fn new(x: isize) -> isize { x }

    #[inline]
    fn get(self) -> isize { self }
}

impl RangeIndex for usize {
    type Index = usize;
    #[inline]
    fn new(x: usize) -> usize { x }

    #[inline]
    fn get(self) -> usize { self }
}

/// Implements a range index type with operator overloads
#[macro_export]
macro_rules! int_range_index {
    ($(#[$attr:meta])* struct $Self_:ident($T:ty)) => (
        #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Debug, Copy)]
        $(#[$attr])*
        pub struct $Self_(pub $T);

        impl $Self_ {
            #[inline]
            pub fn to_usize(self) -> usize {
                self.get() as usize
            }
        }

        impl RangeIndex for $Self_ {
            type Index = $T;
            #[inline]
            fn new(x: $T) -> $Self_ {
                $Self_(x)
            }

            #[inline]
            fn get(self) -> $T {
                match self { $Self_(x) => x }
            }
        }

        impl $crate::range::Int for $Self_ {
            fn zero() -> $Self_ { $Self_($crate::range::Int::zero()) }
            fn one() -> $Self_ { $Self_($crate::range::Int::one()) }
            fn max_value() -> $Self_ { $Self_($crate::range::Int::max_value()) }
            fn from_usize(n: usize) -> Option<$Self_> { $crate::range::Int::from_usize(n).map($Self_) }
        }

        impl ::std::ops::Add<$Self_> for $Self_ {
            type Output = $Self_;

            #[inline]
            fn add(self, other: $Self_) -> $Self_ {
                $Self_(self.get() + other.get())
            }
        }

        impl ::std::ops::Sub<$Self_> for $Self_ {
            type Output = $Self_;

            #[inline]
            fn sub(self, other: $Self_) -> $Self_ {
                $Self_(self.get() - other.get())
            }
        }

        impl ::std::ops::Neg for $Self_ {
            type Output = $Self_;

            #[inline]
            fn neg(self) -> $Self_ {
                $Self_(-self.get())
            }
        }
    )
}

/// A range of indices
#[derive(Clone, RustcEncodable, Copy, Deserialize, Serialize)]
pub struct Range<I> {
    begin: I,
    length: I,
}

impl<I: RangeIndex> fmt::Debug for Range<I> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{:?} .. {:?})", self.begin(), self.end())
    }
}

/// An iterator over each index in a range
pub struct EachIndex<T, I> {
    it: ops::Range<T>,
    phantom: PhantomData<I>,
}

pub fn each_index<T: Int, I: RangeIndex<Index=T>>(start: I, stop: I) -> EachIndex<T, I> {
    EachIndex { it: start.get()..stop.get(), phantom: PhantomData }
}

impl<T: Int, I: RangeIndex<Index=T>> Iterator for EachIndex<T, I>
where T: Int + num::One + iter::Step, for<'a> &'a T: ops::Add<&'a T, Output = T> {
    type Item = I;

    #[inline]
    fn next(&mut self) -> Option<I> {
        self.it.next().map(RangeIndex::new)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.it.size_hint()
    }
}

impl<I: RangeIndex> Range<I> {
    /// Create a new range from beginning and length offsets. This could be
    /// denoted as `[begin, begin + length)`.
    ///
    /// ~~~ignore
    ///    |-- begin ->|-- length ->|
    ///    |           |            |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn new(begin: I, length: I) -> Range<I> {
        Range { begin: begin, length: length }
    }

    #[inline]
    pub fn empty() -> Range<I> {
        Range::new(Int::zero(), Int::zero())
    }

    /// The index offset to the beginning of the range.
    ///
    /// ~~~ignore
    ///    |-- begin ->|
    ///    |           |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn begin(&self) -> I { self.begin  }

    /// The index offset from the beginning to the end of the range.
    ///
    /// ~~~ignore
    ///                |-- length ->|
    ///                |            |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn length(&self) -> I { self.length }

    /// The index offset to the end of the range.
    ///
    /// ~~~ignore
    ///    |--------- end --------->|
    ///    |                        |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn end(&self) -> I { self.begin + self.length }

    /// `true` if the index is between the beginning and the end of the range.
    ///
    /// ~~~ignore
    ///        false        true      false
    ///          |           |          |
    /// <- o - - + - - +=====+======+ - + - ->
    /// ~~~
    #[inline]
    pub fn contains(&self, i: I) -> bool {
        i >= self.begin() && i < self.end()
    }

    /// `true` if the offset from the beginning to the end of the range is zero.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.length() == Int::zero()
    }

    /// Shift the entire range by the supplied index delta.
    ///
    /// ~~~ignore
    ///                     |-- delta ->|
    ///                     |           |
    /// <- o - +============+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn shift_by(&mut self, delta: I) {
        self.begin = self.begin + delta;
    }

    /// Extend the end of the range by the supplied index delta.
    ///
    /// ~~~ignore
    ///                     |-- delta ->|
    ///                     |           |
    /// <- o - - - - - +====+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - +================+ - - - ->
    /// ~~~
    #[inline]
    pub fn extend_by(&mut self, delta: I) {
        self.length = self.length + delta;
    }

    /// Move the end of the range to the target index.
    ///
    /// ~~~ignore
    ///                               target
    ///                                 |
    /// <- o - - - - - +====+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - +================+ - - - ->
    /// ~~~
    #[inline]
    pub fn extend_to(&mut self, target: I) {
        self.length = target - self.begin;
    }

    /// Adjust the beginning offset and the length by the supplied deltas.
    #[inline]
    pub fn adjust_by(&mut self, begin_delta: I, length_delta: I) {
        self.begin = self.begin + begin_delta;
        self.length = self.length + length_delta;
    }

    /// Set the begin and length values.
    #[inline]
    pub fn reset(&mut self, begin: I, length: I) {
        self.begin = begin;
        self.length = length;
    }

    #[inline]
    pub fn intersect(&self, other: &Range<I>) -> Range<I> {
        let begin = max(self.begin(), other.begin());
        let end = min(self.end(), other.end());

        if end < begin {
            Range::empty()
        } else {
            Range::new(begin, end - begin)
        }
    }
}

/// Methods for `Range`s with indices based on integer values
impl<T: Int, I: RangeIndex<Index=T>> Range<I> {
    /// Returns an iterater that increments over `[begin, end)`.
    #[inline]
    pub fn each_index(&self) -> EachIndex<T, I> {
        each_index(self.begin(), self.end())
    }
}
<commit_msg>util: Inline trivial range constructors.<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 num_lib;
use std::cmp::{self, max, min};
use std::fmt;
use std::iter;
use std::marker::PhantomData;
use std::num;
use std::ops;

pub trait Int:
    Copy
    + ops::Add<Self, Output=Self>
    + ops::Sub<Self, Output=Self>
    + cmp::Ord
{
    fn zero() -> Self;
    fn one() -> Self;
    fn max_value() -> Self;
    fn from_usize(n: usize) -> Option<Self>;
}
impl Int for isize {
    #[inline]
    fn zero() -> isize { 0 }
    #[inline]
    fn one() -> isize { 1 }
    #[inline]
    fn max_value() -> isize { ::std::isize::MAX }
    #[inline]
    fn from_usize(n: usize) -> Option<isize> { num_lib::NumCast::from(n) }
}
impl Int for usize {
    #[inline]
    fn zero() -> usize { 0 }
    #[inline]
    fn one() -> usize { 1 }
    #[inline]
    fn max_value() -> usize { ::std::usize::MAX }
    #[inline]
    fn from_usize(n: usize) -> Option<usize> { Some(n) }
}

/// An index type to be used by a `Range`
pub trait RangeIndex: Int + fmt::Debug {
    type Index;
    fn new(x: Self::Index) -> Self;
    fn get(self) -> Self::Index;
}

impl RangeIndex for isize {
    type Index = isize;
    #[inline]
    fn new(x: isize) -> isize { x }

    #[inline]
    fn get(self) -> isize { self }
}

impl RangeIndex for usize {
    type Index = usize;
    #[inline]
    fn new(x: usize) -> usize { x }

    #[inline]
    fn get(self) -> usize { self }
}

/// Implements a range index type with operator overloads
#[macro_export]
macro_rules! int_range_index {
    ($(#[$attr:meta])* struct $Self_:ident($T:ty)) => (
        #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Debug, Copy)]
        $(#[$attr])*
        pub struct $Self_(pub $T);

        impl $Self_ {
            #[inline]
            pub fn to_usize(self) -> usize {
                self.get() as usize
            }
        }

        impl RangeIndex for $Self_ {
            type Index = $T;
            #[inline]
            fn new(x: $T) -> $Self_ {
                $Self_(x)
            }

            #[inline]
            fn get(self) -> $T {
                match self { $Self_(x) => x }
            }
        }

        impl $crate::range::Int for $Self_ {
            #[inline]
            fn zero() -> $Self_ { $Self_($crate::range::Int::zero()) }
            #[inline]
            fn one() -> $Self_ { $Self_($crate::range::Int::one()) }
            #[inline]
            fn max_value() -> $Self_ { $Self_($crate::range::Int::max_value()) }
            #[inline]
            fn from_usize(n: usize) -> Option<$Self_> { $crate::range::Int::from_usize(n).map($Self_) }
        }

        impl ::std::ops::Add<$Self_> for $Self_ {
            type Output = $Self_;

            #[inline]
            fn add(self, other: $Self_) -> $Self_ {
                $Self_(self.get() + other.get())
            }
        }

        impl ::std::ops::Sub<$Self_> for $Self_ {
            type Output = $Self_;

            #[inline]
            fn sub(self, other: $Self_) -> $Self_ {
                $Self_(self.get() - other.get())
            }
        }

        impl ::std::ops::Neg for $Self_ {
            type Output = $Self_;

            #[inline]
            fn neg(self) -> $Self_ {
                $Self_(-self.get())
            }
        }
    )
}

/// A range of indices
#[derive(Clone, RustcEncodable, Copy, Deserialize, Serialize)]
pub struct Range<I> {
    begin: I,
    length: I,
}

impl<I: RangeIndex> fmt::Debug for Range<I> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{:?} .. {:?})", self.begin(), self.end())
    }
}

/// An iterator over each index in a range
pub struct EachIndex<T, I> {
    it: ops::Range<T>,
    phantom: PhantomData<I>,
}

pub fn each_index<T: Int, I: RangeIndex<Index=T>>(start: I, stop: I) -> EachIndex<T, I> {
    EachIndex { it: start.get()..stop.get(), phantom: PhantomData }
}

impl<T: Int, I: RangeIndex<Index=T>> Iterator for EachIndex<T, I>
where T: Int + num::One + iter::Step, for<'a> &'a T: ops::Add<&'a T, Output = T> {
    type Item = I;

    #[inline]
    fn next(&mut self) -> Option<I> {
        self.it.next().map(RangeIndex::new)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.it.size_hint()
    }
}

impl<I: RangeIndex> Range<I> {
    /// Create a new range from beginning and length offsets. This could be
    /// denoted as `[begin, begin + length)`.
    ///
    /// ~~~ignore
    ///    |-- begin ->|-- length ->|
    ///    |           |            |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn new(begin: I, length: I) -> Range<I> {
        Range { begin: begin, length: length }
    }

    #[inline]
    pub fn empty() -> Range<I> {
        Range::new(Int::zero(), Int::zero())
    }

    /// The index offset to the beginning of the range.
    ///
    /// ~~~ignore
    ///    |-- begin ->|
    ///    |           |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn begin(&self) -> I { self.begin  }

    /// The index offset from the beginning to the end of the range.
    ///
    /// ~~~ignore
    ///                |-- length ->|
    ///                |            |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn length(&self) -> I { self.length }

    /// The index offset to the end of the range.
    ///
    /// ~~~ignore
    ///    |--------- end --------->|
    ///    |                        |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn end(&self) -> I { self.begin + self.length }

    /// `true` if the index is between the beginning and the end of the range.
    ///
    /// ~~~ignore
    ///        false        true      false
    ///          |           |          |
    /// <- o - - + - - +=====+======+ - + - ->
    /// ~~~
    #[inline]
    pub fn contains(&self, i: I) -> bool {
        i >= self.begin() && i < self.end()
    }

    /// `true` if the offset from the beginning to the end of the range is zero.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.length() == Int::zero()
    }

    /// Shift the entire range by the supplied index delta.
    ///
    /// ~~~ignore
    ///                     |-- delta ->|
    ///                     |           |
    /// <- o - +============+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn shift_by(&mut self, delta: I) {
        self.begin = self.begin + delta;
    }

    /// Extend the end of the range by the supplied index delta.
    ///
    /// ~~~ignore
    ///                     |-- delta ->|
    ///                     |           |
    /// <- o - - - - - +====+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - +================+ - - - ->
    /// ~~~
    #[inline]
    pub fn extend_by(&mut self, delta: I) {
        self.length = self.length + delta;
    }

    /// Move the end of the range to the target index.
    ///
    /// ~~~ignore
    ///                               target
    ///                                 |
    /// <- o - - - - - +====+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - +================+ - - - ->
    /// ~~~
    #[inline]
    pub fn extend_to(&mut self, target: I) {
        self.length = target - self.begin;
    }

    /// Adjust the beginning offset and the length by the supplied deltas.
    #[inline]
    pub fn adjust_by(&mut self, begin_delta: I, length_delta: I) {
        self.begin = self.begin + begin_delta;
        self.length = self.length + length_delta;
    }

    /// Set the begin and length values.
    #[inline]
    pub fn reset(&mut self, begin: I, length: I) {
        self.begin = begin;
        self.length = length;
    }

    #[inline]
    pub fn intersect(&self, other: &Range<I>) -> Range<I> {
        let begin = max(self.begin(), other.begin());
        let end = min(self.end(), other.end());

        if end < begin {
            Range::empty()
        } else {
            Range::new(begin, end - begin)
        }
    }
}

/// Methods for `Range`s with indices based on integer values
impl<T: Int, I: RangeIndex<Index=T>> Range<I> {
    /// Returns an iterater that increments over `[begin, end)`.
    #[inline]
    pub fn each_index(&self) -> EachIndex<T, I> {
        each_index(self.begin(), self.end())
    }
}
<|endoftext|>


<commit_before>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Andres Vahter (andres.vahter@gmail.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

use ffiasync;
use libc::{c_char, c_int, c_void};
use std::ffi::{CStr, CString};
use std::mem;
use std::slice;
use std::sync::{Barrier, Mutex, Arc};

use super::Message;
use super::options::{PersistenceType, Qos, AsyncConnectOptions};
use super::error::{MqttError, CommandError, ConnectError, ConnectErrReturnCode, CallbackError};
use super::iterator::AsyncClientIntoIterator;

pub struct AsyncClient {
    handle        : ffiasync::MQTTAsync,
    barrier       : Barrier,
    action_result : Option<Result<(), CallbackError>>,
    messages      : Arc<Mutex<Vec<Message>>>,
}

impl AsyncClient {

    /// Ensures the FFI struct is consistent for callback invocation.
    ///
    /// Because the user may move this struct, the `context` pointer
    /// passed back to FFI callbacks might be invalidated. This function
    /// should be called before FFI actions that might fire callbacks to ensure
    /// the self-pointer is valid.
    fn context(&mut self) -> *mut c_void {
        self as *mut _ as *mut c_void
    }

    pub fn new(address: &str, clientid: &str, persistence: PersistenceType) -> Result<AsyncClient, MqttError> {
        let mut handle                      = unsafe{mem::zeroed()};
        let mut persistence_context: c_void = unsafe{mem::zeroed()};

        let c_url          = CString::new(address).unwrap();
        let c_clientid     = CString::new(clientid).unwrap();
        let array_url      = c_url.as_bytes_with_nul();
        let array_clientid = c_clientid.as_bytes_with_nul();

        let error = unsafe {
            ffiasync::MQTTAsync_create(&mut handle,
                                       mem::transmute::<&u8, *const c_char>(&array_url[0]),
                                       mem::transmute::<&u8, *const c_char>(&array_clientid[0]),
                                       persistence as i32,
                                       &mut persistence_context)
        };

        match error {
            0   => { Ok( AsyncClient {
                        handle          : handle,
                        barrier         : Barrier::new(2),
                        action_result   : None,
                        messages        : Arc::new(Mutex::new(Vec::new())),
                    })},
            err => Err(MqttError::Create(err))
        }
    }

    pub fn connect(&mut self, options: &mut AsyncConnectOptions) -> Result<(), MqttError> {
        debug!("connect..");
        unsafe {
            ffiasync::MQTTAsync_setCallbacks(self.handle,
                                             self.context(),
                                             Some(Self::disconnected),
                                             Some(Self::received),
                                             None);
        }

        let mut async_opts = ffiasync::MQTTAsync_connectOptions::new();

        // fill in FFI private struct
        async_opts.keepAliveInterval = options.keep_alive_interval;
        async_opts.cleansession      = options.cleansession;
        async_opts.maxInflight       = options.max_in_flight;
        async_opts.connectTimeout    = options.connect_timeout;
        async_opts.retryInterval     = options.retry_interval;

        // register callbacks
        async_opts.context   = self.context();
        async_opts.onSuccess = Some(Self::action_succeeded);
        async_opts.onFailure = Some(Self::action_failed);

        self.action_result = None;
        let error = unsafe {
            ffiasync::MQTTAsync_connect(self.handle, &async_opts)
        };
        if error == 0 {
            self.barrier.wait();
            match (self.is_connected(), &self.action_result) {
                (true,  _                                     ) => Ok(()),
                (false, &None                                 ) => unreachable!(),  // barrier should ensure we have something
                (false, &Some(Ok(()))                         ) => unreachable!(),  // callback and is_connected() don't agree?
                (false, &Some(Err(CallbackError::Response(r)))) => Err(MqttError::Connect(ConnectError::CallbackResponse(r))),
                (false, &Some(Err(CallbackError::NullPtr))    ) => Err(MqttError::Connect(ConnectError::CallbackNullPtr)),
            }
        } else { Err(MqttError::Connect(ConnectError::ReturnCode(ConnectErrReturnCode::from_int(error)))) }
    }

    #[allow(unused_variables)]
    extern "C" fn disconnected(context: *mut c_void, cause: *mut c_char) -> () {
        warn!("disconnected");
        assert!(!context.is_null());
    }

    pub fn is_connected(&mut self) -> bool {
        let ret = unsafe {
            ffiasync::MQTTAsync_isConnected(self.handle)
        };

        match ret {
            1 => true,
            _ => false,
        }
    }

    pub fn send(&mut self, data: &[u8], topic: &str, qos: Qos) -> Result<(), MqttError> {
        debug!("send..");
        let mut responseoption = ffiasync::MQTTAsync_responseOptions {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'R' as i8],
            struct_version  : 0,
            onSuccess       : Some(Self::action_succeeded),
            onFailure       : Some(Self::action_failed),
            context         : self.context(),
            token           : 0,
        };

        let mut message = ffiasync::MQTTAsync_message {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'M' as i8],
            struct_version  : 0,
            payloadlen      : data.len() as i32,
            payload         : unsafe {mem::transmute::<&u8, *mut c_void>(&data[0])},
            qos             : qos as c_int,
            retained        : 0,
            dup             : 0,
            msgid           : 0,
        };

        let c_topic        = CString::new(topic).unwrap();
        let array_topic    = c_topic.as_bytes_with_nul();
        self.action_result = None;

        let error = unsafe {
            ffiasync::MQTTAsync_sendMessage(self.handle,
                                            mem::transmute::<&u8, *const c_char>(&array_topic[0]),
                                            &mut message,
                                            &mut responseoption)
        };
        if error == 0 {
            self.barrier.wait();
            match (self.is_connected(), &self.action_result) {
                (true,  _                                     ) => Ok(()),
                (false, &None                                 ) => unreachable!(),  // barrier should ensure we have something
                (false, &Some(Ok(()))                         ) => unreachable!(),  // callback and is_connected() don't agree?
                (false, &Some(Err(CallbackError::Response(r)))) => Err(MqttError::Send(CommandError::CallbackResponse(r))),
                (false, &Some(Err(CallbackError::NullPtr))    ) => Err(MqttError::Send(CommandError::CallbackNullPtr)),
            }
        } else { Err(MqttError::Send(CommandError::ReturnCode(error))) }
    }

    pub fn subscribe(&mut self, topic: &str, qos: Qos) -> Result<(), MqttError> {
        debug!("subscribe..");
        let mut responseoption = ffiasync::MQTTAsync_responseOptions {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'R' as i8],
            struct_version  : 0,
            onSuccess       : Some(Self::action_succeeded),
            onFailure       : Some(Self::action_failed),
            context         : self.context(),
            token           : 0,
        };

        let c_topic     = CString::new(topic).unwrap();
        let array_topic = c_topic.as_bytes_with_nul();

        let c_qos: i32 = match qos {
            Qos::FireAndForget  => 0,
            Qos::AtLeastOnce    => 1,
            Qos::OnceAndOneOnly => 2,
        };
        self.action_result = None;

        let error = unsafe {
            ffiasync::MQTTAsync_subscribe(self.handle,
                                          mem::transmute::<&u8, *const c_char>(&array_topic[0]),
                                          c_qos,
                                          &mut responseoption)
        };

        if error == 0 {
            self.barrier.wait();
            match (self.is_connected(), &self.action_result) {
                (true,  _                                     ) => Ok(()),
                (false, &None                                 ) => unreachable!(),  // barrier should ensure we have something
                (false, &Some(Ok(()))                         ) => unreachable!(),  // callback and is_connected() don't agree?
                (false, &Some(Err(CallbackError::Response(r)))) => Err(MqttError::Subscribe(CommandError::CallbackResponse(r))),
                (false, &Some(Err(CallbackError::NullPtr))    ) => Err(MqttError::Subscribe(CommandError::CallbackNullPtr)),
            }
        } else { Err(MqttError::Subscribe(CommandError::ReturnCode(error))) }
    }

    #[allow(unused_variables)]
    extern "C" fn action_succeeded(context: *mut ::libc::c_void, response: *mut ffiasync::MQTTAsync_successData) -> () {
        debug!("success callback");
        assert!(!context.is_null());
        let selfclient: &mut AsyncClient = unsafe {mem::transmute(context)};
        selfclient.action_result = Some(Ok(()));
        selfclient.barrier.wait();
    }

    extern "C" fn action_failed(context: *mut ::libc::c_void, response: *mut ffiasync::MQTTAsync_failureData) -> () {
        debug!("failure callback");
        assert!(!context.is_null());
        let selfclient : &mut AsyncClient = unsafe {mem::transmute(context)};
        if response.is_null() {
            selfclient.action_result = Some(Err(CallbackError::NullPtr));
        } else {
            let resp : &mut ffiasync::MQTTAsync_failureData = unsafe {mem::transmute(response)};
            selfclient.action_result = Some(Err(CallbackError::Response(resp.code)));
        }
        selfclient.barrier.wait();
    }

    extern "C" fn received(context: *mut ::libc::c_void, topic_name: *mut ::libc::c_char, topic_len: ::libc::c_int, amessage: *mut ffiasync::MQTTAsync_message) -> i32 {
        let c_topic = unsafe {CStr::from_ptr(topic_name).to_bytes()};
        let topic   = String::from_utf8(c_topic.to_vec()).unwrap();
        assert_eq!(topic.len(), topic_len as usize);

        assert!(!amessage.is_null());
        let transmessage: &mut ffiasync::MQTTAsync_message = unsafe {mem::transmute(amessage)};

        let payload = match transmessage.payloadlen {
            0  => None,
            _ => {
                let payload_slice: &[u8] = unsafe {
                        slice::from_raw_parts(transmessage.payload as *mut u8, transmessage.payloadlen as usize)
                };
                Some(payload_slice.to_vec())
            }
        };

        assert!(!context.is_null());
        let selfclient : &mut AsyncClient = unsafe {mem::transmute(context)};

        let qos = Qos::from_int(transmessage.qos);

        let retained: bool = match transmessage.retained {
            0 => false,
            1 => true,
            _ => unreachable!(),
        };

        let duplicate: bool = match transmessage.dup {
            0 => false,
            1 => true,
            _ => unreachable!(),
        };

        let msg = Message {
            topic     : topic,
            payload   : payload,
            qos       : qos,
            retained  : retained,
            duplicate : duplicate,
        };

        let mut messages = selfclient.messages.lock().unwrap();
        messages.push(msg);

        let mut msg = amessage;
        unsafe{ffiasync::MQTTAsync_freeMessage(&mut msg)};
        unsafe{ffiasync::MQTTAsync_free(mem::transmute(topic_name))};
        1
    }

    pub fn messages(&mut self) -> AsyncClientIntoIterator {
        AsyncClientIntoIterator::new(self.messages.clone())
    }
}

impl Drop for AsyncClient {
    fn drop(&mut self) {
        unsafe{ffiasync::MQTTAsync_destroy(&mut self.handle)};
    }
}
<commit_msg>AsyncConnectOptions does not need to be mut in connect<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Andres Vahter (andres.vahter@gmail.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

use ffiasync;
use libc::{c_char, c_int, c_void};
use std::ffi::{CStr, CString};
use std::mem;
use std::slice;
use std::sync::{Barrier, Mutex, Arc};

use super::Message;
use super::options::{PersistenceType, Qos, AsyncConnectOptions};
use super::error::{MqttError, CommandError, ConnectError, ConnectErrReturnCode, CallbackError};
use super::iterator::AsyncClientIntoIterator;

pub struct AsyncClient {
    handle        : ffiasync::MQTTAsync,
    barrier       : Barrier,
    action_result : Option<Result<(), CallbackError>>,
    messages      : Arc<Mutex<Vec<Message>>>,
}

impl AsyncClient {

    /// Ensures the FFI struct is consistent for callback invocation.
    ///
    /// Because the user may move this struct, the `context` pointer
    /// passed back to FFI callbacks might be invalidated. This function
    /// should be called before FFI actions that might fire callbacks to ensure
    /// the self-pointer is valid.
    fn context(&mut self) -> *mut c_void {
        self as *mut _ as *mut c_void
    }

    pub fn new(address: &str, clientid: &str, persistence: PersistenceType) -> Result<AsyncClient, MqttError> {
        let mut handle                      = unsafe{mem::zeroed()};
        let mut persistence_context: c_void = unsafe{mem::zeroed()};

        let c_url          = CString::new(address).unwrap();
        let c_clientid     = CString::new(clientid).unwrap();
        let array_url      = c_url.as_bytes_with_nul();
        let array_clientid = c_clientid.as_bytes_with_nul();

        let error = unsafe {
            ffiasync::MQTTAsync_create(&mut handle,
                                       mem::transmute::<&u8, *const c_char>(&array_url[0]),
                                       mem::transmute::<&u8, *const c_char>(&array_clientid[0]),
                                       persistence as i32,
                                       &mut persistence_context)
        };

        match error {
            0   => { Ok( AsyncClient {
                        handle          : handle,
                        barrier         : Barrier::new(2),
                        action_result   : None,
                        messages        : Arc::new(Mutex::new(Vec::new())),
                    })},
            err => Err(MqttError::Create(err))
        }
    }

    pub fn connect(&mut self, options: &AsyncConnectOptions) -> Result<(), MqttError> {
        debug!("connect..");
        unsafe {
            ffiasync::MQTTAsync_setCallbacks(self.handle,
                                             self.context(),
                                             Some(Self::disconnected),
                                             Some(Self::received),
                                             None);
        }

        let mut async_opts = ffiasync::MQTTAsync_connectOptions::new();

        // fill in FFI private struct
        async_opts.keepAliveInterval = options.keep_alive_interval;
        async_opts.cleansession      = options.cleansession;
        async_opts.maxInflight       = options.max_in_flight;
        async_opts.connectTimeout    = options.connect_timeout;
        async_opts.retryInterval     = options.retry_interval;

        // register callbacks
        async_opts.context   = self.context();
        async_opts.onSuccess = Some(Self::action_succeeded);
        async_opts.onFailure = Some(Self::action_failed);

        self.action_result = None;
        let error = unsafe {
            ffiasync::MQTTAsync_connect(self.handle, &async_opts)
        };
        if error == 0 {
            self.barrier.wait();
            match (self.is_connected(), &self.action_result) {
                (true,  _                                     ) => Ok(()),
                (false, &None                                 ) => unreachable!(),  // barrier should ensure we have something
                (false, &Some(Ok(()))                         ) => unreachable!(),  // callback and is_connected() don't agree?
                (false, &Some(Err(CallbackError::Response(r)))) => Err(MqttError::Connect(ConnectError::CallbackResponse(r))),
                (false, &Some(Err(CallbackError::NullPtr))    ) => Err(MqttError::Connect(ConnectError::CallbackNullPtr)),
            }
        } else { Err(MqttError::Connect(ConnectError::ReturnCode(ConnectErrReturnCode::from_int(error)))) }
    }

    #[allow(unused_variables)]
    extern "C" fn disconnected(context: *mut c_void, cause: *mut c_char) -> () {
        warn!("disconnected");
        assert!(!context.is_null());
    }

    pub fn is_connected(&mut self) -> bool {
        let ret = unsafe {
            ffiasync::MQTTAsync_isConnected(self.handle)
        };

        match ret {
            1 => true,
            _ => false,
        }
    }

    pub fn send(&mut self, data: &[u8], topic: &str, qos: Qos) -> Result<(), MqttError> {
        debug!("send..");
        let mut responseoption = ffiasync::MQTTAsync_responseOptions {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'R' as i8],
            struct_version  : 0,
            onSuccess       : Some(Self::action_succeeded),
            onFailure       : Some(Self::action_failed),
            context         : self.context(),
            token           : 0,
        };

        let mut message = ffiasync::MQTTAsync_message {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'M' as i8],
            struct_version  : 0,
            payloadlen      : data.len() as i32,
            payload         : unsafe {mem::transmute::<&u8, *mut c_void>(&data[0])},
            qos             : qos as c_int,
            retained        : 0,
            dup             : 0,
            msgid           : 0,
        };

        let c_topic        = CString::new(topic).unwrap();
        let array_topic    = c_topic.as_bytes_with_nul();
        self.action_result = None;

        let error = unsafe {
            ffiasync::MQTTAsync_sendMessage(self.handle,
                                            mem::transmute::<&u8, *const c_char>(&array_topic[0]),
                                            &mut message,
                                            &mut responseoption)
        };
        if error == 0 {
            self.barrier.wait();
            match (self.is_connected(), &self.action_result) {
                (true,  _                                     ) => Ok(()),
                (false, &None                                 ) => unreachable!(),  // barrier should ensure we have something
                (false, &Some(Ok(()))                         ) => unreachable!(),  // callback and is_connected() don't agree?
                (false, &Some(Err(CallbackError::Response(r)))) => Err(MqttError::Send(CommandError::CallbackResponse(r))),
                (false, &Some(Err(CallbackError::NullPtr))    ) => Err(MqttError::Send(CommandError::CallbackNullPtr)),
            }
        } else { Err(MqttError::Send(CommandError::ReturnCode(error))) }
    }

    pub fn subscribe(&mut self, topic: &str, qos: Qos) -> Result<(), MqttError> {
        debug!("subscribe..");
        let mut responseoption = ffiasync::MQTTAsync_responseOptions {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'R' as i8],
            struct_version  : 0,
            onSuccess       : Some(Self::action_succeeded),
            onFailure       : Some(Self::action_failed),
            context         : self.context(),
            token           : 0,
        };

        let c_topic     = CString::new(topic).unwrap();
        let array_topic = c_topic.as_bytes_with_nul();

        let c_qos: i32 = match qos {
            Qos::FireAndForget  => 0,
            Qos::AtLeastOnce    => 1,
            Qos::OnceAndOneOnly => 2,
        };
        self.action_result = None;

        let error = unsafe {
            ffiasync::MQTTAsync_subscribe(self.handle,
                                          mem::transmute::<&u8, *const c_char>(&array_topic[0]),
                                          c_qos,
                                          &mut responseoption)
        };

        if error == 0 {
            self.barrier.wait();
            match (self.is_connected(), &self.action_result) {
                (true,  _                                     ) => Ok(()),
                (false, &None                                 ) => unreachable!(),  // barrier should ensure we have something
                (false, &Some(Ok(()))                         ) => unreachable!(),  // callback and is_connected() don't agree?
                (false, &Some(Err(CallbackError::Response(r)))) => Err(MqttError::Subscribe(CommandError::CallbackResponse(r))),
                (false, &Some(Err(CallbackError::NullPtr))    ) => Err(MqttError::Subscribe(CommandError::CallbackNullPtr)),
            }
        } else { Err(MqttError::Subscribe(CommandError::ReturnCode(error))) }
    }

    #[allow(unused_variables)]
    extern "C" fn action_succeeded(context: *mut ::libc::c_void, response: *mut ffiasync::MQTTAsync_successData) -> () {
        debug!("success callback");
        assert!(!context.is_null());
        let selfclient: &mut AsyncClient = unsafe {mem::transmute(context)};
        selfclient.action_result = Some(Ok(()));
        selfclient.barrier.wait();
    }

    extern "C" fn action_failed(context: *mut ::libc::c_void, response: *mut ffiasync::MQTTAsync_failureData) -> () {
        debug!("failure callback");
        assert!(!context.is_null());
        let selfclient : &mut AsyncClient = unsafe {mem::transmute(context)};
        if response.is_null() {
            selfclient.action_result = Some(Err(CallbackError::NullPtr));
        } else {
            let resp : &mut ffiasync::MQTTAsync_failureData = unsafe {mem::transmute(response)};
            selfclient.action_result = Some(Err(CallbackError::Response(resp.code)));
        }
        selfclient.barrier.wait();
    }

    extern "C" fn received(context: *mut ::libc::c_void, topic_name: *mut ::libc::c_char, topic_len: ::libc::c_int, amessage: *mut ffiasync::MQTTAsync_message) -> i32 {
        let c_topic = unsafe {CStr::from_ptr(topic_name).to_bytes()};
        let topic   = String::from_utf8(c_topic.to_vec()).unwrap();
        assert_eq!(topic.len(), topic_len as usize);

        assert!(!amessage.is_null());
        let transmessage: &mut ffiasync::MQTTAsync_message = unsafe {mem::transmute(amessage)};

        let payload = match transmessage.payloadlen {
            0  => None,
            _ => {
                let payload_slice: &[u8] = unsafe {
                        slice::from_raw_parts(transmessage.payload as *mut u8, transmessage.payloadlen as usize)
                };
                Some(payload_slice.to_vec())
            }
        };

        assert!(!context.is_null());
        let selfclient : &mut AsyncClient = unsafe {mem::transmute(context)};

        let qos = Qos::from_int(transmessage.qos);

        let retained: bool = match transmessage.retained {
            0 => false,
            1 => true,
            _ => unreachable!(),
        };

        let duplicate: bool = match transmessage.dup {
            0 => false,
            1 => true,
            _ => unreachable!(),
        };

        let msg = Message {
            topic     : topic,
            payload   : payload,
            qos       : qos,
            retained  : retained,
            duplicate : duplicate,
        };

        let mut messages = selfclient.messages.lock().unwrap();
        messages.push(msg);

        let mut msg = amessage;
        unsafe{ffiasync::MQTTAsync_freeMessage(&mut msg)};
        unsafe{ffiasync::MQTTAsync_free(mem::transmute(topic_name))};
        1
    }

    pub fn messages(&mut self) -> AsyncClientIntoIterator {
        AsyncClientIntoIterator::new(self.messages.clone())
    }
}

impl Drop for AsyncClient {
    fn drop(&mut self) {
        unsafe{ffiasync::MQTTAsync_destroy(&mut self.handle)};
    }
}
<|endoftext|>


<commit_before>use async::*;
use async::camera::CameraData;
use async::mesh_renderer::MeshRendererData;
use async::resource::{MaterialId, MeshId};
use async::scheduler::WorkId;
use async::transform::{TransformInnerHandle, TransformGraph};
use cell_extras::{AtomicInitCell, InitCell};
use bootstrap::window::{Message, Window};
use polygon::{GpuMesh, Renderer, RendererBuilder};
use polygon::anchor::Anchor;
use polygon::camera::{Camera as RenderCamera, CameraId};
use polygon::mesh_instance::MeshInstance;
use std::collections::HashMap;
use std::mem;
use std::ptr::{self, Unique};
use std::sync::{Arc, Barrier};
use std::sync::mpsc::{self, Receiver, Sender};
use std::time::{Duration, Instant};
use std::thread;
use stopwatch::Stopwatch;

#[derive(Debug)]
pub struct EngineBuilder {
    max_workers: usize,
}

static INSTANCE: AtomicInitCell<Unique<Engine>> = AtomicInitCell::new();
static MAIN_LOOP: AtomicInitCell<WorkId> = AtomicInitCell::new();

/// A builder for configuring the components and systems registered with the game engine.
///
/// Component managers and systems cannot be changed once the engine has been instantiated so they
/// must be provided all together when the instance is created. `EngineBuilder` provides an
/// interface for gathering all managers and systems to be provided to the engine.
impl EngineBuilder {
    /// Creates a new `EngineBuilder` object.
    pub fn new() -> EngineBuilder {
        EngineBuilder {
            max_workers: 1,
        }
    }

    /// Consumes the builder and creates the `Engine` instance.
    ///
    /// `func` is invoked once the engine has been setup, so `func` should kick off all game
    /// functionality.
    ///
    /// No `Engine` object is returned because this method instantiates the engine singleton.
    pub fn build<F>(self, func: F)
        where F: FnOnce()
    {
        let window = {
            let mut window = unsafe { mem::uninitialized() };
            let mut out = unsafe { Unique::new(&mut window as *mut _) };

            let barrier = Arc::new(Barrier::new(2));
            let barrier_clone = barrier.clone();

            thread::spawn(move || {
                let mut window = Window::new("gunship game").unwrap();

                let mut message_pump = window.message_pump();

                // write data out to `window` without dropping the old (uninitialized) value.
                unsafe { ptr::write(out.get_mut(), window); }

                // Sync with
                barrier_clone.wait();

                // We're done using the barrier, drop it so that the `Arc` can deallocate once
                // the other thread has receieved the Window.
                mem::drop(barrier_clone);

                message_pump.run();
            });

            // Wait until window thread finishe creating the window.
            barrier.wait();

            window
        };

        let renderer = RendererBuilder::new(&window).build();
        let (sender, receiever) = mpsc::channel();

        // Init aysnc subsystem.
        scheduler::init_thread();

        // Spawn our worker threads.
        if self.max_workers > 0 {
            for _ in 0..self.max_workers - 1 {
                let sender = sender.clone();
                thread::spawn(move || {
                    // Initialize thread-local renderer message channel.
                    RENDER_MESSAGE_CHANNEL.with(move |channel| { channel.init(sender); });

                    // Initialize worker thread to support fibers and wait for work to be available.
                    scheduler::run_wait_fiber();
                });
            }
        }

        // Set the current thread's channel.
        RENDER_MESSAGE_CHANNEL.with(move |channel| { channel.init(sender); });

        let engine = Engine {
            window: window,
            renderer: renderer,
            channel: receiever,

            mesh_map: HashMap::new(),

            scene_graph: TransformGraph::new(),
            camera: None,
            behaviors: Vec::new(),
        };

        let main_loop = scheduler::start(move || { main_loop(engine); });

        MAIN_LOOP.init(main_loop.work_id());

        func();

        wait_for_quit();
    }

    pub fn max_workers(&mut self, workers: usize) -> &mut EngineBuilder {
        assert!(workers > 0, "There must be at least one worker for the engine to run");
        self.max_workers = workers;
        self
    }
}

pub struct Engine {
    window: Window,

    renderer: Box<Renderer>,
    channel: Receiver<EngineMessage>,

    mesh_map: HashMap<MeshId, GpuMesh>,

    scene_graph: TransformGraph,
    camera: Option<(Box<CameraData>, CameraId)>,
    behaviors: Vec<Box<FnMut() + Send + Sync>>,
}

impl Drop for Engine {
    fn drop(&mut self) {
        // TODO: Clear instance?
    }
}

// `Engine` does handles synchronization internally, so it's meant be shared between threads.
unsafe impl Send for Engine {}
unsafe impl Sync for Engine {}

thread_local! {
    // TODO: We don't want this to be completely public, only pub(crate), but `thread_local`
    // doesn't support pub(crate) syntax.
    pub static RENDER_MESSAGE_CHANNEL: InitCell<Sender<EngineMessage>> = InitCell::new();
}

pub fn scene_graph<F, T>(func: F) -> T
    where F: FnOnce(&TransformGraph) -> T
{
    let engine = INSTANCE.borrow();
    unsafe { func(&(***engine).scene_graph) }
}

pub enum EngineMessage {
    Anchor(TransformInnerHandle),
    Camera(Box<CameraData>, TransformInnerHandle),
    Material(MaterialId, ::polygon::material::MaterialSource),
    Mesh(MeshId, ::polygon::geometry::mesh::Mesh),
    MeshInstance(Box<MeshRendererData>, TransformInnerHandle),
    Behavior(Box<FnMut() + Send + Sync>),
}

pub fn send_message(message: EngineMessage) {
    RENDER_MESSAGE_CHANNEL.with(move |channel| {
        channel
            .send(message)
            .expect("Unable to send render resource message");
    });
}

pub fn run_each_frame<F>(func: F)
    where
    F: 'static,
    F: FnMut(),
    F: Send + Sync,
{
    send_message(EngineMessage::Behavior(Box::new(func)));
}

/// Suspends the calling worker until the engine main loop has finished.
pub fn wait_for_quit() {
    MAIN_LOOP.borrow().await();
}

fn main_loop(engine: Engine) {
    // TODO: This should be a constant, but we can't create constant `Duration` objects right now.
    let target_frame_time = Duration::new(0, 1_000_000_000 / 60);

    let mut engine = Box::new(engine);
    INSTANCE.init(unsafe { Unique::new(&mut *engine) });
    let engine = &mut *engine;

    let mut last_frame_time = Instant::now();

    'main: loop {
        // Timing scope for main loop.
        {
            let _stopwatch = Stopwatch::with_budget("main loop", target_frame_time);

            // Process any pending window messages.
            for message in &mut engine.window {
                // TODO: Process input messages.
                if let Message::Close = message {
                    break 'main;
                }
            }

            // Kick off all game behaviors and wait for them to complete.
            if engine.behaviors.len() > 0 {
                let _stopwatch = Stopwatch::new("game behaviors");
                let mut pending = Vec::with_capacity(engine.behaviors.len());

                // Start all behaviors...
                for behavior in engine.behaviors.iter_mut() {
                    let async = scheduler::start(&mut **behavior);
                    pending.push(async);
                }

                // ... then wait for each of them to finish.
                for async in pending {
                    async.await();
                }
            } else {
                // There are no per-frame behaviors. We suspend the main loop fiber anyway to give
                // other work some time on the thread. Generally this case only matters when debugging
                // with a single thread.
                scheduler::suspend();
            }

            // Before drawing, process any pending render messages. These will be resources that were
            // loaded but need to be registered with the renderer before the next draw.
            while let Ok(message) = engine.channel.try_recv() {
                match message {
                    EngineMessage::Anchor(transform_inner) => {
                        let anchor = Anchor::new();
                        let anchor_id = engine.renderer.register_anchor(anchor);

                        transform_inner.set_anchor(anchor_id);
                    },
                    EngineMessage::Camera(camera_data, transform_inner) => {
                        assert!(engine.camera.is_none(), "Can't add camera, one is already registered");

                        let anchor_id = match transform_inner.anchor() {
                            Some(anchor) => anchor,
                            None => unimplemented!(), // TODO: Create the anchor.
                        };

                        let mut camera = RenderCamera::default();
                        camera.set_anchor(anchor_id);
                        let camera_id = engine.renderer.register_camera(camera);

                        engine.camera = Some((camera_data, camera_id));
                    },
                    EngineMessage::Material(_material_id, material_source) => {
                        let material = engine.renderer.build_material(material_source).expect("TODO: Handle material compilation failure");
                        let _gpu_material = engine.renderer.register_material(material);

                        // TODO: Create an association between `material_id` and `material_source`.
                    },
                    EngineMessage::Mesh(mesh_id, mesh_data) => {
                        let gpu_mesh = engine.renderer.register_mesh(&mesh_data);
                        let last = engine.mesh_map.insert(mesh_id, gpu_mesh);
                        assert!(last.is_none(), "Duplicate mesh_id found: {:?}", mesh_id);
                    },
                    EngineMessage::MeshInstance(mesh_renderer_data, transform_inner) => {
                        let anchor_id = match transform_inner.anchor() {
                            Some(anchor) => anchor,
                            None => unimplemented!(), // TODO: Create the anchor.
                        };

                        let gpu_mesh = *engine
                            .mesh_map
                            .get(&mesh_renderer_data.mesh_id())
                            .expect("No gpu mesh found for mesh id");

                        let mut mesh_instance = MeshInstance::new(
                            gpu_mesh,
                            engine.renderer.default_material(),
                        );
                        mesh_instance.material_mut().set_color("surface_color", ::math::Color::rgb(1.0, 0.0, 0.0)); // HACK HACK HACK
                        mesh_instance.set_anchor(anchor_id);

                        let _ = engine.renderer.register_mesh_instance(mesh_instance);
                    }
                    EngineMessage::Behavior(func) => {
                        engine.behaviors.push(func);
                    }
                }
            }

            // Update renderer's anchors with flattened scene graph.
            for node in engine.scene_graph.roots() {
                let node = node.borrow();

                // TODO: Do something like pre-sorting so we only try to update out of
                // date nodes.
                if let Some(anchor_id) = node.anchor() {
                    // Send position/rotation/scale to renderer anchor.
                    let anchor = engine.renderer
                        .get_anchor_mut(anchor_id)
                        .expect("Node had anchor id but render did not have specified anchor");
                    anchor.set_position(node.position);
                    anchor.set_orientation(node.orientation);
                    anchor.set_scale(node.scale);
                }
            }

            // Update the camera.
            if let Some((ref camera_data, ref camera_id)) = engine.camera {
                let render_camera = engine.renderer
                    .get_camera_mut(*camera_id)
                    .expect("Camera didn't exist for camera id");

                render_camera.set_fov(camera_data.fov());
                render_camera.set_aspect(camera_data.aspect());
                render_camera.set_near(camera_data.near());
                render_camera.set_far(camera_data.far());
            }

        }

        // Draw.
        engine.renderer.draw();

        // If we've already missed our target frame time then we want to immediately start the
        // next frame. Also, the remaining time calculations will overflow so we don't want to
        // run the below code.
        if last_frame_time.elapsed() > target_frame_time {
            last_frame_time = Instant::now();
            continue;
        }

        // Sleep the thread while there's more than a millisecond left.
        let mut remaining_time_ms = target_frame_time - last_frame_time.elapsed();
        while remaining_time_ms > Duration::from_millis(1) {
            thread::sleep(remaining_time_ms);

            if last_frame_time.elapsed() > target_frame_time {
                break;
            } else {
                remaining_time_ms = target_frame_time - last_frame_time.elapsed();
            }
        }

        // When there's less than a millisecond left the system scheduler isn't accurate enough to
        // awake it at the right time and it's possible to sleep too long. To avoid that we simply
        // busy loop until it's time for the next frame.
        while last_frame_time.elapsed() < target_frame_time {}

        last_frame_time = Instant::now();
    }
}
<commit_msg>Remove Sync bound from engine::run_each_frame()<commit_after>use async::*;
use async::camera::CameraData;
use async::mesh_renderer::MeshRendererData;
use async::resource::{MaterialId, MeshId};
use async::scheduler::WorkId;
use async::transform::{TransformInnerHandle, TransformGraph};
use bootstrap::window::{Message, Window};
use cell_extras::{AtomicInitCell, InitCell};
use input::Input;
use polygon::{GpuMesh, Renderer, RendererBuilder};
use polygon::anchor::Anchor;
use polygon::camera::{Camera as RenderCamera, CameraId};
use polygon::mesh_instance::MeshInstance;
use std::collections::HashMap;
use std::mem;
use std::ptr::{self, Unique};
use std::sync::{Arc, Barrier};
use std::sync::mpsc::{self, Receiver, Sender};
use std::time::{Duration, Instant};
use std::thread;
use stopwatch::Stopwatch;

#[derive(Debug)]
pub struct EngineBuilder {
    max_workers: usize,
}

static INSTANCE: AtomicInitCell<Unique<Engine>> = AtomicInitCell::new();
static MAIN_LOOP: AtomicInitCell<WorkId> = AtomicInitCell::new();

/// A builder for configuring the components and systems registered with the game engine.
///
/// Component managers and systems cannot be changed once the engine has been instantiated so they
/// must be provided all together when the instance is created. `EngineBuilder` provides an
/// interface for gathering all managers and systems to be provided to the engine.
impl EngineBuilder {
    /// Creates a new `EngineBuilder` object.
    pub fn new() -> EngineBuilder {
        EngineBuilder {
            max_workers: 1,
        }
    }

    /// Consumes the builder and creates the `Engine` instance.
    ///
    /// `func` is invoked once the engine has been setup, so `func` should kick off all game
    /// functionality.
    ///
    /// No `Engine` object is returned because this method instantiates the engine singleton.
    pub fn build<F>(self, func: F)
        where F: FnOnce()
    {
        let window = {
            let mut window = unsafe { mem::uninitialized() };
            let mut out = unsafe { Unique::new(&mut window as *mut _) };

            let barrier = Arc::new(Barrier::new(2));
            let barrier_clone = barrier.clone();

            thread::spawn(move || {
                let mut window = Window::new("gunship game").unwrap();

                let mut message_pump = window.message_pump();

                // write data out to `window` without dropping the old (uninitialized) value.
                unsafe { ptr::write(out.get_mut(), window); }

                // Sync with
                barrier_clone.wait();

                // We're done using the barrier, drop it so that the `Arc` can deallocate once
                // the other thread has receieved the Window.
                mem::drop(barrier_clone);

                message_pump.run();
            });

            // Wait until window thread finishe creating the window.
            barrier.wait();

            window
        };

        let renderer = RendererBuilder::new(&window).build();
        let (sender, receiever) = mpsc::channel();

        // Init aysnc subsystem.
        scheduler::init_thread();

        // Spawn our worker threads.
        if self.max_workers > 0 {
            for _ in 0..self.max_workers - 1 {
                let sender = sender.clone();
                thread::spawn(move || {
                    // Initialize thread-local renderer message channel.
                    RENDER_MESSAGE_CHANNEL.with(move |channel| { channel.init(sender); });

                    // Initialize worker thread to support fibers and wait for work to be available.
                    scheduler::run_wait_fiber();
                });
            }
        }

        // Set the current thread's channel.
        RENDER_MESSAGE_CHANNEL.with(move |channel| { channel.init(sender); });

        let engine = Engine {
            window: window,
            renderer: renderer,
            channel: receiever,

            mesh_map: HashMap::new(),

            scene_graph: TransformGraph::new(),
            camera: None,
            behaviors: Vec::new(),
            input: Input::new(),
        };

        let main_loop = scheduler::start(move || { main_loop(engine); });

        MAIN_LOOP.init(main_loop.work_id());

        func();

        wait_for_quit();
    }

    pub fn max_workers(&mut self, workers: usize) -> &mut EngineBuilder {
        assert!(workers > 0, "There must be at least one worker for the engine to run");
        self.max_workers = workers;
        self
    }
}

pub struct Engine {
    window: Window,

    renderer: Box<Renderer>,
    channel: Receiver<EngineMessage>,

    mesh_map: HashMap<MeshId, GpuMesh>,

    scene_graph: TransformGraph,
    camera: Option<(Box<CameraData>, CameraId)>,
    behaviors: Vec<Box<FnMut() + Send>>,
    input: Input,
}

impl Drop for Engine {
    fn drop(&mut self) {
        // TODO: Clear instance?
    }
}

// `Engine` does handles synchronization internally, so it's meant be shared between threads.
unsafe impl Send for Engine {}
unsafe impl Sync for Engine {}

thread_local! {
    // TODO: We don't want this to be completely public, only pub(crate), but `thread_local`
    // doesn't support pub(crate) syntax.
    pub static RENDER_MESSAGE_CHANNEL: InitCell<Sender<EngineMessage>> = InitCell::new();
}

// TODO: This shouln't be public, it's for engine-internal use.
pub fn scene_graph<F, T>(func: F) -> T
    where F: FnOnce(&TransformGraph) -> T
{
    let engine = INSTANCE.borrow();
    unsafe { func(&(***engine).scene_graph) }
}

// TODO: This shouln't be public, it's for engine-internal use.
pub fn input<F, T>(func: F) -> T
    where F: FnOnce(&Input) -> T
{
    let engine = INSTANCE.borrow();
    unsafe { func(&(***engine).input) }
}

pub enum EngineMessage {
    Anchor(TransformInnerHandle),
    Camera(Box<CameraData>, TransformInnerHandle),
    Material(MaterialId, ::polygon::material::MaterialSource),
    Mesh(MeshId, ::polygon::geometry::mesh::Mesh),
    MeshInstance(Box<MeshRendererData>, TransformInnerHandle),
    Behavior(Box<FnMut() + Send>),
}

pub fn send_message(message: EngineMessage) {
    RENDER_MESSAGE_CHANNEL.with(move |channel| {
        channel
            .send(message)
            .expect("Unable to send render resource message");
    });
}

pub fn run_each_frame<F>(func: F)
    where
    F: 'static,
    F: FnMut(),
    F: Send,
{
    send_message(EngineMessage::Behavior(Box::new(func)));
}

/// Suspends the calling worker until the engine main loop has finished.
pub fn wait_for_quit() {
    MAIN_LOOP.borrow().await();
}

fn main_loop(engine: Engine) {
    // TODO: This should be a constant, but we can't create constant `Duration` objects right now.
    let target_frame_time = Duration::new(0, 1_000_000_000 / 60);

    let mut engine = Box::new(engine);
    INSTANCE.init(unsafe { Unique::new(&mut *engine) });
    let engine = &mut *engine;

    let mut last_frame_time = Instant::now();

    'main: loop {
        // Timing scope for main loop.
        {
            let _stopwatch = Stopwatch::with_budget("main loop", target_frame_time);

            // Process any pending window messages.
            engine.input.clear();
            for message in &mut engine.window {
                // TODO: Process input messages.
                if let Message::Close = message {
                    break 'main;
                } else {
                    engine.input.push_input(message);
                }
            }

            // Kick off all game behaviors and wait for them to complete.
            if engine.behaviors.len() > 0 {
                let _stopwatch = Stopwatch::new("game behaviors");
                let mut pending = Vec::with_capacity(engine.behaviors.len());

                // Start all behaviors...
                for behavior in engine.behaviors.iter_mut() {
                    let async = scheduler::start(&mut **behavior);
                    pending.push(async);
                }

                // ... then wait for each of them to finish.
                for async in pending {
                    async.await();
                }
            } else {
                // There are no per-frame behaviors. We suspend the main loop fiber anyway to give
                // other work some time on the thread. Generally this case only matters when debugging
                // with a single thread.
                scheduler::suspend();
            }

            // Before drawing, process any pending render messages. These will be resources that were
            // loaded but need to be registered with the renderer before the next draw.
            while let Ok(message) = engine.channel.try_recv() {
                match message {
                    EngineMessage::Anchor(transform_inner) => {
                        let anchor = Anchor::new();
                        let anchor_id = engine.renderer.register_anchor(anchor);

                        transform_inner.set_anchor(anchor_id);
                    },
                    EngineMessage::Camera(camera_data, transform_inner) => {
                        assert!(engine.camera.is_none(), "Can't add camera, one is already registered");

                        let anchor_id = match transform_inner.anchor() {
                            Some(anchor) => anchor,
                            None => unimplemented!(), // TODO: Create the anchor.
                        };

                        let mut camera = RenderCamera::default();
                        camera.set_anchor(anchor_id);
                        let camera_id = engine.renderer.register_camera(camera);

                        engine.camera = Some((camera_data, camera_id));
                    },
                    EngineMessage::Material(_material_id, material_source) => {
                        let material = engine.renderer.build_material(material_source).expect("TODO: Handle material compilation failure");
                        let _gpu_material = engine.renderer.register_material(material);

                        // TODO: Create an association between `material_id` and `material_source`.
                    },
                    EngineMessage::Mesh(mesh_id, mesh_data) => {
                        let gpu_mesh = engine.renderer.register_mesh(&mesh_data);
                        let last = engine.mesh_map.insert(mesh_id, gpu_mesh);
                        assert!(last.is_none(), "Duplicate mesh_id found: {:?}", mesh_id);
                    },
                    EngineMessage::MeshInstance(mesh_renderer_data, transform_inner) => {
                        let anchor_id = match transform_inner.anchor() {
                            Some(anchor) => anchor,
                            None => unimplemented!(), // TODO: Create the anchor.
                        };

                        let gpu_mesh = *engine
                            .mesh_map
                            .get(&mesh_renderer_data.mesh_id())
                            .expect("No gpu mesh found for mesh id");

                        let mut mesh_instance = MeshInstance::new(
                            gpu_mesh,
                            engine.renderer.default_material(),
                        );
                        mesh_instance.material_mut().set_color("surface_color", ::math::Color::rgb(1.0, 0.0, 0.0)); // HACK HACK HACK
                        mesh_instance.set_anchor(anchor_id);

                        let _ = engine.renderer.register_mesh_instance(mesh_instance);
                    }
                    EngineMessage::Behavior(func) => {
                        engine.behaviors.push(func);
                    }
                }
            }

            // Update renderer's anchors with flattened scene graph.
            for node in engine.scene_graph.roots() {
                let node = node.borrow();

                // TODO: Do something like pre-sorting so we only try to update out of
                // date nodes.
                if let Some(anchor_id) = node.anchor() {
                    // Send position/rotation/scale to renderer anchor.
                    let anchor = engine.renderer
                        .get_anchor_mut(anchor_id)
                        .expect("Node had anchor id but render did not have specified anchor");
                    anchor.set_position(node.position);
                    anchor.set_orientation(node.orientation);
                    anchor.set_scale(node.scale);
                }
            }

            // Update the camera.
            if let Some((ref camera_data, ref camera_id)) = engine.camera {
                let render_camera = engine.renderer
                    .get_camera_mut(*camera_id)
                    .expect("Camera didn't exist for camera id");

                render_camera.set_fov(camera_data.fov());
                render_camera.set_aspect(camera_data.aspect());
                render_camera.set_near(camera_data.near());
                render_camera.set_far(camera_data.far());
            }

        }

        // Draw.
        engine.renderer.draw();

        // If we've already missed our target frame time then we want to immediately start the
        // next frame. Also, the remaining time calculations will overflow so we don't want to
        // run the below code.
        if last_frame_time.elapsed() > target_frame_time {
            last_frame_time = Instant::now();
            continue;
        }

        // Sleep the thread while there's more than a millisecond left.
        let mut remaining_time_ms = target_frame_time - last_frame_time.elapsed();
        while remaining_time_ms > Duration::from_millis(1) {
            thread::sleep(remaining_time_ms);

            if last_frame_time.elapsed() > target_frame_time {
                break;
            } else {
                remaining_time_ms = target_frame_time - last_frame_time.elapsed();
            }
        }

        // When there's less than a millisecond left the system scheduler isn't accurate enough to
        // awake it at the right time and it's possible to sleep too long. To avoid that we simply
        // busy loop until it's time for the next frame.
        while last_frame_time.elapsed() < target_frame_time {}

        last_frame_time = Instant::now();
    }
}
<|endoftext|>


<commit_before>use std::ops::Index;

use num::{Zero, zero};

/// The logarithm (in base-2) of the block size. This ensures that the block size is a power of 2.
/// In this case, 3 means a block size of 8.
const LOG_BLOCK_SIZE: usize = 3;
const BLOCK_SIZE: usize = 1 << LOG_BLOCK_SIZE;

pub struct BlockedArray<T> {
    u_res: usize,
    v_res: usize,
    u_blocks: usize,
    log_block_size: usize,
    block_size: usize,
    data: Vec<T>,
}

impl<T> BlockedArray<T>
    where T: Copy,
          T: Zero
{
    pub fn new(u_res: usize, v_res: usize) -> BlockedArray<T> {

        let data = vec![zero(); u_res * v_res];

        BlockedArray {
            u_res: u_res,
            v_res: v_res,
            u_blocks: u_res.next_power_of_two() >> LOG_BLOCK_SIZE,
            log_block_size: LOG_BLOCK_SIZE,
            block_size: BLOCK_SIZE,
            data: data,
        }
    }

    pub fn block_size(&self) -> usize {
        self.block_size
    }

    pub fn block(&self, a: usize) -> usize {
        a >> self.log_block_size
    }

    pub fn offset(&self, a: usize) -> usize {
        a & (self.block_size() - 1)
    }
}

impl<T> Index<(usize, usize)> for BlockedArray<T>
    where T: Copy,
          T: Zero
{
    type Output = T;

    fn index(&self, i: (usize, usize)) -> &T {
        let (u, v) = i;
        let bu = self.block(u);
        let bv = self.block(v);
        let ou = self.offset(u);
        let ov = self.offset(v);
        let offset = self.block_size() * self.block_size() * (self.u_blocks * bv + bu) +
                     self.block_size() * ov + ou;
        &self.data[offset]
    }
}
<commit_msg>Add IndexMut impl for BlockedArray<commit_after>use std::ops::{Index, IndexMut};

use num::{Zero, zero};

/// The logarithm (in base-2) of the block size. This ensures that the block size is a power of 2.
/// In this case, 3 means a block size of 8.
const LOG_BLOCK_SIZE: usize = 3;
const BLOCK_SIZE: usize = 1 << LOG_BLOCK_SIZE;

pub struct BlockedArray<T> {
    u_res: usize,
    v_res: usize,
    u_blocks: usize,
    log_block_size: usize,
    block_size: usize,
    data: Vec<T>,
}

impl<T> BlockedArray<T>
    where T: Copy,
          T: Zero
{
    pub fn new(u_res: usize, v_res: usize) -> BlockedArray<T> {
        let data = vec![zero(); u_res * v_res];

        BlockedArray {
            u_res: u_res,
            v_res: v_res,
            u_blocks: u_res.next_power_of_two() >> LOG_BLOCK_SIZE,
            log_block_size: LOG_BLOCK_SIZE,
            block_size: BLOCK_SIZE,
            data: data,
        }
    }

    pub fn new_from(u_res: usize, v_res: usize, d: &[T]) -> BlockedArray<T> {
        let mut ba = Self::new(u_res, v_res);

        for u in 0..u_res {
            for v in 0..v_res {
                ba[(u, v)] = d[v * u_res + u]
            }
        }

        ba
    }

    pub fn u_size(&self) -> usize {
        self.u_res
    }

    pub fn v_size(&self) -> usize {
        self.v_res
    }

    pub fn block_size(&self) -> usize {
        self.block_size
    }

    pub fn block(&self, a: usize) -> usize {
        a >> self.log_block_size
    }

    pub fn offset(&self, a: usize) -> usize {
        a & (self.block_size() - 1)
    }
}

impl<T> Index<(usize, usize)> for BlockedArray<T>
    where T: Copy,
          T: Zero
{
    type Output = T;

    fn index(&self, i: (usize, usize)) -> &T {
        let (u, v) = i;
        let bu = self.block(u);
        let bv = self.block(v);
        let ou = self.offset(u);
        let ov = self.offset(v);
        let offset = self.block_size() * self.block_size() * (self.u_blocks * bv + bu) +
                     self.block_size() * ov + ou;
        &self.data[offset]
    }
}

impl<T> IndexMut<(usize, usize)> for BlockedArray<T>
    where T: Copy,
          T: Zero
{
    fn index_mut(&mut self, i: (usize, usize)) -> &mut T {
        let (u, v) = i;
        let bu = self.block(u);
        let bv = self.block(v);
        let ou = self.offset(u);
        let ov = self.offset(v);
        let offset = self.block_size() * self.block_size() * (self.u_blocks * bv + bu) +
                     self.block_size() * ov + ou;
        &mut self.data[offset]
    }
}
<|endoftext|>


<commit_before>use error::{CliError, Usage, UsageKind};
use super::Command;

use lib::setting::{Config, ConfigKey, Storage};

#[derive(Debug)]
pub struct Burn;

impl Command for Burn {
    fn validation(&self) -> bool { true }

    fn usage(&self) -> Usage {
        return Usage::new(UsageKind::Burn);
    }

    fn main(&self) -> Result<(), CliError> {
        let config         = try!(Config::read());
        let raw_moratorium = try!(config.get(ConfigKey::BurnAfter));
        let moratorium     = Config::to_duration(raw_moratorium);

        let storage = Storage::new();
        try!(storage.delete_expired_boxes(moratorium));

        Ok(())
    }
}
<commit_msg>[Feature] Leave log file for "burn" command<commit_after>use error::{CliError, Usage, UsageKind};
use super::Command;

use lib::setting::{Config, ConfigKey, Storage};

#[derive(Debug)]
pub struct Burn;

impl Command for Burn {
    fn validation(&self) -> bool { true }

    fn usage(&self) -> Usage {
        return Usage::new(UsageKind::Burn);
    }

    fn main(&self) -> Result<(), CliError> {
        let config         = try!(Config::read());
        let raw_moratorium = try!(config.get(ConfigKey::BurnAfter));
        let moratorium     = Config::to_duration(raw_moratorium);

        let storage = try!(Storage::new().create_box_with_log("burn"));
        try!(storage.delete_expired_boxes(moratorium));

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