From a4f59cabf79a60125e1f7243f18a610599e678f9 Mon Sep 17 00:00:00 2001 From: Ian Ker-Seymer Date: Wed, 29 Nov 2023 11:14:40 -0500 Subject: [PATCH] Make Send and Sync impls an opt-in feature --- ext/Cargo.toml | 8 +++++++- ext/src/helpers/macros.rs | 17 +++++++++++++++++ ext/src/ruby_api/caller.rs | 3 ++- ext/src/ruby_api/convert.rs | 6 +++--- ext/src/ruby_api/instance.rs | 4 ++-- ext/src/ruby_api/linker.rs | 4 ++-- ext/src/ruby_api/memory.rs | 5 +++-- ext/src/ruby_api/module.rs | 2 +- ext/src/ruby_api/store.rs | 5 ++--- 9 files changed, 39 insertions(+), 15 deletions(-) diff --git a/ext/Cargo.toml b/ext/Cargo.toml index 26439283..02577bce 100644 --- a/ext/Cargo.toml +++ b/ext/Cargo.toml @@ -14,10 +14,16 @@ tokio = ["dep:tokio", "dep:async-timer"] all-arch = ["wasmtime/all-arch"] ruby-api = [] winch = ["wasmtime/winch"] +unsafe-impl-sync = [] +unsafe-impl-send = [] +unsafe-impl-send-sync = ["unsafe-impl-send", "unsafe-impl-sync"] [dependencies] lazy_static = "1.4.0" -magnus = { version = "0.6", features = ["rb-sys", "deprecated-send-sync-value"] } +magnus = { version = "0.6", features = [ + "rb-sys", + "deprecated-send-sync-value", +] } rb-sys = { version = "*", default-features = false, features = [ "stable-api-compiled-fallback", ] } diff --git a/ext/src/helpers/macros.rs b/ext/src/helpers/macros.rs index bfe7115d..eb7ad9a2 100644 --- a/ext/src/helpers/macros.rs +++ b/ext/src/helpers/macros.rs @@ -10,3 +10,20 @@ macro_rules! define_rb_intern { )* }; } + +/// Boilerplate for defining send and sync on a Magnus struct when the feature is enabled. +#[macro_export] +macro_rules! unsafe_impl_send_sync { + ($struct:ident) => { + #[cfg(feature = "unsafe-impl-send")] + unsafe impl Send for $struct {} + #[cfg(feature = "unsafe-impl-sync")] + unsafe impl Sync for $struct {} + }; + ($struct:ident <'_>) => { + #[cfg(feature = "unsafe-impl-send")] + unsafe impl Send for $struct<'_> {} + #[cfg(feature = "unsafe-impl-sync")] + unsafe impl Sync for $struct<'_> {} + }; +} diff --git a/ext/src/ruby_api/caller.rs b/ext/src/ruby_api/caller.rs index dd6149c3..3876fbe3 100644 --- a/ext/src/ruby_api/caller.rs +++ b/ext/src/ruby_api/caller.rs @@ -1,4 +1,5 @@ use super::{convert::WrapWasmtimeType, externals::Extern, root, store::StoreData}; +use crate::{error, unsafe_impl_send_sync}; use magnus::{ class, gc::{Compactor, Marker}, @@ -143,7 +144,7 @@ impl<'a> Caller<'a> { } } -unsafe impl Send for Caller<'_> {} +unsafe_impl_send_sync!(Caller); pub fn init() -> Result<(), Error> { let klass = root().define_class("Caller", class::object())?; diff --git a/ext/src/ruby_api/convert.rs b/ext/src/ruby_api/convert.rs index dd7ccc70..4abaa6cf 100644 --- a/ext/src/ruby_api/convert.rs +++ b/ext/src/ruby_api/convert.rs @@ -1,4 +1,4 @@ -use crate::{define_rb_intern, err, error, helpers::SymbolEnum}; +use crate::{define_rb_intern, err, error, helpers::SymbolEnum, unsafe_impl_send_sync}; use lazy_static::lazy_static; use magnus::{prelude::*, Error, IntoValue, RArray, Ruby, Symbol, TryConvert, TypedData, Value}; use wasmtime::{ExternRef, Val, ValType}; @@ -95,8 +95,8 @@ impl From for ExternRefValue { Self(v) } } -unsafe impl Send for ExternRefValue {} -unsafe impl Sync for ExternRefValue {} + +unsafe_impl_send_sync!(ExternRefValue); pub trait ToExtern { fn to_extern(&self, ruby: &Ruby) -> Result; diff --git a/ext/src/ruby_api/instance.rs b/ext/src/ruby_api/instance.rs index ba1c5360..1880b6d3 100644 --- a/ext/src/ruby_api/instance.rs +++ b/ext/src/ruby_api/instance.rs @@ -5,7 +5,7 @@ use super::{ root, store::{Store, StoreContextValue, StoreData}, }; -use crate::err; +use crate::{err, unsafe_impl_send_sync}; use magnus::{ class, function, gc::Marker, method, prelude::*, scan_args, typed_data::Obj, DataTypeFunctions, Error, Object, RArray, RHash, RString, Ruby, TryConvert, TypedData, Value, @@ -22,7 +22,7 @@ pub struct Instance { store: Obj, } -unsafe impl Send for Instance {} +unsafe_impl_send_sync!(Instance); impl DataTypeFunctions for Instance { fn mark(&self, marker: &Marker) { diff --git a/ext/src/ruby_api/linker.rs b/ext/src/ruby_api/linker.rs index 0d92b5f0..d8ba2f34 100644 --- a/ext/src/ruby_api/linker.rs +++ b/ext/src/ruby_api/linker.rs @@ -9,7 +9,7 @@ use super::{ root, store::{Store, StoreContextValue, StoreData}, }; -use crate::{define_rb_intern, err, error}; +use crate::{define_rb_intern, err, error, unsafe_impl_send_sync}; use magnus::{ block::Proc, class, function, gc::Marker, method, prelude::*, scan_args, scan_args::scan_args, typed_data::Obj, DataTypeFunctions, Error, Object, RArray, RHash, RString, Ruby, TypedData, @@ -32,7 +32,7 @@ pub struct Linker { has_wasi: bool, } -unsafe impl Send for Linker {} +unsafe_impl_send_sync!(Linker); impl DataTypeFunctions for Linker { fn mark(&self, marker: &Marker) { diff --git a/ext/src/ruby_api/memory.rs b/ext/src/ruby_api/memory.rs index 0802aea6..861a88ed 100644 --- a/ext/src/ruby_api/memory.rs +++ b/ext/src/ruby_api/memory.rs @@ -5,7 +5,7 @@ use super::{ root, store::{Store, StoreContextValue}, }; -use crate::{define_rb_intern, error}; +use crate::{define_rb_intern, error, unsafe_impl_send_sync}; use magnus::{ class, function, gc::Marker, method, r_string::RString, scan_args, typed_data::Obj, DataTypeFunctions, Error, Module as _, Object, Ruby, TypedData, Value, @@ -31,12 +31,13 @@ pub struct Memory<'a> { inner: ManuallyTracked, } +unsafe_impl_send_sync!(Memory<'_>); + impl DataTypeFunctions for Memory<'_> { fn mark(&self, marker: &Marker) { self.store.mark(marker) } } -unsafe impl Send for Memory<'_> {} impl<'a> Memory<'a> { /// @yard diff --git a/ext/src/ruby_api/module.rs b/ext/src/ruby_api/module.rs index 061fcd68..17169ed2 100644 --- a/ext/src/ruby_api/module.rs +++ b/ext/src/ruby_api/module.rs @@ -14,7 +14,7 @@ pub struct Module { _track_memory_usage: ManuallyTracked<()>, } -// Needed for ManuallyTracked +#[cfg(feature = "unsafe-impl-send")] unsafe impl Send for Module {} impl Module { diff --git a/ext/src/ruby_api/store.rs b/ext/src/ruby_api/store.rs index f6576f99..635fcfdd 100644 --- a/ext/src/ruby_api/store.rs +++ b/ext/src/ruby_api/store.rs @@ -1,6 +1,6 @@ use super::errors::wasi_exit_error; use super::{caller::Caller, engine::Engine, root, trap::Trap, wasi_ctx_builder::WasiCtxBuilder}; -use crate::{define_rb_intern, error}; +use crate::{define_rb_intern, error, unsafe_impl_send_sync}; use magnus::rb_sys::AsRawValue; use magnus::Class; use magnus::{ @@ -96,8 +96,7 @@ impl DataTypeFunctions for Store { } } -unsafe impl Send for Store {} -unsafe impl Send for StoreData {} +unsafe_impl_send_sync!(Store); impl Store { /// @yard