<commit_before>use libc::{c_int, int64_t, size_t};
use std::ffi::{CStr, CString};
use std::mem;
use std::path::Path;
use std::os::raw::c_void;
use tensorflow_sys as ffi;

macro_rules! nonnull(
    ($pointer:expr) => ({
        let pointer = $pointer;
        assert!(!pointer.is_null());
        pointer
    });
);

macro_rules! ok(
    ($status:expr) => ({
        if ffi::TF_GetCode($status) != ffi::TF_OK {
            panic!(CStr::from_ptr(ffi::TF_Message($status)).to_string_lossy().into_owned());
        }
    });
);

#[cfg_attr(feature="examples_system_alloc", global_allocator)]
#[cfg(feature="examples_system_alloc")]
static ALLOCATOR: std::alloc::System = std::alloc::System;

fn main() {
    use std::mem::size_of;
    use std::ptr::{null, null_mut};
    use std::slice::from_raw_parts;

    unsafe {
        let options = nonnull!(ffi::TF_NewSessionOptions());
        let status = nonnull!(ffi::TF_NewStatus());
        let graph = nonnull!(ffi::TF_NewGraph());

        let graph_def = read("examples/assets/multiplication.pb"); // c = a * b
        let opts = nonnull!(ffi::TF_NewImportGraphDefOptions());
        let graph_def_buf = ffi::TF_Buffer{
            data: graph_def.as_ptr() as *const c_void,
            length: graph_def.len(),
            data_deallocator: None,
        };
        ffi::TF_GraphImportGraphDef(graph,
                                    &graph_def_buf,
                                    opts,
                                    status);
        ffi::TF_DeleteImportGraphDefOptions(opts);
        ok!(status);

        let session = nonnull!(ffi::TF_NewSession(graph, options, status));
        let mut inputs = vec![];
        let mut input_tensors: Vec<*const ffi::TF_Tensor> = vec![];

        let name = CString::new("a").unwrap();
        let mut data = vec![1f32, 2.0, 3.0];
        let dims = vec![data.len() as int64_t];
        let tensor = nonnull!(ffi::TF_NewTensor(ffi::TF_FLOAT,
                                                dims.as_ptr(),
                                                dims.len() as c_int,
                                                data.as_mut_ptr() as *mut _,
                                                data.len() as size_t * mem::size_of::<f32>(),
                                                Some(noop),
                                                null_mut()));

        let input_op = nonnull!(ffi::TF_GraphOperationByName(graph, name.as_ptr()));
        inputs.push(ffi::TF_Output{
            oper: input_op,
            index: 0,
        });
        input_tensors.push(tensor);

        let name = CString::new("b").unwrap();
        let mut data = vec![4f32, 5.0, 6.0];
        let dims = vec![data.len() as int64_t];
        let tensor = nonnull!(ffi::TF_NewTensor(ffi::TF_FLOAT,
                                                dims.as_ptr(),
                                                dims.len() as c_int,
                                                data.as_mut_ptr() as *mut _,
                                                data.len() as size_t as size_t * mem::size_of::<f32>(),
                                                Some(noop),
                                                null_mut()));

        let input_op = nonnull!(ffi::TF_GraphOperationByName(graph, name.as_ptr()));
        inputs.push(ffi::TF_Output{
            oper: input_op,
            index: 0,
        });
        input_tensors.push(tensor);

        let mut outputs = vec![];
        let mut output_tensors = vec![];

        let name = CString::new("c").unwrap();

        let output_op = nonnull!(ffi::TF_GraphOperationByName(graph, name.as_ptr()));
        outputs.push(ffi::TF_Output{
            oper: output_op,
            index: 0,
        });
        output_tensors.push(null_mut());

        let mut target_names = vec![];

        ffi::TF_SessionRun(session,
                    null(),
                    inputs.as_mut_ptr(),
                    input_tensors.as_ptr(),
                    inputs.len() as c_int,
                    outputs.as_mut_ptr(),
                    output_tensors.as_mut_ptr(),
                    outputs.len() as c_int,
                    target_names.as_mut_ptr(),
                    target_names.len() as c_int,
                    null_mut(),
                    status);
        ok!(status);

        let tensor = nonnull!(output_tensors[0]);
        let data = nonnull!(ffi::TF_TensorData(tensor)) as *const f32;
        let data = from_raw_parts(data, ffi::TF_TensorByteSize(tensor) / size_of::<f32>());

        assert_eq!(data, &[1.0 * 4.0, 2.0 * 5.0, 3.0 * 6.0]);

        ffi::TF_CloseSession(session, status);

        ffi::TF_DeleteSession(session, status);
        ffi::TF_DeleteGraph(graph);
        ffi::TF_DeleteTensor(tensor);
        ffi::TF_DeleteStatus(status);
        ffi::TF_DeleteSessionOptions(options);
    }

    unsafe extern "C" fn noop(_: *mut std::os::raw::c_void, _: size_t, _: *mut std::os::raw::c_void) {}
}

fn read<T: AsRef<Path>>(path: T) -> Vec<u8> {
    use std::fs::File;
    use std::io::Read;

    let mut buffer = vec![];
    let mut file = File::open(path).unwrap();
    file.read_to_end(&mut buffer).unwrap();
    buffer
}
<commit_msg>Fix memory leak in tensorflow-sys/examples/multiplication.rs<commit_after>use libc::{c_int, int64_t, size_t};
use std::ffi::{CStr, CString};
use std::mem;
use std::path::Path;
use std::os::raw::c_void;
use tensorflow_sys as ffi;

macro_rules! nonnull(
    ($pointer:expr) => ({
        let pointer = $pointer;
        assert!(!pointer.is_null());
        pointer
    });
);

macro_rules! ok(
    ($status:expr) => ({
        if ffi::TF_GetCode($status) != ffi::TF_OK {
            panic!(CStr::from_ptr(ffi::TF_Message($status)).to_string_lossy().into_owned());
        }
    });
);

#[cfg_attr(feature="examples_system_alloc", global_allocator)]
#[cfg(feature="examples_system_alloc")]
static ALLOCATOR: std::alloc::System = std::alloc::System;

fn main() {
    use std::mem::size_of;
    use std::ptr::{null, null_mut};
    use std::slice::from_raw_parts;

    unsafe {
        let options = nonnull!(ffi::TF_NewSessionOptions());
        let status = nonnull!(ffi::TF_NewStatus());
        let graph = nonnull!(ffi::TF_NewGraph());

        let graph_def = read("examples/assets/multiplication.pb"); // c = a * b
        let opts = nonnull!(ffi::TF_NewImportGraphDefOptions());
        let graph_def_buf = ffi::TF_Buffer{
            data: graph_def.as_ptr() as *const c_void,
            length: graph_def.len(),
            data_deallocator: None,
        };
        ffi::TF_GraphImportGraphDef(graph,
                                    &graph_def_buf,
                                    opts,
                                    status);
        ffi::TF_DeleteImportGraphDefOptions(opts);
        ok!(status);

        let session = nonnull!(ffi::TF_NewSession(graph, options, status));
        let mut inputs = vec![];
        let mut input_tensors: Vec<*const ffi::TF_Tensor> = vec![];

        let name = CString::new("a").unwrap();
        let mut data = vec![1f32, 2.0, 3.0];
        let dims = vec![data.len() as int64_t];
        let input_tensor1 = nonnull!(ffi::TF_NewTensor(ffi::TF_FLOAT,
                                                dims.as_ptr(),
                                                dims.len() as c_int,
                                                data.as_mut_ptr() as *mut _,
                                                data.len() as size_t * mem::size_of::<f32>(),
                                                Some(noop),
                                                null_mut()));

        let input_op = nonnull!(ffi::TF_GraphOperationByName(graph, name.as_ptr()));
        inputs.push(ffi::TF_Output{
            oper: input_op,
            index: 0,
        });
        input_tensors.push(input_tensor1);

        let name = CString::new("b").unwrap();
        let mut data = vec![4f32, 5.0, 6.0];
        let dims = vec![data.len() as int64_t];
        let input_tensor2 = nonnull!(ffi::TF_NewTensor(ffi::TF_FLOAT,
                                                dims.as_ptr(),
                                                dims.len() as c_int,
                                                data.as_mut_ptr() as *mut _,
                                                data.len() as size_t as size_t * mem::size_of::<f32>(),
                                                Some(noop),
                                                null_mut()));

        let input_op = nonnull!(ffi::TF_GraphOperationByName(graph, name.as_ptr()));
        inputs.push(ffi::TF_Output{
            oper: input_op,
            index: 0,
        });
        input_tensors.push(input_tensor2);

        let mut outputs = vec![];
        let mut output_tensors = vec![];

        let name = CString::new("c").unwrap();

        let output_op = nonnull!(ffi::TF_GraphOperationByName(graph, name.as_ptr()));
        outputs.push(ffi::TF_Output{
            oper: output_op,
            index: 0,
        });
        output_tensors.push(null_mut());

        let mut target_names = vec![];

        ffi::TF_SessionRun(session,
                    null(),
                    inputs.as_mut_ptr(),
                    input_tensors.as_ptr(),
                    inputs.len() as c_int,
                    outputs.as_mut_ptr(),
                    output_tensors.as_mut_ptr(),
                    outputs.len() as c_int,
                    target_names.as_mut_ptr(),
                    target_names.len() as c_int,
                    null_mut(),
                    status);
        ok!(status);

        let output_tensor = nonnull!(output_tensors[0]);
        let data = nonnull!(ffi::TF_TensorData(output_tensor)) as *const f32;
        let data = from_raw_parts(data, ffi::TF_TensorByteSize(output_tensor) / size_of::<f32>());

        assert_eq!(data, &[1.0 * 4.0, 2.0 * 5.0, 3.0 * 6.0]);

        ffi::TF_CloseSession(session, status);

        ffi::TF_DeleteSession(session, status);
        ffi::TF_DeleteGraph(graph);
        ffi::TF_DeleteTensor(output_tensor);
        ffi::TF_DeleteTensor(input_tensor1);
        ffi::TF_DeleteTensor(input_tensor2);
        ffi::TF_DeleteStatus(status);
        ffi::TF_DeleteSessionOptions(options);
    }

    unsafe extern "C" fn noop(_: *mut std::os::raw::c_void, _: size_t, _: *mut std::os::raw::c_void) {}
}

fn read<T: AsRef<Path>>(path: T) -> Vec<u8> {
    use std::fs::File;
    use std::io::Read;

    let mut buffer = vec![];
    let mut file = File::open(path).unwrap();
    file.read_to_end(&mut buffer).unwrap();
    buffer
}
<|endoftext|>


<commit_before>use ra_db::{CrateId, Cancelable, FileId};
use ra_syntax::ast;

use crate::{Name, db::HirDatabase, DefId};

/// hir::Crate describes a single crate. It's the main inteface with which
/// crate's dependencies interact. Mostly, it should be just a proxy for the
/// root module.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Crate {
    pub(crate) crate_id: CrateId,
}

#[derive(Debug)]
pub struct CrateDependency {
    pub krate: Crate,
    pub name: Name,
}

impl Crate {
    pub fn crate_id(&self) -> CrateId {
        self.crate_id
    }
    pub fn dependencies(&self, db: &impl HirDatabase) -> Cancelable<Vec<CrateDependency>> {
        Ok(self.dependencies_impl(db))
    }
    pub fn root_module(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> {
        self.root_module_impl(db)
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Module {
    pub(crate) def_id: DefId,
}

impl Module {
    pub fn source(&self, db: &impl HirDatabase) -> (FileId, Option<ast::ModuleNode>) {
        self.source_impl(db)
    }

    /// Returns the crate this module is part of.
    pub fn krate(&self, db: &impl HirDatabase) -> Cancelable<Option<Crate>> {
        self.krate_impl(db)
    }

    pub fn crate_root(&self, db: &impl HirDatabase) -> Cancelable<Module> {
        self.crate_root_impl(db)
    }

    /// Finds a child module with the specified name.
    pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> {
        self.child_impl(db, name)
    }
}
<commit_msg>make source cancelable<commit_after>use ra_db::{CrateId, Cancelable, FileId};
use ra_syntax::ast;

use crate::{Name, db::HirDatabase, DefId};

/// hir::Crate describes a single crate. It's the main inteface with which
/// crate's dependencies interact. Mostly, it should be just a proxy for the
/// root module.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Crate {
    pub(crate) crate_id: CrateId,
}

#[derive(Debug)]
pub struct CrateDependency {
    pub krate: Crate,
    pub name: Name,
}

impl Crate {
    pub fn crate_id(&self) -> CrateId {
        self.crate_id
    }
    pub fn dependencies(&self, db: &impl HirDatabase) -> Cancelable<Vec<CrateDependency>> {
        Ok(self.dependencies_impl(db))
    }
    pub fn root_module(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> {
        self.root_module_impl(db)
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Module {
    pub(crate) def_id: DefId,
}

impl Module {
    pub fn source(&self, db: &impl HirDatabase) -> Cancelable<(FileId, Option<ast::ModuleNode>)> {
        Ok(self.source_impl(db))
    }

    /// Returns the crate this module is part of.
    pub fn krate(&self, db: &impl HirDatabase) -> Cancelable<Option<Crate>> {
        self.krate_impl(db)
    }

    pub fn crate_root(&self, db: &impl HirDatabase) -> Cancelable<Module> {
        self.crate_root_impl(db)
    }

    /// Finds a child module with the specified name.
    pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> {
        self.child_impl(db, name)
    }
}
<|endoftext|>


<commit_before>//! Handle process life-time and message passing for proc-macro client

use crossbeam_channel::{bounded, Receiver, Sender};
use ra_tt::Subtree;

use crate::msg::{ErrorCode, Message, Request, Response, ResponseError};
use crate::rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind};

use io::{BufRead, BufReader};
use std::{
    io::{self, Write},
    path::{Path, PathBuf},
    process::{Child, Command, Stdio},
    thread::{spawn, JoinHandle},
};

#[derive(Debug, Default)]
pub(crate) struct ProcMacroProcessSrv {
    inner: Option<Handle>,
}

#[derive(Debug)]
pub(crate) struct ProcMacroProcessThread {
    handle: Option<JoinHandle<()>>,
    sender: Sender<Task>,
}

enum Task {
    Request { req: Message, result_tx: Sender<Message> },
    Close,
}

#[derive(Debug)]
struct Handle {
    sender: Sender<Task>,
}

struct Process {
    path: PathBuf,
    child: Child,
}

impl Process {
    fn run(process_path: &Path) -> Result<Process, io::Error> {
        let child = Command::new(process_path.clone())
            .stdin(Stdio::piped())
            .stdout(Stdio::piped())
            .spawn()?;

        Ok(Process { path: process_path.into(), child })
    }

    fn restart(&mut self) -> Result<(), io::Error> {
        let _ = self.child.kill();
        self.child =
            Command::new(self.path.clone()).stdin(Stdio::piped()).stdout(Stdio::piped()).spawn()?;
        Ok(())
    }

    fn stdio(&mut self) -> Option<(impl Write, impl BufRead)> {
        let stdin = self.child.stdin.take()?;
        let stdout = self.child.stdout.take()?;
        let read = BufReader::new(stdout);

        Some((stdin, read))
    }
}

impl std::ops::Drop for ProcMacroProcessThread {
    fn drop(&mut self) {
        if let Some(handle) = self.handle.take() {
            let _ = self.sender.send(Task::Close);

            // Join the thread, it should finish shortly. We don't really care
            // whether it panicked, so it is safe to ignore the result
            let _ = handle.join();
        }
    }
}

impl ProcMacroProcessSrv {
    pub fn run(
        process_path: &Path,
    ) -> Result<(ProcMacroProcessThread, ProcMacroProcessSrv), io::Error> {
        let process = Process::run(process_path)?;

        let (task_tx, task_rx) = bounded(0);
        let handle = spawn(move || {
            client_loop(task_rx, process);
        });

        let srv = ProcMacroProcessSrv { inner: Some(Handle { sender: task_tx.clone() }) };
        let thread = ProcMacroProcessThread { handle: Some(handle), sender: task_tx };

        Ok((thread, srv))
    }

    pub fn find_proc_macros(
        &self,
        dylib_path: &Path,
    ) -> Result<Vec<(String, ProcMacroKind)>, ra_tt::ExpansionError> {
        let task = ListMacrosTask { lib: dylib_path.to_path_buf() };

        let result: ListMacrosResult = self.send_task("list_macros", task)?;
        Ok(result.macros)
    }

    pub fn custom_derive(
        &self,
        dylib_path: &Path,
        subtree: &Subtree,
        derive_name: &str,
    ) -> Result<Subtree, ra_tt::ExpansionError> {
        let task = ExpansionTask {
            macro_body: subtree.clone(),
            macro_name: derive_name.to_string(),
            attributes: None,
            lib: dylib_path.to_path_buf(),
        };

        let result: ExpansionResult = self.send_task("custom_derive", task)?;
        Ok(result.expansion)
    }

    pub fn send_task<'a, T, R>(&self, method: &str, task: T) -> Result<R, ra_tt::ExpansionError>
    where
        T: serde::Serialize,
        R: serde::de::DeserializeOwned + Default,
    {
        let handle = match &self.inner {
            None => return Err(ra_tt::ExpansionError::Unknown("No handle is found.".to_string())),
            Some(it) => it,
        };

        let msg = serde_json::to_value(task).unwrap();

        // FIXME: use a proper request id
        let id = 0;
        let req = Request { id: id.into(), method: method.into(), params: msg };

        let (result_tx, result_rx) = bounded(0);

        handle.sender.send(Task::Request { req: req.into(), result_tx }).map_err(|err| {
            ra_tt::ExpansionError::Unknown(format!(
                "Fail to send task in channel, reason : {:#?} ",
                err
            ))
        })?;
        let response = result_rx.recv().unwrap();

        match response {
            Message::Request(_) => {
                return Err(ra_tt::ExpansionError::Unknown(
                    "Return request from ra_proc_srv".into(),
                ))
            }
            Message::Response(res) => {
                if let Some(err) = res.error {
                    return Err(ra_tt::ExpansionError::ExpansionError(err.message));
                }
                match res.result {
                    None => Ok(R::default()),
                    Some(res) => {
                        let result: R = serde_json::from_value(res)
                            .map_err(|err| ra_tt::ExpansionError::JsonError(err.to_string()))?;
                        Ok(result)
                    }
                }
            }
        }
    }
}

fn client_loop(task_rx: Receiver<Task>, mut process: Process) {
    let (mut stdin, mut stdout) = match process.stdio() {
        None => return,
        Some(it) => it,
    };

    loop {
        let task = match task_rx.recv() {
            Ok(task) => task,
            Err(_) => break,
        };

        let (req, result_tx) = match task {
            Task::Request { req, result_tx } => (req, result_tx),
            Task::Close => break,
        };

        let res = match send_message(&mut stdin, &mut stdout, req) {
            Ok(res) => res,
            Err(_err) => {
                let res = Response {
                    id: 0.into(),
                    result: None,
                    error: Some(ResponseError {
                        code: ErrorCode::ServerErrorEnd as i32,
                        message: "Server closed".into(),
                        data: None,
                    }),
                };
                if result_tx.send(res.into()).is_err() {
                    break;
                }
                // Restart the process
                if process.restart().is_err() {
                    break;
                }
                let stdio = match process.stdio() {
                    None => break,
                    Some(it) => it,
                };
                stdin = stdio.0;
                stdout = stdio.1;
                continue;
            }
        };

        if let Some(res) = res {
            if result_tx.send(res).is_err() {
                break;
            }
        }
    }

    let _ = process.child.kill();
}

fn send_message(
    mut writer: &mut impl Write,
    mut reader: &mut impl BufRead,
    msg: Message,
) -> Result<Option<Message>, io::Error> {
    msg.write(&mut writer)?;
    Ok(Message::read(&mut reader)?)
}
<commit_msg>Remove unused struct<commit_after>//! Handle process life-time and message passing for proc-macro client

use crossbeam_channel::{bounded, Receiver, Sender};
use ra_tt::Subtree;

use crate::msg::{ErrorCode, Message, Request, Response, ResponseError};
use crate::rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind};

use io::{BufRead, BufReader};
use std::{
    io::{self, Write},
    path::{Path, PathBuf},
    process::{Child, Command, Stdio},
    thread::{spawn, JoinHandle},
};

#[derive(Debug, Default)]
pub(crate) struct ProcMacroProcessSrv {
    inner: Option<Sender<Task>>,
}

#[derive(Debug)]
pub(crate) struct ProcMacroProcessThread {
    handle: Option<JoinHandle<()>>,
    sender: Sender<Task>,
}

enum Task {
    Request { req: Message, result_tx: Sender<Message> },
    Close,
}

struct Process {
    path: PathBuf,
    child: Child,
}

impl Process {
    fn run(process_path: &Path) -> Result<Process, io::Error> {
        let child = Command::new(process_path.clone())
            .stdin(Stdio::piped())
            .stdout(Stdio::piped())
            .spawn()?;

        Ok(Process { path: process_path.into(), child })
    }

    fn restart(&mut self) -> Result<(), io::Error> {
        let _ = self.child.kill();
        self.child =
            Command::new(self.path.clone()).stdin(Stdio::piped()).stdout(Stdio::piped()).spawn()?;
        Ok(())
    }

    fn stdio(&mut self) -> Option<(impl Write, impl BufRead)> {
        let stdin = self.child.stdin.take()?;
        let stdout = self.child.stdout.take()?;
        let read = BufReader::new(stdout);

        Some((stdin, read))
    }
}

impl std::ops::Drop for ProcMacroProcessThread {
    fn drop(&mut self) {
        if let Some(handle) = self.handle.take() {
            let _ = self.sender.send(Task::Close);

            // Join the thread, it should finish shortly. We don't really care
            // whether it panicked, so it is safe to ignore the result
            let _ = handle.join();
        }
    }
}

impl ProcMacroProcessSrv {
    pub fn run(
        process_path: &Path,
    ) -> Result<(ProcMacroProcessThread, ProcMacroProcessSrv), io::Error> {
        let process = Process::run(process_path)?;

        let (task_tx, task_rx) = bounded(0);
        let handle = spawn(move || {
            client_loop(task_rx, process);
        });

        let srv = ProcMacroProcessSrv { inner: Some(task_tx.clone()) };
        let thread = ProcMacroProcessThread { handle: Some(handle), sender: task_tx };

        Ok((thread, srv))
    }

    pub fn find_proc_macros(
        &self,
        dylib_path: &Path,
    ) -> Result<Vec<(String, ProcMacroKind)>, ra_tt::ExpansionError> {
        let task = ListMacrosTask { lib: dylib_path.to_path_buf() };

        let result: ListMacrosResult = self.send_task("list_macros", task)?;
        Ok(result.macros)
    }

    pub fn custom_derive(
        &self,
        dylib_path: &Path,
        subtree: &Subtree,
        derive_name: &str,
    ) -> Result<Subtree, ra_tt::ExpansionError> {
        let task = ExpansionTask {
            macro_body: subtree.clone(),
            macro_name: derive_name.to_string(),
            attributes: None,
            lib: dylib_path.to_path_buf(),
        };

        let result: ExpansionResult = self.send_task("custom_derive", task)?;
        Ok(result.expansion)
    }

    pub fn send_task<'a, T, R>(&self, method: &str, task: T) -> Result<R, ra_tt::ExpansionError>
    where
        T: serde::Serialize,
        R: serde::de::DeserializeOwned + Default,
    {
        let sender = match &self.inner {
            None => return Err(ra_tt::ExpansionError::Unknown("No sender is found.".to_string())),
            Some(it) => it,
        };

        let msg = serde_json::to_value(task).unwrap();

        // FIXME: use a proper request id
        let id = 0;
        let req = Request { id: id.into(), method: method.into(), params: msg };

        let (result_tx, result_rx) = bounded(0);

        sender.send(Task::Request { req: req.into(), result_tx }).map_err(|err| {
            ra_tt::ExpansionError::Unknown(format!(
                "Fail to send task in channel, reason : {:#?} ",
                err
            ))
        })?;
        let response = result_rx.recv().unwrap();

        match response {
            Message::Request(_) => {
                return Err(ra_tt::ExpansionError::Unknown(
                    "Return request from ra_proc_srv".into(),
                ))
            }
            Message::Response(res) => {
                if let Some(err) = res.error {
                    return Err(ra_tt::ExpansionError::ExpansionError(err.message));
                }
                match res.result {
                    None => Ok(R::default()),
                    Some(res) => {
                        let result: R = serde_json::from_value(res)
                            .map_err(|err| ra_tt::ExpansionError::JsonError(err.to_string()))?;
                        Ok(result)
                    }
                }
            }
        }
    }
}

fn client_loop(task_rx: Receiver<Task>, mut process: Process) {
    let (mut stdin, mut stdout) = match process.stdio() {
        None => return,
        Some(it) => it,
    };

    loop {
        let task = match task_rx.recv() {
            Ok(task) => task,
            Err(_) => break,
        };

        let (req, result_tx) = match task {
            Task::Request { req, result_tx } => (req, result_tx),
            Task::Close => break,
        };

        let res = match send_message(&mut stdin, &mut stdout, req) {
            Ok(res) => res,
            Err(_err) => {
                let res = Response {
                    id: 0.into(),
                    result: None,
                    error: Some(ResponseError {
                        code: ErrorCode::ServerErrorEnd as i32,
                        message: "Server closed".into(),
                        data: None,
                    }),
                };
                if result_tx.send(res.into()).is_err() {
                    break;
                }
                // Restart the process
                if process.restart().is_err() {
                    break;
                }
                let stdio = match process.stdio() {
                    None => break,
                    Some(it) => it,
                };
                stdin = stdio.0;
                stdout = stdio.1;
                continue;
            }
        };

        if let Some(res) = res {
            if result_tx.send(res).is_err() {
                break;
            }
        }
    }

    let _ = process.child.kill();
}

fn send_message(
    mut writer: &mut impl Write,
    mut reader: &mut impl BufRead,
    msg: Message,
) -> Result<Option<Message>, io::Error> {
    msg.write(&mut writer)?;
    Ok(Message::read(&mut reader)?)
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.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.
 */

#![feature(proc_macro)]

extern crate gtk;
#[macro_use]
extern crate relm;
extern crate relm_core;
extern crate relm_attributes;
#[macro_use]
extern crate relm_derive;
#[macro_use]
extern crate relm_test;

use gtk::{
    ButtonExt,
    Inhibit,
    OrientableExt,
    WidgetExt,
};
use gtk::Orientation::Vertical;
use relm::Widget;
use relm_attributes::widget;

use self::Msg::*;

#[derive(Clone)]
struct Model {
    counter: i32,
}

#[derive(Msg)]
enum Msg {
    Decrement,
    Increment,
    Quit,
}

#[widget]
impl Widget<Msg> for Win {
    fn model() -> Model {
        Model {
            counter: 0,
        }
    }

    fn update(&mut self, event: Msg, model: &mut Model) {
        match event {
            Decrement => model.counter -= 1,
            Increment => model.counter += 1,
            Quit => gtk::main_quit(),
        }
    }

    view! {
        gtk::Window {
            gtk::Box {
                orientation: Vertical,
                #[name="inc_button"]
                gtk::Button {
                    clicked => Increment,
                    label: "+",
                },
                #[name="label"]
                gtk::Label {
                    text: &model.counter.to_string(),
                },
                #[name="dec_button"]
                gtk::Button {
                    clicked => Decrement,
                    label: "-",
                },
            },
            delete_event(_, _) => (Quit, Inhibit(false)),
        }
    }
}

#[cfg(test)]
mod tests {
    use relm;
    use relm_test::click;

    use super::{Msg, Win};

    #[test]
    fn label_change() {
        let (_component, widgets) = relm::init_test::<Win, Msg>().unwrap();

        assert_text!(widgets.label, 0);
        click(&widgets.inc_button);
        assert_text!(widgets.label, 1);
        click(&widgets.inc_button);
        assert_text!(widgets.label, 2);
        click(&widgets.dec_button);
        assert_text!(widgets.label, 1);
        click(&widgets.dec_button);
        assert_text!(widgets.label, 0);
        click(&widgets.dec_button);
        assert_text!(widgets.label, -1);
    }
}
<commit_msg>Remove unused extern crate in test<commit_after>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.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.
 */

#![feature(proc_macro)]

extern crate gtk;
#[macro_use]
extern crate relm;
extern crate relm_attributes;
#[macro_use]
extern crate relm_derive;
#[macro_use]
extern crate relm_test;

use gtk::{
    ButtonExt,
    Inhibit,
    OrientableExt,
    WidgetExt,
};
use gtk::Orientation::Vertical;
use relm::Widget;
use relm_attributes::widget;

use self::Msg::*;

#[derive(Clone)]
struct Model {
    counter: i32,
}

#[derive(Msg)]
enum Msg {
    Decrement,
    Increment,
    Quit,
}

#[widget]
impl Widget<Msg> for Win {
    fn model() -> Model {
        Model {
            counter: 0,
        }
    }

    fn update(&mut self, event: Msg, model: &mut Model) {
        match event {
            Decrement => model.counter -= 1,
            Increment => model.counter += 1,
            Quit => gtk::main_quit(),
        }
    }

    view! {
        gtk::Window {
            gtk::Box {
                orientation: Vertical,
                #[name="inc_button"]
                gtk::Button {
                    clicked => Increment,
                    label: "+",
                },
                #[name="label"]
                gtk::Label {
                    text: &model.counter.to_string(),
                },
                #[name="dec_button"]
                gtk::Button {
                    clicked => Decrement,
                    label: "-",
                },
            },
            delete_event(_, _) => (Quit, Inhibit(false)),
        }
    }
}

#[cfg(test)]
mod tests {
    use relm;
    use relm_test::click;

    use super::{Msg, Win};

    #[test]
    fn label_change() {
        let (_component, widgets) = relm::init_test::<Win, Msg>().unwrap();

        assert_text!(widgets.label, 0);
        click(&widgets.inc_button);
        assert_text!(widgets.label, 1);
        click(&widgets.inc_button);
        assert_text!(widgets.label, 2);
        click(&widgets.dec_button);
        assert_text!(widgets.label, 1);
        click(&widgets.dec_button);
        assert_text!(widgets.label, 0);
        click(&widgets.dec_button);
        assert_text!(widgets.label, -1);
    }
}
<|endoftext|>


<commit_before>//! The LLVM Stack Map Section format is documented here:
//!
//! http://llvm.org/docs/StackMaps.html#stack-map-format
//!
//! portions of which I am transcribing here.
//!
//! ```
//! Header {
//!     uint8  : Stack Map Version (current version is 1)
//!     uint8  : Reserved (expected to be 0)
//!     uint16 : Reserved (expected to be 0)
//! }
//! uint32 : NumFunctions
//! uint32 : NumConstants
//! uint32 : NumRecords
//! StkSizeRecord[NumFunctions] {
//!     uint64 : Function Address
//!     uint64 : Stack Size
//! }
//! Constants[NumConstants] {
//!     uint64 : LargeConstant
//! }
//! StkMapRecord[NumRecords] {
//!     uint64 : PatchPoint ID
//!     uint32 : Instruction Offset
//!     uint16 : Reserved (record flags)
//!     uint16 : NumLocations
//!     Location[NumLocations] {
//!         uint8  : Register | Direct | Indirect | Constant | ConstantIndex
//!         uint8  : Reserved (location flags)
//!         uint16 : Dwarf RegNum
//!         int32  : Offset or SmallConstant
//!     }
//!     uint16 : Padding
//!     uint16 : NumLiveOuts
//!     LiveOuts[NumLiveOuts] {
//!         uint16 : Dwarf RegNum
//!         uint8  : Reserved
//!         uint8  : Size in Bytes
//!     }
//!     uint32 : Padding (only if required to align to 8 byte)
//! }
//! ```

use byteorder::{ByteOrder, ReadBytesExt};
use byteorder::{BigEndian, LittleEndian};

use std::io::{Read};

pub trait Many {
    type Count;
}

pub mod errors {
    use std::io;

    #[derive(Debug)]
    pub enum StackMapError {
        Truncated { reading: &'static str },
        Header(HeaderError),
    }

    #[derive(Debug)]
    pub enum HeaderError {
        Prim(PrimError),
    }
    #[derive(Debug)]
    pub struct ConstantError { pub name: &'static str, pub err: io::Error }
    #[derive(Debug)]
    pub enum StackSizeError {
        Prim(PrimError),
    }
    #[derive(Debug)]
    pub enum LargeConstantError {
        Prim(PrimError),
    }
    #[derive(Debug)]
    pub enum RecordError {
        Prim(PrimError),
        Constant(ConstantError),
    }
    #[derive(Debug)]
    pub enum PrimError {
        Io(io::Error),
    }

    macro_rules! impl_from_for_read_error {
        ($VariantErr:ident, $Variant:ident) => {
            impl From<$VariantErr> for ReadError {
                fn from(x: $VariantErr) -> Self { ReadError::$Variant(x) }
            }
        }
    }

    macro_rules! enum_read_error {
        {$($Variant:ident($VariantErr:ident),)*} => {
            #[derive(Debug)]
            pub enum ReadError {
                $($Variant($VariantErr),)*
            }
            $(impl_from_for_read_error!{$VariantErr, $Variant})*
        }
    }

    enum_read_error!{
        StackMap(StackMapError),
        Constant(ConstantError),
        Header(HeaderError),
        StackSize(StackSizeError),
        LargeConstant(LargeConstantError),
        Record(RecordError),
        Prim(PrimError),
    }

    impl From<io::Error> for PrimError {
        fn from(x: io::Error) -> Self { PrimError::Io(x) }
    }

    impl From<PrimError> for HeaderError {
        fn from(x: PrimError) -> Self { HeaderError::Prim(x) }
    }

    impl From<PrimError> for StackSizeError {
        fn from(x: PrimError) -> Self { StackSizeError::Prim(x) }
    }

    impl From<PrimError> for LargeConstantError {
        fn from(x: PrimError) -> Self { LargeConstantError::Prim(x) }
    }

    impl From<PrimError> for RecordError {
        fn from(x: PrimError) -> Self { RecordError::Prim(x) }
    }

    impl From<ConstantError> for RecordError {
        fn from(x: ConstantError) -> Self { RecordError::Constant(x) }
    }
}

use self::errors::*;

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumFunctions(pub u32);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumConstants(pub u32);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumRecords(pub u32);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumLocations(pub u32);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumLiveOuts(pub u32);

trait ToUsize { fn to_usize(&self) -> usize; }

impl StackMap {
    pub fn read_from<T>(r: &[u8]) -> Result<Self, ReadError>
        where T:ByteOrder
    {
        ReadFrom<T>::read_from(r)
    }
}

trait ReadFrom<T:ByteOrder> {
    //
    fn read_from(bytes: &[u8]) -> Option<(Self, usize)>;
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct StackMap {
    header: Header,
    stack_sizes: Vec<StackSize>,
    large_constants: Vec<LargeConstant>,
    records: Vec<Record>
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Header {
    version: u8,
    reserved_1: u8,
    reserved_2: u16,
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct StackSize {
    function_address: u64,
    stack_size: u64,
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct LargeConstant {
    value: u64,
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Record {
    patchpoint_id: u64,
    instruction_offset: u32,
    reserved: u16,
    num_locations: NumLocations,
    locations: Vec<Location>,
    padding_1: u16,
    num_live_outs: NumLiveOuts,
    live_outs: Vec<LiveOut>,
    padding_2: Option<u32>, // only if required to align to 8 byte
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Location {
    val_type: u8,
    reserved: u8,
    dwarf_regnum: u16,
    offset_or_small_constant: i32,
}

#[repr(u8)]
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum ValType { Register, Direct, Indirect, Constant, ConstantIndex }

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct LiveOut {
    dwarf_regnum: u16,
    reserved: u8,
    size_in_bytes: u8,
}
<commit_msg>more plausible code for reading stackmap section from LLVM.<commit_after>//! The LLVM Stack Map Section format is documented here:
//!
//! http://llvm.org/docs/StackMaps.html#stack-map-format
//!
//! portions of which I am transcribing here.
//!
//! ```
//! Header {
//!     uint8  : Stack Map Version (current version is 1)
//!     uint8  : Reserved (expected to be 0)
//!     uint16 : Reserved (expected to be 0)
//! }
//! uint32 : NumFunctions
//! uint32 : NumConstants
//! uint32 : NumRecords
//! StkSizeRecord[NumFunctions] {
//!     uint64 : Function Address
//!     uint64 : Stack Size
//! }
//! Constants[NumConstants] {
//!     uint64 : LargeConstant
//! }
//! StkMapRecord[NumRecords] {
//!     uint64 : PatchPoint ID
//!     uint32 : Instruction Offset
//!     uint16 : Reserved (record flags)
//!     uint16 : NumLocations
//!     Location[NumLocations] {
//!         uint8  : Register | Direct | Indirect | Constant | ConstantIndex
//!         uint8  : Reserved (location flags)
//!         uint16 : Dwarf RegNum
//!         int32  : Offset or SmallConstant
//!     }
//!     uint16 : Padding
//!     uint16 : NumLiveOuts
//!     LiveOuts[NumLiveOuts] {
//!         uint16 : Dwarf RegNum
//!         uint8  : Reserved
//!         uint8  : Size in Bytes
//!     }
//!     uint32 : Padding (only if required to align to 8 byte)
//! }
//! ```

use byteorder::{ByteOrder, ReadBytesExt};
use byteorder::{BigEndian, LittleEndian};

use std::io::{Read};

pub trait Many {
    type Count;
}

pub mod errors {
    use std::io;

    #[derive(Debug)]
    pub enum StackMapError {
        Truncated { reading: &'static str },
        Header(HeaderError),
    }

    #[derive(Debug)]
    pub enum HeaderError {
        Prim(PrimError),
    }
    #[derive(Debug)]
    pub struct ConstantError { pub name: &'static str, pub err: io::Error }
    #[derive(Debug)]
    pub enum StackSizeError {
        Prim(PrimError),
    }
    #[derive(Debug)]
    pub enum LargeConstantError {
        Prim(PrimError),
    }
    #[derive(Debug)]
    pub enum RecordError {
        Prim(PrimError),
        Constant(ConstantError),
    }
    #[derive(Debug)]
    pub enum PrimError {
        Truncated { want: &'static str, at: usize },
        Io(io::Error),
    }

    macro_rules! impl_from_for_read_error {
        ($VariantErr:ident, $Variant:ident) => {
            impl From<$VariantErr> for ReadError {
                fn from(x: $VariantErr) -> Self { ReadError::$Variant(x) }
            }
        }
    }

    macro_rules! enum_read_error {
        {$($Variant:ident($VariantErr:ident),)*} => {
            #[derive(Debug)]
            pub enum ReadError {
                $($Variant($VariantErr),)*
            }
            $(impl_from_for_read_error!{$VariantErr, $Variant})*
        }
    }

    enum_read_error!{
        StackMap(StackMapError),
        Constant(ConstantError),
        Header(HeaderError),
        StackSize(StackSizeError),
        LargeConstant(LargeConstantError),
        Record(RecordError),
        Prim(PrimError),
    }

    impl From<io::Error> for PrimError {
        fn from(x: io::Error) -> Self { PrimError::Io(x) }
    }

    impl From<PrimError> for HeaderError {
        fn from(x: PrimError) -> Self { HeaderError::Prim(x) }
    }

    impl From<PrimError> for StackSizeError {
        fn from(x: PrimError) -> Self { StackSizeError::Prim(x) }
    }

    impl From<PrimError> for LargeConstantError {
        fn from(x: PrimError) -> Self { LargeConstantError::Prim(x) }
    }

    impl From<PrimError> for RecordError {
        fn from(x: PrimError) -> Self { RecordError::Prim(x) }
    }

    impl From<ConstantError> for RecordError {
        fn from(x: ConstantError) -> Self { RecordError::Constant(x) }
    }
}

use self::errors::*;

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumFunctions(pub u32);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumConstants(pub u32);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumRecords(pub u32);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumLocations(pub u32);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct NumLiveOuts(pub u32);

trait ToUsize { fn to_usize(&self) -> usize; }

macro_rules! impl_to_usize {
    ($($S:ident),*) => {$(
        impl ToUsize for $S {
            fn to_usize(&self) -> usize { self.0 as usize }
        }
        )*}
}

impl_to_usize!(NumFunctions, NumConstants, NumRecords, NumLocations, NumLiveOuts);

impl StackMap {
    pub fn read_from<T>(r: &[u8]) -> Result<Self, ReadError>
        where T:ByteOrder
    {
        ReadFrom::<T>::read(r, 0).map(|x|x.0)
    }
}

type ReadResult<X> = Result<(X, usize), ReadError>;

trait ReadFrom<T:ByteOrder>: Sized {
    fn read(bytes: &[u8], offset: usize) -> ReadResult<Self>;
}

trait ReadMany<T:ByteOrder>: ReadFrom<T> {
    type Count: ToUsize;
    fn read_many(bytes: &[u8],
                 mut offset: usize,
                 count: &Self::Count) -> ReadResult<Vec<Self>> {
        let mut v = Vec::with_capacity(count.to_usize());
        for _ in 0..(count.to_usize()) {
            let (e, new_offset) = Self::read(bytes, offset)?;
            offset = new_offset;
            v.push(e);
        }
        Ok((v, offset))
    }
}

impl<T:ByteOrder> ReadFrom<T> for StackMap {
    fn read(b: &[u8], i: usize) -> Result<(Self, usize), ReadError> {
        let (hr, i): (Header, _) = ReadFrom::<T>::read(b, i)?;
        let (nf, i): (NumFunctions, _) = ReadFrom::<T>::read(b, i)?;
        let (nc, i): (NumConstants, _) = ReadFrom::<T>::read(b, i)?;
        let (nr, i): (NumRecords, _) = ReadFrom::<T>::read(b, i)?;
        let (ss, i): (Vec<StackSize>, _) = ReadMany::<T>::read_many(b, i, &nf)?;
        let (cs, i): (Vec<LargeConstant>, _) = ReadMany::<T>::read_many(b, i, &nc)?;
        let (rs, i): (Vec<Record>, _) = ReadMany::<T>::read_many(b, i, &nr)?;
        Ok((StackMap { header: hr,
                       stack_sizes: ss,
                       large_constants: cs,
                       records: rs }, i))
    }
}

impl<T:ByteOrder> ReadFrom<T> for Header {
    fn read(b: &[u8], i: usize) -> Result<(Self, usize), ReadError> {
        let (version, i): (u8, _) = ReadFrom::<T>::read(b, i)?;
        let (reserved_1, i): (u8, _) = ReadFrom::<T>::read(b, i)?;
        let (reserved_2, i): (u16, _) = ReadFrom::<T>::read(b, i)?;
        Ok((Header { version: version,
                     reserved_1: reserved_1,
                     reserved_2: reserved_2, }, i))
    }
}

macro_rules! impl_read_for_prim {
    ($t:ident, $read:ident) => {
        impl<T:ByteOrder> ReadFrom<T> for $t {
            fn read(b: &[u8], i: usize) -> Result<(Self, usize), ReadError> {
                let size = ::std::mem::size_of::<$t>();
                if b.len() < (i + size) {
                    return Err(PrimError::Truncated {
                        want: stringify!($t),
                        at: i,
                    }.into());
                }
                Ok((T::$read(b.split_at(i).1), i+size))
            }
        }
    }
}

impl_read_for_prim!(u16, read_u16);
impl_read_for_prim!(u32, read_u32);
impl_read_for_prim!(i32, read_i32);
impl_read_for_prim!(u64, read_u64);

impl<T:ByteOrder> ReadFrom<T> for u8 {
    fn read(b: &[u8], i: usize) -> Result<(Self, usize), ReadError> {
        if b.len() < (i + 1) {
            return Err(PrimError::Truncated {
                want: stringify!(u8),
                at: i,
            }.into());
        }
        Ok((b[i], i+1))
    }
}

macro_rules! impl_read_from_for_u32_wrapper {
    ($S:ident) => {
        impl<T:ByteOrder> ReadFrom<T> for $S {
            fn read(b: &[u8], i: usize) -> Result<(Self, usize), ReadError> {
                if b.len() < (i + 4) {
                    return Err(PrimError::Truncated {
                        want: stringify!($S),
                        at: i,
                    }.into());
                }
                Ok(($S(T::read_u32(b.split_at(i).1)), 4))
            }
        }
    }
}

impl_read_from_for_u32_wrapper!(NumFunctions);
impl_read_from_for_u32_wrapper!(NumConstants);
impl_read_from_for_u32_wrapper!(NumRecords);
impl_read_from_for_u32_wrapper!(NumLocations);
impl_read_from_for_u32_wrapper!(NumLiveOuts);

impl<T:ByteOrder> ReadMany<T> for StackSize { type Count = NumFunctions; }
impl<T:ByteOrder> ReadMany<T> for LargeConstant { type Count = NumConstants; }
impl<T:ByteOrder> ReadMany<T> for Record { type Count = NumRecords; }
impl<T:ByteOrder> ReadMany<T> for Location { type Count = NumLocations; }

impl<T:ByteOrder> ReadFrom<T> for StackSize {
    fn read(b: &[u8], i: usize) -> ReadResult<Self> {
        let (fa, i): (u64, _) = ReadFrom::<T>::read(b, i)?;
        let (ss, i): (u64, _) = ReadFrom::<T>::read(b, i)?;
        Ok((StackSize { function_address: fa,
                        stack_size: ss }, i))
    }
}

impl<T:ByteOrder> ReadFrom<T> for LargeConstant {
    fn read(b: &[u8], i: usize) -> ReadResult<Self> {
        let (value, i): (u64, _) = ReadFrom::<T>::read(b, i)?;
        Ok((LargeConstant { value: value }, i))
    }
}

impl<T:ByteOrder> ReadFrom<T> for Record {
    fn read(b: &[u8], i: usize) -> ReadResult<Self> {
        let (pi, i): (u64, _) = ReadFrom::<T>::read(b, i)?;
        let (io, i): (u32, _) = ReadFrom::<T>::read(b, i)?;
        let (rs, i): (u16, _) = ReadFrom::<T>::read(b, i)?;
        let (nl, i): (NumLocations, _) = ReadFrom::<T>::read(b, i)?;
        let (ls, i): (Vec<Location>, _) = ReadMany::<T>::read_many(b, i, &nl)?;
        let (p1, i): (u16, _) = ReadFrom::<T>::read(b, i)?;
        let (nlo, i): (NumLiveOuts, _) = ReadFrom::<T>::read(b, i)?;
        let (los, i): (Vec<LiveOut>, _) = ReadMany::<T>::read_many(b, i, &nlo)?;
        assert!(i % 4 == 0);
        let (p2, i) = if i % 8 == 0 {
            (None, i) } else {
            let (p2, i): (u32, _) = ReadFrom::<T>::read(b, i)?;
            (Some(p2), i)
        };
        Ok((Record {
            patchpoint_id: pi,
            instruction_offset: io,
            reserved: rs,
            num_locations: nl,
            locations: ls,
            padding_1: p1,
            num_live_outs: nlo,
            live_outs: los,
            padding_2: p2,
        }, i))
    }
}

impl<T:ByteOrder> ReadFrom<T> for Location {
    fn read(b: &[u8], i: usize) -> ReadResult<Self> {
        let (vt, i): (u8, _) = ReadFrom::<T>::read(b, i)?;
        let (rs, i): (u8, _) = ReadFrom::<T>::read(b, i)?;
        let (dr, i): (u16, _) = ReadFrom::<T>::read(b, i)?;
        let (os, i): (i32, _) = ReadFrom::<T>::read(b, i)?;
        Ok((Location {
            val_type: vt,
            reserved: rs,
            dwarf_regnum: dr,
            offset_or_small_constant: os,
        }, i))
    }
}

impl<T:ByteOrder> ReadMany<T> for LiveOut { type Count = NumLiveOuts; }

impl<T:ByteOrder> ReadFrom<T> for LiveOut {
    fn read(b: &[u8], i: usize) -> ReadResult<Self> {
        let (dr, i): (u16, _) = ReadFrom::<T>::read(b, i)?;
        let (rs, i): (u8, _) = ReadFrom::<T>::read(b, i)?;
        let (sb, i): (u8, _) = ReadFrom::<T>::read(b, i)?;
        Ok((LiveOut {
            dwarf_regnum: dr,
            reserved: rs,
            size_in_bytes: sb, }, i))
    }
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct StackMap {
    header: Header,
    stack_sizes: Vec<StackSize>,
    large_constants: Vec<LargeConstant>,
    records: Vec<Record>
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Header {
    version: u8,
    reserved_1: u8,
    reserved_2: u16,
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct StackSize {
    function_address: u64,
    stack_size: u64,
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct LargeConstant {
    value: u64,
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Record {
    patchpoint_id: u64,
    instruction_offset: u32,
    reserved: u16,
    num_locations: NumLocations,
    locations: Vec<Location>,
    padding_1: u16,
    num_live_outs: NumLiveOuts,
    live_outs: Vec<LiveOut>,
    padding_2: Option<u32>, // only if required to align to 8 byte
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Location {
    val_type: u8,
    reserved: u8,
    dwarf_regnum: u16,
    offset_or_small_constant: i32,
}

#[repr(u8)]
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum ValType { Register, Direct, Indirect, Constant, ConstantIndex }

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct LiveOut {
    dwarf_regnum: u16,
    reserved: u8,
    size_in_bytes: u8,
}
<|endoftext|>


<commit_before>//! Starts a timely dataflow execution from configuration information and per-worker logic.

use crate::communication::{initialize_from, Configuration, Allocator, allocator::AllocateBuilder, WorkerGuards};
use crate::dataflow::scopes::Child;
use crate::worker::Worker;

/// Executes a single-threaded timely dataflow computation.
///
/// The `example` method takes a closure on a `Scope` which it executes to initialize and run a
/// timely dataflow computation on a single thread. This method is intended for use in examples,
/// rather than programs that may need to run across multiple workers.
///
/// The `example` method returns whatever the single worker returns from its closure.
/// This is often nothing, but the worker can return something about the data it saw in order to
/// test computations.
///
/// The method aggressively unwraps returned `Result<_>` types.
///
/// # Examples
///
/// The simplest example creates a stream of data and inspects it.
///
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// timely::example(|scope| {
///     (0..10).to_stream(scope)
///            .inspect(|x| println!("seen: {:?}", x));
/// });
/// ```
///
/// This next example captures the data and displays them once the computation is complete.
///
/// More precisely, the example captures a stream of events (receiving batches of data,
/// updates to input capabilities) and displays these events.
///
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect, Capture};
/// use timely::dataflow::operators::capture::Extract;
///
/// let data = timely::example(|scope| {
///     (0..10).to_stream(scope)
///            .inspect(|x| println!("seen: {:?}", x))
///            .capture()
/// });
///
/// // the extracted data should have data (0..10) at timestamp 0.
/// assert_eq!(data.extract()[0].1, (0..10).collect::<Vec<_>>());
/// ```
pub fn example<T, F>(func: F) -> T
where
    T: Send+'static,
    F: FnOnce(&mut Child<Worker<crate::communication::allocator::thread::Thread>,u64>)->T+Send+Sync+'static
{
    crate::execute::execute_directly(|worker| worker.dataflow(|scope| func(scope)))
}

/// Executes a single-threaded timely dataflow computation.
///
/// The `execute_directly` constructs a `Worker` and directly executes the supplied
/// closure to construct and run a timely dataflow computation. It does not create any
/// worker threads, and simply uses the current thread of control.
///
/// The closure may return a result, which will be returned from the computation.
///
/// # Examples
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute_directly(|worker| {
///     worker.dataflow::<(),_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// });
/// ```
pub fn execute_directly<T, F>(func: F) -> T
where
    T: Send+'static,
    F: FnOnce(&mut Worker<crate::communication::allocator::thread::Thread>)->T+Send+Sync+'static
{
    let alloc = crate::communication::allocator::thread::Thread::new();
    let mut worker = crate::worker::Worker::new(alloc);
    let result = func(&mut worker);
    while worker.step() { }
    result
}

/// Executes a timely dataflow from a configuration and per-communicator logic.
///
/// The `execute` method takes a `Configuration` and spins up some number of
/// workers threads, each of which execute the supplied closure to construct
/// and run a timely dataflow computation.
///
/// The closure may return a `T: Send+'static`, and `execute` returns a result
/// containing a `WorkerGuards<T>` (or error information), which can be joined
/// to recover the result `T` values from the local workers.
///
/// # Examples
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute(timely::Configuration::Process(3), |worker| {
///     worker.dataflow::<(),_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
///
/// The following example demonstrates how one can extract data from a multi-worker execution.
/// In a multi-process setting, each process will only receive those records present at workers
/// in the process.
///
/// ```rust
/// use std::sync::{Arc, Mutex};
/// use timely::dataflow::operators::{ToStream, Inspect, Capture};
/// use timely::dataflow::operators::capture::Extract;
///
/// // get send and recv endpoints, wrap send to share
/// let (send, recv) = ::std::sync::mpsc::channel();
/// let send = Arc::new(Mutex::new(send));
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute(timely::Configuration::Process(3), move |worker| {
///     let send = send.lock().unwrap().clone();
///     worker.dataflow::<(),_,_>(move |scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x))
///                .capture_into(send);
///     });
/// }).unwrap();
///
/// // the extracted data should have data (0..10) thrice at timestamp 0.
/// assert_eq!(recv.extract()[0].1, (0..30).map(|x| x / 3).collect::<Vec<_>>());
/// ```
pub fn execute<T, F>(mut config: Configuration, func: F) -> Result<WorkerGuards<T>,String>
where
    T:Send+'static,
    F: Fn(&mut Worker<Allocator>)->T+Send+Sync+'static {

    if let Configuration::Cluster { ref mut log_fn, .. } = config {

        *log_fn = Box::new(|events_setup| {

            let mut result = None;
            if let Ok(addr) = ::std::env::var("TIMELY_COMM_LOG_ADDR") {

                use ::std::net::TcpStream;
                use crate::logging::BatchLogger;
                use crate::dataflow::operators::capture::EventWriter;

                eprintln!("enabled COMM logging to {}", addr);

                if let Ok(stream) = TcpStream::connect(&addr) {
                    let writer = EventWriter::new(stream);
                    let mut logger = BatchLogger::new(writer);
                    result = Some(crate::logging_core::Logger::new(
                        ::std::time::Instant::now(),
                        events_setup,
                        move |time, data| logger.publish_batch(time, data)
                    ));
                }
                else {
                    panic!("Could not connect to communication log address: {:?}", addr);
                }
            }
            result
        });
    }

    let (allocators, other) = config.try_build()?;

    initialize_from(allocators, other, move |allocator| {

        let mut worker = Worker::new(allocator);

        // If an environment variable is set, use it as the default timely logging.
        if let Ok(addr) = ::std::env::var("TIMELY_WORKER_LOG_ADDR") {

            use ::std::net::TcpStream;
            use crate::logging::{BatchLogger, TimelyEvent};
            use crate::dataflow::operators::capture::EventWriter;

            if let Ok(stream) = TcpStream::connect(&addr) {
                let writer = EventWriter::new(stream);
                let mut logger = BatchLogger::new(writer);
                worker.log_register()
                    .insert::<TimelyEvent,_>("timely", move |time, data|
                        logger.publish_batch(time, data)
                    );
            }
            else {
                panic!("Could not connect logging stream to: {:?}", addr);
            }
        }

        let result = func(&mut worker);
        while worker.step() { }
        result
    })
}

/// Executes a timely dataflow from supplied arguments and per-communicator logic.
///
/// The `execute` method takes arguments (typically `std::env::args()`) and spins up some number of
/// workers threads, each of which execute the supplied closure to construct and run a timely
/// dataflow computation.
///
/// The closure may return a `T: Send+'static`, and `execute` returns a result
/// containing a `WorkerGuards<T>` (or error information), which can be joined
/// to recover the result `T` values from the local workers.
///
/// The arguments `execute` currently understands are:
///
/// `-w, --workers`: number of per-process worker threads.
///
/// `-n, --processes`: number of processes involved in the computation.
///
/// `-p, --process`: identity of this process; from 0 to n-1.
///
/// `-h, --hostfile`: a text file whose lines are "hostname:port" in order of process identity.
/// If not specified, `localhost` will be used, with port numbers increasing from 2101 (chosen
/// arbitrarily).
///
/// # Examples
///
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using command line parameters
/// timely::execute_from_args(std::env::args(), |worker| {
///     worker.dataflow::<(),_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
/// ```ignore
/// host0% cargo run -- -w 2 -n 4 -h hosts.txt -p 0
/// host1% cargo run -- -w 2 -n 4 -h hosts.txt -p 1
/// host2% cargo run -- -w 2 -n 4 -h hosts.txt -p 2
/// host3% cargo run -- -w 2 -n 4 -h hosts.txt -p 3
/// ```
/// ```ignore
/// % cat hosts.txt
/// host0:port
/// host1:port
/// host2:port
/// host3:port
/// ```
pub fn execute_from_args<I, T, F>(iter: I, func: F) -> Result<WorkerGuards<T>,String>
    where I: Iterator<Item=String>,
          T:Send+'static,
          F: Fn(&mut Worker<Allocator>)->T+Send+Sync+'static, {
    let configuration = Configuration::from_args(iter)?;
    execute(configuration, func)
}

/// Executes a timely dataflow from supplied allocators and logging.
///
/// Refer to [`execute`](fn.execute.html) for more details.
///
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using command line parameters
/// let (builders, other) = timely::Configuration::Process(3).try_build().unwrap();
/// timely::execute::execute_from(builders, other, |worker| {
///     worker.dataflow::<(),_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
pub fn execute_from<A, T, F>(builders: Vec<A>, others: Box<::std::any::Any>, func: F) -> Result<WorkerGuards<T>,String>
where
    A: AllocateBuilder+'static,
    T: Send+'static,
    F: Fn(&mut Worker<<A as AllocateBuilder>::Allocator>)->T+Send+Sync+'static {
    initialize_from(builders, others, move |allocator| {
        let mut worker = Worker::new(allocator);
        let result = func(&mut worker);
        while worker.step() { }
        result
    })
}<commit_msg>use step_or_park(None) in shutdown<commit_after>//! Starts a timely dataflow execution from configuration information and per-worker logic.

use crate::communication::{initialize_from, Configuration, Allocator, allocator::AllocateBuilder, WorkerGuards};
use crate::dataflow::scopes::Child;
use crate::worker::Worker;

/// Executes a single-threaded timely dataflow computation.
///
/// The `example` method takes a closure on a `Scope` which it executes to initialize and run a
/// timely dataflow computation on a single thread. This method is intended for use in examples,
/// rather than programs that may need to run across multiple workers.
///
/// The `example` method returns whatever the single worker returns from its closure.
/// This is often nothing, but the worker can return something about the data it saw in order to
/// test computations.
///
/// The method aggressively unwraps returned `Result<_>` types.
///
/// # Examples
///
/// The simplest example creates a stream of data and inspects it.
///
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// timely::example(|scope| {
///     (0..10).to_stream(scope)
///            .inspect(|x| println!("seen: {:?}", x));
/// });
/// ```
///
/// This next example captures the data and displays them once the computation is complete.
///
/// More precisely, the example captures a stream of events (receiving batches of data,
/// updates to input capabilities) and displays these events.
///
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect, Capture};
/// use timely::dataflow::operators::capture::Extract;
///
/// let data = timely::example(|scope| {
///     (0..10).to_stream(scope)
///            .inspect(|x| println!("seen: {:?}", x))
///            .capture()
/// });
///
/// // the extracted data should have data (0..10) at timestamp 0.
/// assert_eq!(data.extract()[0].1, (0..10).collect::<Vec<_>>());
/// ```
pub fn example<T, F>(func: F) -> T
where
    T: Send+'static,
    F: FnOnce(&mut Child<Worker<crate::communication::allocator::thread::Thread>,u64>)->T+Send+Sync+'static
{
    crate::execute::execute_directly(|worker| worker.dataflow(|scope| func(scope)))
}

/// Executes a single-threaded timely dataflow computation.
///
/// The `execute_directly` constructs a `Worker` and directly executes the supplied
/// closure to construct and run a timely dataflow computation. It does not create any
/// worker threads, and simply uses the current thread of control.
///
/// The closure may return a result, which will be returned from the computation.
///
/// # Examples
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute_directly(|worker| {
///     worker.dataflow::<(),_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// });
/// ```
pub fn execute_directly<T, F>(func: F) -> T
where
    T: Send+'static,
    F: FnOnce(&mut Worker<crate::communication::allocator::thread::Thread>)->T+Send+Sync+'static
{
    let alloc = crate::communication::allocator::thread::Thread::new();
    let mut worker = crate::worker::Worker::new(alloc);
    let result = func(&mut worker);
    while worker.step_or_park() { }
    result
}

/// Executes a timely dataflow from a configuration and per-communicator logic.
///
/// The `execute` method takes a `Configuration` and spins up some number of
/// workers threads, each of which execute the supplied closure to construct
/// and run a timely dataflow computation.
///
/// The closure may return a `T: Send+'static`, and `execute` returns a result
/// containing a `WorkerGuards<T>` (or error information), which can be joined
/// to recover the result `T` values from the local workers.
///
/// # Examples
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute(timely::Configuration::Process(3), |worker| {
///     worker.dataflow::<(),_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
///
/// The following example demonstrates how one can extract data from a multi-worker execution.
/// In a multi-process setting, each process will only receive those records present at workers
/// in the process.
///
/// ```rust
/// use std::sync::{Arc, Mutex};
/// use timely::dataflow::operators::{ToStream, Inspect, Capture};
/// use timely::dataflow::operators::capture::Extract;
///
/// // get send and recv endpoints, wrap send to share
/// let (send, recv) = ::std::sync::mpsc::channel();
/// let send = Arc::new(Mutex::new(send));
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute(timely::Configuration::Process(3), move |worker| {
///     let send = send.lock().unwrap().clone();
///     worker.dataflow::<(),_,_>(move |scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x))
///                .capture_into(send);
///     });
/// }).unwrap();
///
/// // the extracted data should have data (0..10) thrice at timestamp 0.
/// assert_eq!(recv.extract()[0].1, (0..30).map(|x| x / 3).collect::<Vec<_>>());
/// ```
pub fn execute<T, F>(mut config: Configuration, func: F) -> Result<WorkerGuards<T>,String>
where
    T:Send+'static,
    F: Fn(&mut Worker<Allocator>)->T+Send+Sync+'static {

    if let Configuration::Cluster { ref mut log_fn, .. } = config {

        *log_fn = Box::new(|events_setup| {

            let mut result = None;
            if let Ok(addr) = ::std::env::var("TIMELY_COMM_LOG_ADDR") {

                use ::std::net::TcpStream;
                use crate::logging::BatchLogger;
                use crate::dataflow::operators::capture::EventWriter;

                eprintln!("enabled COMM logging to {}", addr);

                if let Ok(stream) = TcpStream::connect(&addr) {
                    let writer = EventWriter::new(stream);
                    let mut logger = BatchLogger::new(writer);
                    result = Some(crate::logging_core::Logger::new(
                        ::std::time::Instant::now(),
                        events_setup,
                        move |time, data| logger.publish_batch(time, data)
                    ));
                }
                else {
                    panic!("Could not connect to communication log address: {:?}", addr);
                }
            }
            result
        });
    }

    let (allocators, other) = config.try_build()?;

    initialize_from(allocators, other, move |allocator| {

        let mut worker = Worker::new(allocator);

        // If an environment variable is set, use it as the default timely logging.
        if let Ok(addr) = ::std::env::var("TIMELY_WORKER_LOG_ADDR") {

            use ::std::net::TcpStream;
            use crate::logging::{BatchLogger, TimelyEvent};
            use crate::dataflow::operators::capture::EventWriter;

            if let Ok(stream) = TcpStream::connect(&addr) {
                let writer = EventWriter::new(stream);
                let mut logger = BatchLogger::new(writer);
                worker.log_register()
                    .insert::<TimelyEvent,_>("timely", move |time, data|
                        logger.publish_batch(time, data)
                    );
            }
            else {
                panic!("Could not connect logging stream to: {:?}", addr);
            }
        }

        let result = func(&mut worker);
        while worker.step_or_park(None) { }
        result
    })
}

/// Executes a timely dataflow from supplied arguments and per-communicator logic.
///
/// The `execute` method takes arguments (typically `std::env::args()`) and spins up some number of
/// workers threads, each of which execute the supplied closure to construct and run a timely
/// dataflow computation.
///
/// The closure may return a `T: Send+'static`, and `execute` returns a result
/// containing a `WorkerGuards<T>` (or error information), which can be joined
/// to recover the result `T` values from the local workers.
///
/// The arguments `execute` currently understands are:
///
/// `-w, --workers`: number of per-process worker threads.
///
/// `-n, --processes`: number of processes involved in the computation.
///
/// `-p, --process`: identity of this process; from 0 to n-1.
///
/// `-h, --hostfile`: a text file whose lines are "hostname:port" in order of process identity.
/// If not specified, `localhost` will be used, with port numbers increasing from 2101 (chosen
/// arbitrarily).
///
/// # Examples
///
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using command line parameters
/// timely::execute_from_args(std::env::args(), |worker| {
///     worker.dataflow::<(),_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
/// ```ignore
/// host0% cargo run -- -w 2 -n 4 -h hosts.txt -p 0
/// host1% cargo run -- -w 2 -n 4 -h hosts.txt -p 1
/// host2% cargo run -- -w 2 -n 4 -h hosts.txt -p 2
/// host3% cargo run -- -w 2 -n 4 -h hosts.txt -p 3
/// ```
/// ```ignore
/// % cat hosts.txt
/// host0:port
/// host1:port
/// host2:port
/// host3:port
/// ```
pub fn execute_from_args<I, T, F>(iter: I, func: F) -> Result<WorkerGuards<T>,String>
    where I: Iterator<Item=String>,
          T:Send+'static,
          F: Fn(&mut Worker<Allocator>)->T+Send+Sync+'static, {
    let configuration = Configuration::from_args(iter)?;
    execute(configuration, func)
}

/// Executes a timely dataflow from supplied allocators and logging.
///
/// Refer to [`execute`](fn.execute.html) for more details.
///
/// ```rust
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using command line parameters
/// let (builders, other) = timely::Configuration::Process(3).try_build().unwrap();
/// timely::execute::execute_from(builders, other, |worker| {
///     worker.dataflow::<(),_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
pub fn execute_from<A, T, F>(builders: Vec<A>, others: Box<::std::any::Any>, func: F) -> Result<WorkerGuards<T>,String>
where
    A: AllocateBuilder+'static,
    T: Send+'static,
    F: Fn(&mut Worker<<A as AllocateBuilder>::Allocator>)->T+Send+Sync+'static {
    initialize_from(builders, others, move |allocator| {
        let mut worker = Worker::new(allocator);
        let result = func(&mut worker);
        while worker.step_or_park(None) { }
        result
    })
}<|endoftext|>


<commit_before>// Because the memory map is so important to not be aliased, it is defined here, in one place
// The lower 256 PML4 entries are reserved for userspace
// Each PML4 entry references up to 512 GB of memory
// The top (511) PML4 is reserved for recursive mapping
// The second from the top (510) PML4 is reserved for the kernel
    /// The size of a single PML4
    pub const PML4_SIZE: usize = 0x0000_0080_0000_0000;
    pub const PML4_MASK: usize = 0x0000_ff80_0000_0000;

    /// Size of a page and frame
    pub const PAGE_SIZE: usize = 4096;

    /// Offset of recursive paging
    pub const RECURSIVE_PAGE_OFFSET: usize = (-(PML4_SIZE as isize)) as usize;
    pub const RECURSIVE_PAGE_PML4: usize = (RECURSIVE_PAGE_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset of kernel
    pub const KERNEL_OFFSET: usize = RECURSIVE_PAGE_OFFSET - PML4_SIZE;
    pub const KERNEL_PML4: usize = (KERNEL_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Kernel stack size - must be kept in sync with early_init.S. Used by memory::init
    pub const KERNEL_STACK_SIZE: usize = PAGE_SIZE;

    /// Offset to kernel heap
    pub const KERNEL_HEAP_OFFSET: usize = KERNEL_OFFSET - PML4_SIZE;
    pub const KERNEL_HEAP_PML4: usize = (KERNEL_HEAP_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Size of kernel heap
    pub const KERNEL_HEAP_SIZE: usize = 1 * 1024 * 1024; // 1 MB

    /// Offset of device map region
    pub const KERNEL_DEVMAP_OFFSET: usize = KERNEL_HEAP_OFFSET - PML4_SIZE;

    /// Offset of environment region
    pub const KERNEL_ENV_OFFSET: usize = KERNEL_DEVMAP_OFFSET - PML4_SIZE;

    /// Offset of temporary mapping for misc kernel bring-up actions
    pub const KERNEL_TMP_MISC_OFFSET: usize = KERNEL_ENV_OFFSET - PML4_SIZE;

    /// Offset to kernel percpu variables
    //TODO: Use 64-bit fs offset to enable this pub const KERNEL_PERCPU_OFFSET: usize = KERNEL_HEAP_OFFSET - PML4_SIZE;
    pub const KERNEL_PERCPU_OFFSET: usize = KERNEL_TMP_MISC_OFFSET - PML4_SIZE;

    /// Size of kernel percpu variables
    pub const KERNEL_PERCPU_SIZE: usize = 64 * 1024; // 64 KB

    /// Offset of physmap
    // This needs to match RMM's PHYS_OFFSET
    pub const PHYS_OFFSET: usize = 0xFFFF_FE00_0000_0000;
    pub const PHYS_PML4: usize = (PHYS_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user image
    pub const USER_OFFSET: usize = 0;
    pub const USER_PML4: usize = (USER_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user TCB
    pub const USER_TCB_OFFSET: usize = 0xB000_0000;

    /// Offset to user arguments
    pub const USER_ARG_OFFSET: usize = USER_OFFSET + PML4_SIZE/2;

    /// Offset to user heap
    pub const USER_HEAP_OFFSET: usize = USER_OFFSET + PML4_SIZE;
    pub const USER_HEAP_PML4: usize = (USER_HEAP_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user grants
    pub const USER_GRANT_OFFSET: usize = USER_HEAP_OFFSET + PML4_SIZE;
    pub const USER_GRANT_PML4: usize = (USER_GRANT_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user stack
    pub const USER_STACK_OFFSET: usize = USER_GRANT_OFFSET + PML4_SIZE;
    pub const USER_STACK_PML4: usize = (USER_STACK_OFFSET & PML4_MASK)/PML4_SIZE;
    /// Size of user stack
    pub const USER_STACK_SIZE: usize = 1024 * 1024; // 1 MB

    /// Offset to user sigstack
    pub const USER_SIGSTACK_OFFSET: usize = USER_STACK_OFFSET + PML4_SIZE;
    pub const USER_SIGSTACK_PML4: usize = (USER_SIGSTACK_OFFSET & PML4_MASK)/PML4_SIZE;
    /// Size of user sigstack
    pub const USER_SIGSTACK_SIZE: usize = 256 * 1024; // 256 KB

    /// Offset to user TLS
    pub const USER_TLS_OFFSET: usize = USER_SIGSTACK_OFFSET + PML4_SIZE;
    pub const USER_TLS_PML4: usize = (USER_TLS_OFFSET & PML4_MASK)/PML4_SIZE;
    // Maximum TLS allocated to each PID, should be approximately 8 MB
    pub const USER_TLS_SIZE: usize = PML4_SIZE / 65536;

    /// Offset to user temporary image (used when cloning)
    pub const USER_TMP_OFFSET: usize = USER_TLS_OFFSET + PML4_SIZE;
    pub const USER_TMP_PML4: usize = (USER_TMP_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user temporary heap (used when cloning)
    pub const USER_TMP_HEAP_OFFSET: usize = USER_TMP_OFFSET + PML4_SIZE;
    pub const USER_TMP_HEAP_PML4: usize = (USER_TMP_HEAP_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user temporary page for grants
    pub const USER_TMP_GRANT_OFFSET: usize = USER_TMP_HEAP_OFFSET + PML4_SIZE;
    pub const USER_TMP_GRANT_PML4: usize = (USER_TMP_GRANT_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user temporary stack (used when cloning)
    pub const USER_TMP_STACK_OFFSET: usize = USER_TMP_GRANT_OFFSET + PML4_SIZE;
    pub const USER_TMP_STACK_PML4: usize = (USER_TMP_STACK_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user temporary sigstack (used when cloning)
    pub const USER_TMP_SIGSTACK_OFFSET: usize = USER_TMP_STACK_OFFSET + PML4_SIZE;
    pub const USER_TMP_SIGSTACK_PML4: usize = (USER_TMP_SIGSTACK_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user temporary tls (used when cloning)
    pub const USER_TMP_TLS_OFFSET: usize = USER_TMP_SIGSTACK_OFFSET + PML4_SIZE;
    pub const USER_TMP_TLS_PML4: usize = (USER_TMP_TLS_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset for usage in other temporary pages
    pub const USER_TMP_MISC_OFFSET: usize = USER_TMP_TLS_OFFSET + PML4_SIZE;
    pub const USER_TMP_MISC_PML4: usize = (USER_TMP_MISC_OFFSET & PML4_MASK)/PML4_SIZE;
<commit_msg>Add KERNEL_PERCPU_PML4 on AArch64.<commit_after>// Because the memory map is so important to not be aliased, it is defined here, in one place
// The lower 256 PML4 entries are reserved for userspace
// Each PML4 entry references up to 512 GB of memory
// The top (511) PML4 is reserved for recursive mapping
// The second from the top (510) PML4 is reserved for the kernel
    /// The size of a single PML4
    pub const PML4_SIZE: usize = 0x0000_0080_0000_0000;
    pub const PML4_MASK: usize = 0x0000_ff80_0000_0000;

    /// Size of a page and frame
    pub const PAGE_SIZE: usize = 4096;

    /// Offset of recursive paging
    pub const RECURSIVE_PAGE_OFFSET: usize = (-(PML4_SIZE as isize)) as usize;
    pub const RECURSIVE_PAGE_PML4: usize = (RECURSIVE_PAGE_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset of kernel
    pub const KERNEL_OFFSET: usize = RECURSIVE_PAGE_OFFSET - PML4_SIZE;
    pub const KERNEL_PML4: usize = (KERNEL_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Kernel stack size - must be kept in sync with early_init.S. Used by memory::init
    pub const KERNEL_STACK_SIZE: usize = PAGE_SIZE;

    /// Offset to kernel heap
    pub const KERNEL_HEAP_OFFSET: usize = KERNEL_OFFSET - PML4_SIZE;
    pub const KERNEL_HEAP_PML4: usize = (KERNEL_HEAP_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Size of kernel heap
    pub const KERNEL_HEAP_SIZE: usize = 1 * 1024 * 1024; // 1 MB

    /// Offset of device map region
    pub const KERNEL_DEVMAP_OFFSET: usize = KERNEL_HEAP_OFFSET - PML4_SIZE;

    /// Offset of environment region
    pub const KERNEL_ENV_OFFSET: usize = KERNEL_DEVMAP_OFFSET - PML4_SIZE;

    /// Offset of temporary mapping for misc kernel bring-up actions
    pub const KERNEL_TMP_MISC_OFFSET: usize = KERNEL_ENV_OFFSET - PML4_SIZE;

    /// Offset to kernel percpu variables
    pub const KERNEL_PERCPU_OFFSET: usize = KERNEL_TMP_MISC_OFFSET - PML4_SIZE;
    pub const KERNEL_PERCPU_PML4: usize = (KERNEL_PERCPU_OFFSET & PML4_MASK) / PML4_SIZE;

    /// Size of kernel percpu variables
    pub const KERNEL_PERCPU_SIZE: usize = 64 * 1024; // 64 KB

    /// Offset of physmap
    // This needs to match RMM's PHYS_OFFSET
    pub const PHYS_OFFSET: usize = 0xFFFF_FE00_0000_0000;
    pub const PHYS_PML4: usize = (PHYS_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user image
    pub const USER_OFFSET: usize = 0;
    pub const USER_PML4: usize = (USER_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user TCB
    pub const USER_TCB_OFFSET: usize = 0xB000_0000;

    /// Offset to user arguments
    pub const USER_ARG_OFFSET: usize = USER_OFFSET + PML4_SIZE/2;

    /// Offset to user heap
    pub const USER_HEAP_OFFSET: usize = USER_OFFSET + PML4_SIZE;
    pub const USER_HEAP_PML4: usize = (USER_HEAP_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user grants
    pub const USER_GRANT_OFFSET: usize = USER_HEAP_OFFSET + PML4_SIZE;
    pub const USER_GRANT_PML4: usize = (USER_GRANT_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user stack
    pub const USER_STACK_OFFSET: usize = USER_GRANT_OFFSET + PML4_SIZE;
    pub const USER_STACK_PML4: usize = (USER_STACK_OFFSET & PML4_MASK)/PML4_SIZE;
    /// Size of user stack
    pub const USER_STACK_SIZE: usize = 1024 * 1024; // 1 MB

    /// Offset to user sigstack
    pub const USER_SIGSTACK_OFFSET: usize = USER_STACK_OFFSET + PML4_SIZE;
    pub const USER_SIGSTACK_PML4: usize = (USER_SIGSTACK_OFFSET & PML4_MASK)/PML4_SIZE;
    /// Size of user sigstack
    pub const USER_SIGSTACK_SIZE: usize = 256 * 1024; // 256 KB

    /// Offset to user TLS
    pub const USER_TLS_OFFSET: usize = USER_SIGSTACK_OFFSET + PML4_SIZE;
    pub const USER_TLS_PML4: usize = (USER_TLS_OFFSET & PML4_MASK)/PML4_SIZE;
    // Maximum TLS allocated to each PID, should be approximately 8 MB
    pub const USER_TLS_SIZE: usize = PML4_SIZE / 65536;

    /// Offset to user temporary image (used when cloning)
    pub const USER_TMP_OFFSET: usize = USER_TLS_OFFSET + PML4_SIZE;
    pub const USER_TMP_PML4: usize = (USER_TMP_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user temporary heap (used when cloning)
    pub const USER_TMP_HEAP_OFFSET: usize = USER_TMP_OFFSET + PML4_SIZE;
    pub const USER_TMP_HEAP_PML4: usize = (USER_TMP_HEAP_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user temporary page for grants
    pub const USER_TMP_GRANT_OFFSET: usize = USER_TMP_HEAP_OFFSET + PML4_SIZE;
    pub const USER_TMP_GRANT_PML4: usize = (USER_TMP_GRANT_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user temporary stack (used when cloning)
    pub const USER_TMP_STACK_OFFSET: usize = USER_TMP_GRANT_OFFSET + PML4_SIZE;
    pub const USER_TMP_STACK_PML4: usize = (USER_TMP_STACK_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user temporary sigstack (used when cloning)
    pub const USER_TMP_SIGSTACK_OFFSET: usize = USER_TMP_STACK_OFFSET + PML4_SIZE;
    pub const USER_TMP_SIGSTACK_PML4: usize = (USER_TMP_SIGSTACK_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset to user temporary tls (used when cloning)
    pub const USER_TMP_TLS_OFFSET: usize = USER_TMP_SIGSTACK_OFFSET + PML4_SIZE;
    pub const USER_TMP_TLS_PML4: usize = (USER_TMP_TLS_OFFSET & PML4_MASK)/PML4_SIZE;

    /// Offset for usage in other temporary pages
    pub const USER_TMP_MISC_OFFSET: usize = USER_TMP_TLS_OFFSET + PML4_SIZE;
    pub const USER_TMP_MISC_PML4: usize = (USER_TMP_MISC_OFFSET & PML4_MASK)/PML4_SIZE;
<|endoftext|>


<commit_before>extern crate badger;

use badger::*;

fn output_program(input_program: &str) -> Result<String, Vec<String>> {
    let program = parser::parse(input_program.into());
    let ast = transformer::traverse(program);
    codegen::generate_code(ast)
}

#[test]
fn convert_const_to_var_in_global_scope() {
    assert_eq!(output_program("const pi = 3.14"),
               Ok("var pi = 3.14;".into()));
}

#[test]
fn convert_let_to_var_in_global_scope() {
    assert_eq!(output_program("let pi = 3.14"),
               Ok("var pi = 3.14;".into()));
}

#[test]
fn dont_touch_var_in_global_scope() {
    assert_eq!(output_program("var pi = 3.14"),
               Ok("var pi = 3.14;".into()));
}

#[test]
fn convert_let_to_var_in_block() {
    let program = "if(true) {
      let pi = 3.14;
    }
    ";

    let expected = "if(true){var _pi = 3.14;}";

    assert_eq!(output_program(program), Ok(expected.into()));
}
<commit_msg>Fixed and streamlined the codegen tests a bit<commit_after>extern crate badger;

use badger::*;

fn output_program(input_program: &str) -> String {
    let program = parser::parse(input_program.to_string());
    let ast = transformer::traverse(program);
    codegen::generate_code(ast, false)
}

macro_rules! assert_compile {
    ($string:expr, $expect:expr) => {
        assert_eq!(output_program($string), $expect.to_string());
    }
}

#[test]
fn convert_const_to_var_in_global_scope() {
    assert_compile!("const pi = 3.14", "var pi = 3.14;\n");
}

#[test]
fn convert_let_to_var_in_global_scope() {
    assert_compile!("let pi = 3.14", "var pi = 3.14;\n");
}

#[test]
fn dont_touch_var_in_global_scope() {
    assert_compile!("var pi = 3.14", "var pi = 3.14;\n");
}

#[test]
fn convert_let_to_var_in_block() {
    let program = "if(true) {
      let pi = 3.14;
    }
    ";

    let expected = "if(true){var _pi = 3.14;}";

    assert_compile!(program, expected);
}
<|endoftext|>


<commit_before>extern crate rs_nes;

use rs_nes::memory::{Memory, MemoryError};

#[test]
fn store_and_load_smoke_test() {
  let mut mem = Memory::new();
  let stored = 0xB;
  let _ = mem.store(0x0, stored);
  let loaded = mem.load(0x0).unwrap();
  assert_eq!(stored, loaded);
}

#[test]
fn ram_should_be_mirrored() {
  let mut mem = Memory::new();
  let stored = 0xB;
  let _ = mem.store(0x0, stored);
  let mirror1 = mem.load(0x800).unwrap();
  let mirror2 = mem.load(0x1000).unwrap();
  let mirror3 = mem.load(0x1800).unwrap();
  assert_eq!(stored, mirror1);
  assert_eq!(stored, mirror2);
  assert_eq!(stored, mirror3);
}

#[test]
fn write_to_mirrored_ram_returns_error() {
  let mut mem = Memory::new();
  match mem.store(0x1000, 0x0) {
    Err(MemoryError::WriteToMirror) => { /* expected */ },
    _ => assert!(false)
  }
}

#[test]
fn write_to_rom_returns_error() {
  let mut mem = Memory::new();
  match mem.store(0x8000, 0x0) {
    Err(MemoryError::WriteToROM) => { /* expected */ },
    _ => assert!(false)
  }
}

#[test]
fn out_of_bounds_address_returns_error() {
  let mut mem = Memory::new();
  match mem.store(0xffffff, 0xb) {
    Err(MemoryError::AddressOutOfBounds) => { /* expected */ },
    _ => assert!(false)
  };
}
<commit_msg>Renamed some tests<commit_after>extern crate rs_nes;

use rs_nes::memory::{Memory, MemoryError};

#[test]
fn store_and_load_from_ram_succeeds() {
  let mut mem = Memory::new();
  let stored = 0xB;
  let _ = mem.store(0x0, stored);
  let loaded = mem.load(0x0).unwrap();
  assert_eq!(stored, loaded);
}

#[test]
fn ram_should_be_mirrored() {
  let mut mem = Memory::new();
  let stored = 0xB;
  let _ = mem.store(0x0, stored);
  let mirror1 = mem.load(0x800).unwrap();
  let mirror2 = mem.load(0x1000).unwrap();
  let mirror3 = mem.load(0x1800).unwrap();
  assert_eq!(stored, mirror1);
  assert_eq!(stored, mirror2);
  assert_eq!(stored, mirror3);
}

#[test]
fn write_to_mirrored_ram_should_error() {
  let mut mem = Memory::new();
  match mem.store(0x1000, 0x0) {
    Err(MemoryError::WriteToMirror) => { /* expected */ },
    _ => assert!(false)
  }
}

#[test]
fn store_to_rom_should_error() {
  let mut mem = Memory::new();
  match mem.store(0x8000, 0x0) {
    Err(MemoryError::WriteToROM) => { /* expected */ },
    _ => assert!(false)
  }
}

#[test]
fn store_out_of_bounds_address_returns_error() {
  let mut mem = Memory::new();
  match mem.store(0xffffff, 0xb) {
    Err(MemoryError::AddressOutOfBounds) => { /* expected */ },
    _ => assert!(false)
  };
}
<|endoftext|>