Implement Send for Instance

This commit is contained in:
Mark McCaskey
2019-09-17 10:37:37 -07:00
parent 90dfb0f7a7
commit 17a0e78cef
5 changed files with 71 additions and 32 deletions

View File

@ -536,9 +536,8 @@ fn import_functions(
let namespace = module.info.namespace_table.get(*namespace_index); let namespace = module.info.namespace_table.get(*namespace_index);
let name = module.info.name_table.get(*name_index); let name = module.info.name_table.get(*name_index);
let import = imports let import =
.get_namespace(namespace) imports.maybe_with_namespace(namespace, |namespace| namespace.get_export(name));
.and_then(|namespace| namespace.get_export(name));
match import { match import {
Some(Export::Function { Some(Export::Function {
func, func,
@ -624,9 +623,8 @@ fn import_memories(
let namespace = module.info.namespace_table.get(*namespace_index); let namespace = module.info.namespace_table.get(*namespace_index);
let name = module.info.name_table.get(*name_index); let name = module.info.name_table.get(*name_index);
let memory_import = imports let memory_import =
.get_namespace(&namespace) imports.maybe_with_namespace(namespace, |namespace| namespace.get_export(name));
.and_then(|namespace| namespace.get_export(&name));
match memory_import { match memory_import {
Some(Export::Memory(memory)) => { Some(Export::Memory(memory)) => {
if expected_memory_desc.fits_in_imported(memory.descriptor()) { if expected_memory_desc.fits_in_imported(memory.descriptor()) {
@ -696,9 +694,8 @@ fn import_tables(
let namespace = module.info.namespace_table.get(*namespace_index); let namespace = module.info.namespace_table.get(*namespace_index);
let name = module.info.name_table.get(*name_index); let name = module.info.name_table.get(*name_index);
let table_import = imports let table_import =
.get_namespace(&namespace) imports.maybe_with_namespace(namespace, |namespace| namespace.get_export(name));
.and_then(|namespace| namespace.get_export(&name));
match table_import { match table_import {
Some(Export::Table(mut table)) => { Some(Export::Table(mut table)) => {
if expected_table_desc.fits_in_imported(table.descriptor()) { if expected_table_desc.fits_in_imported(table.descriptor()) {
@ -767,9 +764,8 @@ fn import_globals(
{ {
let namespace = module.info.namespace_table.get(*namespace_index); let namespace = module.info.namespace_table.get(*namespace_index);
let name = module.info.name_table.get(*name_index); let name = module.info.name_table.get(*name_index);
let import = imports let import =
.get_namespace(namespace) imports.maybe_with_namespace(namespace, |namespace| namespace.get_export(name));
.and_then(|namespace| namespace.get_export(name));
match import { match import {
Some(Export::Global(mut global)) => { Some(Export::Global(mut global)) => {
if global.descriptor() == *imported_global_desc { if global.descriptor() == *imported_global_desc {

View File

@ -11,6 +11,8 @@ pub enum Context {
Internal, Internal,
} }
unsafe impl Send for Context {}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Export { pub enum Export {
Function { Function {
@ -26,6 +28,8 @@ pub enum Export {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct FuncPointer(*const vm::Func); pub struct FuncPointer(*const vm::Func);
unsafe impl Send for FuncPointer {}
impl FuncPointer { impl FuncPointer {
/// This needs to be unsafe because there is /// This needs to be unsafe because there is
/// no way to check whether the passed function /// no way to check whether the passed function

View File

@ -4,11 +4,11 @@ use crate::{
types::{GlobalDescriptor, Type, Value}, types::{GlobalDescriptor, Type, Value},
vm, vm,
}; };
use std::{cell::RefCell, fmt, rc::Rc}; use std::{cell::RefCell, fmt, sync::Arc};
pub struct Global { pub struct Global {
desc: GlobalDescriptor, desc: GlobalDescriptor,
storage: Rc<RefCell<vm::LocalGlobal>>, storage: Arc<RefCell<vm::LocalGlobal>>,
} }
impl Global { impl Global {
@ -56,7 +56,7 @@ impl Global {
Self { Self {
desc, desc,
storage: Rc::new(RefCell::new(local_global)), storage: Arc::new(RefCell::new(local_global)),
} }
} }
@ -120,7 +120,7 @@ impl Clone for Global {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
desc: self.desc, desc: self.desc,
storage: Rc::clone(&self.storage), storage: Arc::clone(&self.storage),
} }
} }
} }

View File

@ -2,9 +2,9 @@ use crate::export::Export;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::collections::{hash_map::Entry, HashMap}; use std::collections::{hash_map::Entry, HashMap};
use std::{ use std::{
cell::{Ref, RefCell}, borrow::{Borrow, BorrowMut},
ffi::c_void, ffi::c_void,
rc::Rc, sync::{Arc, Mutex},
}; };
pub trait LikeNamespace { pub trait LikeNamespace {
@ -45,8 +45,8 @@ impl IsExport for Export {
/// } /// }
/// ``` /// ```
pub struct ImportObject { pub struct ImportObject {
map: Rc<RefCell<HashMap<String, Box<dyn LikeNamespace>>>>, map: Arc<Mutex<HashMap<String, Box<dyn LikeNamespace + Send>>>>,
pub(crate) state_creator: Option<Rc<dyn Fn() -> (*mut c_void, fn(*mut c_void))>>, pub(crate) state_creator: Option<Arc<dyn Fn() -> (*mut c_void, fn(*mut c_void)) + Send>>,
pub allow_missing_functions: bool, pub allow_missing_functions: bool,
} }
@ -54,7 +54,7 @@ impl ImportObject {
/// Create a new `ImportObject`. /// Create a new `ImportObject`.
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
map: Rc::new(RefCell::new(HashMap::new())), map: Arc::new(Mutex::new(HashMap::new())),
state_creator: None, state_creator: None,
allow_missing_functions: false, allow_missing_functions: false,
} }
@ -62,11 +62,11 @@ impl ImportObject {
pub fn new_with_data<F>(state_creator: F) -> Self pub fn new_with_data<F>(state_creator: F) -> Self
where where
F: Fn() -> (*mut c_void, fn(*mut c_void)) + 'static, F: Fn() -> (*mut c_void, fn(*mut c_void)) + 'static + Send,
{ {
Self { Self {
map: Rc::new(RefCell::new(HashMap::new())), map: Arc::new(Mutex::new(HashMap::new())),
state_creator: Some(Rc::new(state_creator)), state_creator: Some(Arc::new(state_creator)),
allow_missing_functions: false, allow_missing_functions: false,
} }
} }
@ -92,9 +92,10 @@ impl ImportObject {
pub fn register<S, N>(&mut self, name: S, namespace: N) -> Option<Box<dyn LikeNamespace>> pub fn register<S, N>(&mut self, name: S, namespace: N) -> Option<Box<dyn LikeNamespace>>
where where
S: Into<String>, S: Into<String>,
N: LikeNamespace + 'static, N: LikeNamespace + Send + 'static,
{ {
let mut map = self.map.borrow_mut(); let mut guard = self.map.lock().unwrap();
let map = guard.borrow_mut();
match map.entry(name.into()) { match map.entry(name.into()) {
Entry::Vacant(empty) => { Entry::Vacant(empty) => {
@ -105,19 +106,50 @@ impl ImportObject {
} }
} }
pub fn get_namespace(&self, namespace: &str) -> Option<Ref<dyn LikeNamespace + 'static>> { /*pub fn get_namespace(
let map_ref = self.map.borrow(); &self,
namespace: &str,
) -> Option<
MutexGuardRef<HashMap<String, Box<dyn LikeNamespace + Send>>, &(dyn LikeNamespace + Send)>,
> {
MutexGuardRef::new(self.map.lock().unwrap())
.try_map(|mg| mg.get(namespace).map(|ns| &ns.as_ref()).ok_or(()))
.ok()
}*/
/// Apply a function on the namespace if it exists
/// If your function can fail, consider using `maybe_with_namespace`
pub fn with_namespace<Func, InnerRet>(&self, namespace: &str, f: Func) -> Option<InnerRet>
where
Func: FnOnce(&(dyn LikeNamespace + Send)) -> InnerRet,
InnerRet: Sized,
{
let guard = self.map.lock().unwrap();
let map_ref = guard.borrow();
if map_ref.contains_key(namespace) { if map_ref.contains_key(namespace) {
Some(Ref::map(map_ref, |map| &*map[namespace])) Some(f(map_ref[namespace].as_ref()))
} else { } else {
None None
} }
} }
/// The same as `with_namespace` but takes a function that may fail
pub fn maybe_with_namespace<Func, InnerRet>(&self, namespace: &str, f: Func) -> Option<InnerRet>
where
Func: FnOnce(&(dyn LikeNamespace + Send)) -> Option<InnerRet>,
InnerRet: Sized,
{
let guard = self.map.lock().unwrap();
let map_ref = guard.borrow();
map_ref
.get(namespace)
.map(|ns| ns.as_ref())
.and_then(|ns| f(ns))
}
pub fn clone_ref(&self) -> Self { pub fn clone_ref(&self) -> Self {
Self { Self {
map: Rc::clone(&self.map), map: Arc::clone(&self.map),
state_creator: self.state_creator.clone(), state_creator: self.state_creator.clone(),
allow_missing_functions: false, allow_missing_functions: false,
} }
@ -125,7 +157,9 @@ impl ImportObject {
fn get_objects(&self) -> VecDeque<(String, String, Export)> { fn get_objects(&self) -> VecDeque<(String, String, Export)> {
let mut out = VecDeque::new(); let mut out = VecDeque::new();
for (name, ns) in self.map.borrow().iter() { let guard = self.map.lock().unwrap();
let map = guard.borrow();
for (name, ns) in map.iter() {
for (id, exp) in ns.get_exports() { for (id, exp) in ns.get_exports() {
out.push_back((name.clone(), id, exp)); out.push_back((name.clone(), id, exp));
} }
@ -158,7 +192,8 @@ impl IntoIterator for ImportObject {
impl Extend<(String, String, Export)> for ImportObject { impl Extend<(String, String, Export)> for ImportObject {
fn extend<T: IntoIterator<Item = (String, String, Export)>>(&mut self, iter: T) { fn extend<T: IntoIterator<Item = (String, String, Export)>>(&mut self, iter: T) {
let mut map = self.map.borrow_mut(); let mut guard = self.map.lock().unwrap();
let map = guard.borrow_mut();
for (ns, id, exp) in iter.into_iter() { for (ns, id, exp) in iter.into_iter() {
if let Some(like_ns) = map.get_mut(&ns) { if let Some(like_ns) = map.get_mut(&ns) {
like_ns.maybe_insert(&id, exp); like_ns.maybe_insert(&id, exp);
@ -175,6 +210,8 @@ pub struct Namespace {
map: HashMap<String, Box<dyn IsExport>>, map: HashMap<String, Box<dyn IsExport>>,
} }
unsafe impl Send for Namespace {}
impl Namespace { impl Namespace {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {

View File

@ -165,6 +165,8 @@ pub struct Func<'a, Args = (), Rets = (), Inner: Kind = Wasm> {
_phantom: PhantomData<(&'a (), Args, Rets)>, _phantom: PhantomData<(&'a (), Args, Rets)>,
} }
unsafe impl<'a, Args, Rets> Send for Func<'a, Args, Rets> {}
impl<'a, Args, Rets> Func<'a, Args, Rets, Wasm> impl<'a, Args, Rets> Func<'a, Args, Rets, Wasm>
where where
Args: WasmTypeList, Args: WasmTypeList,