diff --git a/crates/plugin_runtime/src/plugin.rs b/crates/plugin_runtime/src/plugin.rs index 777d40c26571b3eabb7582c9b61855f848b5aa4d..3515bfd8e70432e9274c907a2d6b9acbf52ed8f8 100644 --- a/crates/plugin_runtime/src/plugin.rs +++ b/crates/plugin_runtime/src/plugin.rs @@ -60,25 +60,16 @@ pub struct PluginYieldEpoch { epoch: std::time::Duration, } -impl Into for PluginYieldEpoch { - fn into(self) -> PluginYield { - PluginYield::Epoch(self) - } -} - pub struct PluginYieldFuel { initial: u64, refill: u64, } -impl Into for PluginYieldFuel { - fn into(self) -> PluginYield { - PluginYield::Fuel(self) - } -} - pub enum PluginYield { - Epoch(PluginYieldEpoch), + Epoch { + yield_epoch: PluginYieldEpoch, + initialize_incrementer: Box () + Send>, + }, Fuel(PluginYieldFuel), } @@ -117,7 +108,7 @@ impl PluginBuilder { let linker = Linker::new(&engine); match yield_when { - PluginYield::Epoch(_) => { + PluginYield::Epoch { .. } => { config.epoch_interruption(true); } PluginYield::Fuel(_) => { @@ -136,23 +127,27 @@ impl PluginBuilder { callback: C, ) -> Result where - C: FnOnce(std::pin::Pin + Send + 'static>>) -> (), + C: FnOnce(std::pin::Pin + Send + 'static>>) -> () + + Send + + 'static, { - let epoch = yield_epoch.epoch; - let yield_when = PluginYield::Epoch(yield_epoch); - let (engine, linker) = Self::create_engine(&yield_when)?; - - let engine_ref = &engine; - // we can't create the future until after initializing // because we need the engine to load the plugin - // we could use an Arc, but that'd suck - callback(Box::pin(async move { - loop { - smol::Timer::after(epoch).await; - engine_ref.increment_epoch(); - } - })); + let epoch = yield_epoch.epoch; + let initialize_incrementer = Box::new(move |engine: Engine| { + callback(Box::pin(async move { + loop { + smol::Timer::after(epoch).await; + engine.increment_epoch(); + } + })) + }); + + let yield_when = PluginYield::Epoch { + yield_epoch, + initialize_incrementer, + }; + let (engine, linker) = Self::create_engine(&yield_when)?; Ok(PluginBuilder { wasi_ctx, @@ -188,7 +183,9 @@ impl PluginBuilder { callback: C, ) -> Result where - C: FnOnce(std::pin::Pin + Send + 'static>>) -> (), + C: FnOnce(std::pin::Pin + Send + 'static>>) -> () + + Send + + 'static, { Self::new_epoch(Self::default_ctx(), yield_epoch, callback) } @@ -342,7 +339,7 @@ impl PluginBuilder { /// Will panic if this is plugin uses `PluginYield::Epoch`, /// but an epoch incrementer has not yet been created. pub async fn init>(self, precompiled: bool, module: T) -> Result { - Plugin::init(precompiled, module.as_ref().to_vec(), self).await + Plugin::init(precompiled, module.as_ref(), self).await } } @@ -402,11 +399,7 @@ impl Plugin { println!(); } - async fn init( - precompiled: bool, - module: Vec, - plugin: PluginBuilder, - ) -> Result { + async fn init(precompiled: bool, module: &[u8], plugin: PluginBuilder) -> Result { // initialize the WebAssembly System Interface context let engine = plugin.engine; let mut linker = plugin.linker; @@ -430,8 +423,12 @@ impl Plugin { // set up automatic yielding based on configuration match plugin.yield_when { - PluginYield::Epoch(PluginYieldEpoch { delta, .. }) => { + PluginYield::Epoch { + yield_epoch: PluginYieldEpoch { delta, .. }, + initialize_incrementer, + } => { store.epoch_deadline_async_yield_and_update(delta); + initialize_incrementer(engine); } PluginYield::Fuel(PluginYieldFuel { initial, refill }) => { store.add_fuel(initial).unwrap(); @@ -455,6 +452,25 @@ impl Plugin { Ok(Plugin { store, instance }) } + // async fn init_fuel( + // precompiled: bool, + // module: &[u8], + // plugin: PluginBuilder, + // ) -> Result { + // let (_, plugin) = Self::init_inner(precompiled, module, plugin).await?; + // Ok(plugin) + // } + + // async fn init_epoch( + // precompiled: bool, + // module: &[u8], + // plugin: PluginBuilder, + // callback: C, + // ) -> Result { + // let (_, plugin) = Self::init_inner(precompiled, module, plugin).await?; + // Ok(plugin) + // } + /// Attaches a file or directory the the given system path to the runtime. /// Note that the resource must be freed by calling `remove_resource` afterwards. pub fn attach_path>(&mut self, path: T) -> Result { diff --git a/crates/zed/src/languages/language_plugin.rs b/crates/zed/src/languages/language_plugin.rs index 78242865ab4b1d77725b10a41992e8b4b7e99d49..8417f0ff9a6f699878309f406a8ef875f3f76317 100644 --- a/crates/zed/src/languages/language_plugin.rs +++ b/crates/zed/src/languages/language_plugin.rs @@ -9,9 +9,10 @@ use std::{any::Any, path::PathBuf, sync::Arc}; use util::ResultExt; pub async fn new_json(executor: Arc) -> Result { + let executor_ref = executor.clone(); let plugin = - PluginBuilder::new_epoch_with_default_ctx(PluginYield::default_epoch(), |future| { - executor.spawn(future).detach() + PluginBuilder::new_epoch_with_default_ctx(PluginYield::default_epoch(), move |future| { + executor_ref.spawn(future).detach() })? .host_function_async("command", |command: String| async move { let mut args = command.split(' ');