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 name = module.info.name_table.get(*name_index);
let import = imports
.get_namespace(namespace)
.and_then(|namespace| namespace.get_export(name));
let import =
imports.maybe_with_namespace(namespace, |namespace| namespace.get_export(name));
match import {
Some(Export::Function {
func,
@ -624,9 +623,8 @@ fn import_memories(
let namespace = module.info.namespace_table.get(*namespace_index);
let name = module.info.name_table.get(*name_index);
let memory_import = imports
.get_namespace(&namespace)
.and_then(|namespace| namespace.get_export(&name));
let memory_import =
imports.maybe_with_namespace(namespace, |namespace| namespace.get_export(name));
match memory_import {
Some(Export::Memory(memory)) => {
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 name = module.info.name_table.get(*name_index);
let table_import = imports
.get_namespace(&namespace)
.and_then(|namespace| namespace.get_export(&name));
let table_import =
imports.maybe_with_namespace(namespace, |namespace| namespace.get_export(name));
match table_import {
Some(Export::Table(mut table)) => {
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 name = module.info.name_table.get(*name_index);
let import = imports
.get_namespace(namespace)
.and_then(|namespace| namespace.get_export(name));
let import =
imports.maybe_with_namespace(namespace, |namespace| namespace.get_export(name));
match import {
Some(Export::Global(mut global)) => {
if global.descriptor() == *imported_global_desc {

View File

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

View File

@ -4,11 +4,11 @@ use crate::{
types::{GlobalDescriptor, Type, Value},
vm,
};
use std::{cell::RefCell, fmt, rc::Rc};
use std::{cell::RefCell, fmt, sync::Arc};
pub struct Global {
desc: GlobalDescriptor,
storage: Rc<RefCell<vm::LocalGlobal>>,
storage: Arc<RefCell<vm::LocalGlobal>>,
}
impl Global {
@ -56,7 +56,7 @@ impl Global {
Self {
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 {
Self {
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::{hash_map::Entry, HashMap};
use std::{
cell::{Ref, RefCell},
borrow::{Borrow, BorrowMut},
ffi::c_void,
rc::Rc,
sync::{Arc, Mutex},
};
pub trait LikeNamespace {
@ -45,8 +45,8 @@ impl IsExport for Export {
/// }
/// ```
pub struct ImportObject {
map: Rc<RefCell<HashMap<String, Box<dyn LikeNamespace>>>>,
pub(crate) state_creator: Option<Rc<dyn Fn() -> (*mut c_void, fn(*mut c_void))>>,
map: Arc<Mutex<HashMap<String, Box<dyn LikeNamespace + Send>>>>,
pub(crate) state_creator: Option<Arc<dyn Fn() -> (*mut c_void, fn(*mut c_void)) + Send>>,
pub allow_missing_functions: bool,
}
@ -54,7 +54,7 @@ impl ImportObject {
/// Create a new `ImportObject`.
pub fn new() -> Self {
Self {
map: Rc::new(RefCell::new(HashMap::new())),
map: Arc::new(Mutex::new(HashMap::new())),
state_creator: None,
allow_missing_functions: false,
}
@ -62,11 +62,11 @@ impl ImportObject {
pub fn new_with_data<F>(state_creator: F) -> Self
where
F: Fn() -> (*mut c_void, fn(*mut c_void)) + 'static,
F: Fn() -> (*mut c_void, fn(*mut c_void)) + 'static + Send,
{
Self {
map: Rc::new(RefCell::new(HashMap::new())),
state_creator: Some(Rc::new(state_creator)),
map: Arc::new(Mutex::new(HashMap::new())),
state_creator: Some(Arc::new(state_creator)),
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>>
where
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()) {
Entry::Vacant(empty) => {
@ -105,19 +106,50 @@ impl ImportObject {
}
}
pub fn get_namespace(&self, namespace: &str) -> Option<Ref<dyn LikeNamespace + 'static>> {
let map_ref = self.map.borrow();
/*pub fn get_namespace(
&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) {
Some(Ref::map(map_ref, |map| &*map[namespace]))
Some(f(map_ref[namespace].as_ref()))
} else {
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 {
Self {
map: Rc::clone(&self.map),
map: Arc::clone(&self.map),
state_creator: self.state_creator.clone(),
allow_missing_functions: false,
}
@ -125,7 +157,9 @@ impl ImportObject {
fn get_objects(&self) -> VecDeque<(String, String, Export)> {
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() {
out.push_back((name.clone(), id, exp));
}
@ -158,7 +192,8 @@ impl IntoIterator for ImportObject {
impl Extend<(String, String, Export)> for ImportObject {
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() {
if let Some(like_ns) = map.get_mut(&ns) {
like_ns.maybe_insert(&id, exp);
@ -175,6 +210,8 @@ pub struct Namespace {
map: HashMap<String, Box<dyn IsExport>>,
}
unsafe impl Send for Namespace {}
impl Namespace {
pub fn new() -> Self {
Self {

View File

@ -165,6 +165,8 @@ pub struct Func<'a, Args = (), Rets = (), Inner: Kind = Wasm> {
_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>
where
Args: WasmTypeList,