diff --git a/src/Rust/vvs_cli/src/main.rs b/src/Rust/vvs_cli/src/main.rs index a47c618a58fb7789c7ef48db9d21f9e0164b1bfd..5c723d6b164f2a26e881aa98dba1c9bbb34febc2 100644 --- a/src/Rust/vvs_cli/src/main.rs +++ b/src/Rust/vvs_cli/src/main.rs @@ -10,6 +10,7 @@ use vvs_cli::{ config::{Config, ConfigFile}, }; use vvs_lang::*; +use vvs_runtime::Runtime; use vvs_xdg::{file::TempFile, XDGConfig, XDGConfigMergedSilent}; fn print_font(n: impl AsRef<Path>, f: &[u8]) -> Result<()> { @@ -79,19 +80,15 @@ fn main() -> Result<()> { } let mut file = TempFile::new("vvcc")?; - let jit = vvs_runtime::JIT::new()?; - jit.with_module( - vvs_codegen::lowerer::Lowerer::new(&jit.ctx(), &output.main.name)? + Runtime::new(move |ctx| { + Ok(vvs_codegen::lowerer::Lowerer::new(&ctx, &output.main.name)? .declare_globals(output.declared_functions())? .lower_module(&output.main.name, output.ast)? .lower_modules(output.imports)? .generate_main(output.main)? - .finished(), - )? - .run_on_file( - vvs_ass::ass_container_from_file(ass_file.context("no subtitle file to run the script on")?) - .context("failed to parse the subtitle file")?, - )? + .finished()) + })? + .run_on_file(ass_file.context("no subtitle file to run the script on")?)? .write_ass_to_file(&mut file)?; println!("output file ........ {}", file.leak().path().display()); diff --git a/src/Rust/vvs_codegen/src/lowerer/mod.rs b/src/Rust/vvs_codegen/src/lowerer/mod.rs index 35e8475d2ca17c130f0c66b1368745d2e26347e4..a929f1209f604d8f530e46803ae0b98e621bc05a 100644 --- a/src/Rust/vvs_codegen/src/lowerer/mod.rs +++ b/src/Rust/vvs_codegen/src/lowerer/mod.rs @@ -13,7 +13,7 @@ where 'ctx: 'this, { context: &'this Context<'ctx>, - module: Module<'this>, + module: Module<'ctx>, } impl<'ctx, 'this> Lowerer<'ctx, 'this> @@ -22,8 +22,7 @@ where { /// Create a new lowerer. We will lower things into a module. pub fn new(context: &'this Context<'ctx>, module: impl AsRef<str>) -> Result<Self, CodegenError> { - let _ = vvs_llvm::init::initialize_llvm(); - Ok(Self { context, module: context.create_module(module.as_ref()).map_err(CodegenError::NulError)? }) + Ok(Self { context, module: Module::new(context, module.as_ref()).map_err(CodegenError::NulError)? }) } pub fn declare_globals<'a>( @@ -86,7 +85,7 @@ where } /// Finished the lowering process and get the module out of the builder. - pub fn finished(self) -> Module<'this> { + pub fn finished(self) -> Module<'ctx> { self.module } } diff --git a/src/Rust/vvs_llvm/src/bindings/basic_block.rs b/src/Rust/vvs_llvm/src/bindings/basic_block.rs index ed65e7b118d7569f89f0aa9c7cb589589d9471a9..c42d116f290e64c6d052b8c3d7f44ed620c75838 100644 --- a/src/Rust/vvs_llvm/src/bindings/basic_block.rs +++ b/src/Rust/vvs_llvm/src/bindings/basic_block.rs @@ -2,7 +2,9 @@ use crate::prelude::*; use llvm_sys::{core::*, prelude::*}; crate::bindings::declare! { const LLVMBasicBlockRef as BB<'a> } -crate::bindings::declare! { mut LLVMBasicBlockRef as BBMut<'a> } +crate::bindings::declare! { mut LLVMBasicBlockRef as BBMut<'a> { + const_ref: BB<'a>, +} } /// Share code between the [BB::terminator] and [BB::terminator_mut] macro_rules! get_terminator { @@ -27,7 +29,7 @@ macro_rules! get_terminator { impl<'a> BBMut<'a> { /// Get a const reference to the basic block. pub fn into_ref(self) -> BB<'a> { - todo!() + unsafe { BB::from_ptr(self.as_ptr()) } } /// Get the terminator in a mutable way of the basic block if it exists. @@ -36,12 +38,17 @@ impl<'a> BBMut<'a> { } /// Iterate over the instructions of a basic block in a mutable way. - pub fn iter_mut(&'a mut self) -> BBIter<'a, &'a mut BBMut<'a>> { + pub fn iter_mut(&'a mut self) -> BBIterMut<'a, &'a mut BBMut<'a>> { match self.as_ref().is_empty() { - true => BBIter { curr: None, last: None, bb: self }, + true => BBIterMut { curr: None, last: None, bb: self }, false => todo!(), } } + + /// Create a new [BBMut] from the pointer. + pub(crate) unsafe fn new(ptr: LLVMBasicBlockRef) -> Self { + unsafe { Self::from_ptr(ptr, BB::from_ptr(ptr)) } + } } impl<'a> BB<'a> { @@ -67,11 +74,34 @@ impl<'a> BB<'a> { false => todo!(), } } + + /// Create a new [BB] from the pointer. + pub(crate) unsafe fn new(ptr: LLVMBasicBlockRef) -> Self { + unsafe { Self::from_ptr(ptr) } + } } impl<'a> AsRef<BB<'a>> for BBMut<'a> { fn as_ref(&self) -> &BB<'a> { - todo!() + &self.const_ref + } +} + +impl<'a> AsRef<BB<'a>> for &'a BB<'a> { + fn as_ref(&self) -> &BB<'a> { + self + } +} + +impl<'a> AsRef<BB<'a>> for &'a mut BB<'a> { + fn as_ref(&self) -> &BB<'a> { + self + } +} + +impl<'a> AsMut<BBMut<'a>> for &'a mut BBMut<'a> { + fn as_mut(&mut self) -> &mut BBMut<'a> { + self } } @@ -91,33 +121,13 @@ impl PartialEq for BBMut<'_> { mod sealed { pub trait BBRef<'a>: AsRef<super::BB<'a>> {} - pub trait BBMutRef<'a>: AsMut<super::BBMut<'a>> + BBRef<'a> {} + pub trait BBMutRef<'a>: AsMut<super::BBMut<'a>> + AsRef<super::BB<'a>> {} } impl<'a> sealed::BBRef<'a> for &'a BB<'a> {} impl<'a> sealed::BBRef<'a> for &'a mut BB<'a> {} -impl<'a> sealed::BBRef<'a> for &'a BBMut<'a> {} -impl<'a> sealed::BBRef<'a> for &'a mut BBMut<'a> {} impl<'a> sealed::BBMutRef<'a> for &'a mut BBMut<'a> {} -impl<'a> AsRef<BB<'a>> for &'a BB<'a> { - fn as_ref(&self) -> &BB<'a> { - self - } -} - -impl<'a> AsRef<BB<'a>> for &'a mut BB<'a> { - fn as_ref(&self) -> &BB<'a> { - self - } -} - -impl<'a> AsMut<BBMut<'a>> for &'a mut BBMut<'a> { - fn as_mut(&mut self) -> &mut BBMut<'a> { - todo!() - } -} - /// Iterate over the instructions in a basic block. pub struct BBIter<'a, B: sealed::BBRef<'a>> { curr: Option<Value<'a>>, @@ -161,7 +171,7 @@ impl<'a, B: sealed::BBRef<'a>> Iterator for BBIter<'a, B> { } fn count(self) -> usize { - self.bb.as_ref().len() + self.size_hint().0 } fn size_hint(&self) -> (usize, Option<usize>) { @@ -182,7 +192,7 @@ impl<'a, B: sealed::BBMutRef<'a>> Iterator for BBIterMut<'a, B> { } fn count(self) -> usize { - self.bb.as_ref().len() + self.size_hint().0 } fn size_hint(&self) -> (usize, Option<usize>) { diff --git a/src/Rust/vvs_llvm/src/bindings/builder.rs b/src/Rust/vvs_llvm/src/bindings/builder.rs index 74ee630fd399f64a8359bb97eaa0a6e697df683a..37d4823281195720e20ca5023a41555dce9e64b7 100644 --- a/src/Rust/vvs_llvm/src/bindings/builder.rs +++ b/src/Rust/vvs_llvm/src/bindings/builder.rs @@ -18,6 +18,11 @@ macro_rules! build { } impl<'a> Builder<'a> { + /// Create a new builder. + pub fn new(ctx: &Context) -> Self { + unsafe { Self::from_ptr(LLVMCreateBuilderInContext(ctx.as_ptr())) } + } + /// Position the builder at the end of a basic block. pub fn position_at_end(&mut self, bb: &mut BBMut) -> &mut Self { unsafe { LLVMPositionBuilderAtEnd(self.as_ptr(), bb.as_ptr()) }; diff --git a/src/Rust/vvs_llvm/src/bindings/context.rs b/src/Rust/vvs_llvm/src/bindings/context.rs index a9aadfcf3a450e012ee4f66df7050f525435cde8..0beb8e7833031ec73d61529692ca9281ec3a2500 100644 --- a/src/Rust/vvs_llvm/src/bindings/context.rs +++ b/src/Rust/vvs_llvm/src/bindings/context.rs @@ -1,9 +1,6 @@ use crate::prelude::*; use llvm_sys::{core::*, prelude::*}; -use std::{ - ffi::{CString, NulError}, - marker, -}; +use std::marker; crate::bindings::declare! { mut LLVMContextRef as Context<'a> { borrowed: bool, @@ -37,17 +34,6 @@ impl Context<'_> { Self { inner: unsafe { LLVMContextCreate() }, borrowed: false, marker: marker::PhantomData } } - /// Create a new builder for this context. - pub fn create_builder(&self) -> Builder { - unsafe { Builder::from_ptr(LLVMCreateBuilderInContext(self.inner)) } - } - - /// Create a new module in this context. - pub fn create_module(&self, name: impl AsRef<str>) -> Result<Module, NulError> { - let name = CString::new(name.as_ref())?; - Ok(unsafe { Module::from_ptr(LLVMModuleCreateWithName(name.as_ptr())) }) - } - /// Get the pointer type. We always use the address space 0 for now, we will see latter if we /// need different address spaces. pub fn type_ptr(&self) -> Type { diff --git a/src/Rust/vvs_llvm/src/bindings/function.rs b/src/Rust/vvs_llvm/src/bindings/function.rs index fd79b262922d522e7eda6450ea22212cd599e1da..e945babdcad3f75827f67516d4270fe5a5a92160 100644 --- a/src/Rust/vvs_llvm/src/bindings/function.rs +++ b/src/Rust/vvs_llvm/src/bindings/function.rs @@ -23,7 +23,7 @@ impl<'a> FunctionDeclaration<'a> { impl<'a> FunctionBuilder<'a> { /// Get the associated declaration. pub fn declaration(&self) -> FunctionDeclaration { - todo!() + unsafe { FunctionDeclaration::from_ptr(self.as_ptr()) } } /// Set the [LLVMLinkage] and [LLVMVisibility] accordingly. @@ -61,7 +61,7 @@ impl<'a> FunctionBuilder<'a> { impl<'a> Function<'a> { /// Get the associated declaration. pub fn declaration(&self) -> FunctionDeclaration { - todo!() + unsafe { FunctionDeclaration::from_ptr(self.as_ptr()) } } /// Get the entry point of the function. @@ -92,8 +92,8 @@ impl<'a> Function<'a> { match LLVMCountBasicBlocks(self.as_ptr()) { 0 => FunctionIter { curr: None, last: None, func: self }, _ => FunctionIter { - curr: Some(BB::from_ptr(LLVMGetFirstBasicBlock(self.inner))), - last: Some(BB::from_ptr(LLVMGetLastBasicBlock(self.inner))), + curr: Some(BB::new(LLVMGetFirstBasicBlock(self.inner))), + last: Some(BB::new(LLVMGetLastBasicBlock(self.inner))), func: self, }, } @@ -106,8 +106,8 @@ impl<'a> Function<'a> { match LLVMCountBasicBlocks(self.as_ptr()) { 0 => FunctionIterMut { curr: None, last: None, func: self }, _ => FunctionIterMut { - curr: Some(BBMut::from_ptr(LLVMGetFirstBasicBlock(self.inner))), - last: Some(BBMut::from_ptr(LLVMGetLastBasicBlock(self.inner))), + curr: Some(BBMut::new(LLVMGetFirstBasicBlock(self.inner))), + last: Some(BBMut::new(LLVMGetLastBasicBlock(self.inner))), func: self, }, } @@ -158,7 +158,7 @@ macro_rules! next { Some(curr) } (Some(curr), Some(_)) => unsafe { - $self.curr = Some($bb::from_ptr(LLVMGetNextBasicBlock(curr.as_ptr()))); + $self.curr = Some($bb::new(LLVMGetNextBasicBlock(curr.as_ptr()))); Some(curr) }, } diff --git a/src/Rust/vvs_runtime/src/jit.rs b/src/Rust/vvs_llvm/src/bindings/jit.rs similarity index 56% rename from src/Rust/vvs_runtime/src/jit.rs rename to src/Rust/vvs_llvm/src/bindings/jit.rs index e238daedc159c12f672207225cc23c33a0c28fe4..29506a042593d580a6dd94b65430683290c0796e 100644 --- a/src/Rust/vvs_runtime/src/jit.rs +++ b/src/Rust/vvs_llvm/src/bindings/jit.rs @@ -1,19 +1,15 @@ -use crate::workers::Workers; +use crate::prelude::{Context, Module}; use anyhow::{bail, Context as _}; +use llvm_sys::{ + error::*, + orc2::{ee::*, lljit::*, *}, +}; use std::{ ffi::{c_int, c_void, CStr, CString}, ptr, - sync::{ - atomic::{AtomicU64, Ordering}, - Arc, - }, - thread, }; -use vvs_ass::ASSContainer; -use vvs_llvm::prelude::{Context, Module}; -use vvs_llvm::sys::*; -use vvs_runtime_types::{types::VVRTTable, VVRTSymbol}; +/// Create a JIT engine. #[allow(dead_code)] pub struct JIT { jit: *mut LLVMOrcOpaqueLLJIT, @@ -24,8 +20,6 @@ pub struct JIT { irtl: *mut LLVMOrcOpaqueIRTransformLayer, objl: *mut LLVMOrcOpaqueObjectLayer, dylib: *mut LLVMOrcOpaqueJITDylib, - - workers: Workers, } macro_rules! llvm_expect { @@ -45,17 +39,6 @@ macro_rules! llvm_expect { }}; } -/// This function should be visible because it starts with `VVRT` -#[allow(non_snake_case)] -pub extern "C" fn VVRTHelloWorld() { - println!("Hello World from LLVM JIT"); -} - -/// This function should not be visible because it doesn't start with `VVRT` -pub extern "C" fn hello_world() { - println!("wtf !?"); -} - extern "C" fn orc_sym_filter(_: *mut c_void, sym: LLVMOrcSymbolStringPoolEntryRef) -> c_int { eprintln!("toto"); let Ok(sym) = unsafe { CStr::from_ptr(LLVMOrcSymbolStringPoolEntryStr(sym)) }.to_str() else { @@ -67,8 +50,13 @@ extern "C" fn orc_sym_filter(_: *mut c_void, sym: LLVMOrcSymbolStringPoolEntryRe impl JIT { /// Create a new JIT thingy to execute Vivy Script code. - pub fn new() -> anyhow::Result<JIT> { - let _ = vvs_llvm::init::initialize_llvm(); + fn new() -> anyhow::Result<JIT> { + if let Err(err) = crate::init::initialize_llvm() { + // Should fail only on re-init. If a real problem occured, we would have already + // aborted the program. + log::debug!("{err}"); + } + unsafe { // Create the jit. let mut jit = ptr::null_mut(); @@ -94,55 +82,34 @@ impl JIT { ); LLVMOrcJITDylibAddGenerator(dylib, dg); - // Ok. Create workers and return the struct. - let tsctx = LLVMOrcCreateNewThreadSafeContext(); - let workers = Workers::new(|flag: Arc<AtomicU64>| loop { - match flag.load(Ordering::SeqCst) { - 0 => thread::yield_now(), - u64::MAX => return Ok(()), - x => bail!("won't handle work package n°{x}"), - } - })?; - Ok(JIT { jit, es, dylib, tsctx, irtl, objl, workers }) + // Ok. + Ok(JIT { jit, es, dylib, tsctx: LLVMOrcCreateNewThreadSafeContext(), irtl, objl }) } } - /// Get the context out of the JIT thingy. Used to create a LLVM module to be used latter by - /// the JIT. - pub fn ctx(&self) -> Context { - unsafe { Context::from_ptr(LLVMOrcThreadSafeContextGetContext(self.tsctx), true) } - } - - /// Add a new module to the JIT engine. - pub fn with_module(&self, module: Module) -> anyhow::Result<&Self> { - log::debug!("add module `{}` to jit engine", module.name()); - let tsm = unsafe { LLVMOrcCreateNewThreadSafeModule(module.as_ptr(), self.tsctx) }; - let rc = unsafe { LLVMOrcLLJITAddLLVMIRModule(self.jit, self.dylib, tsm) }; + /// Initialize a jot with a module, that must be created from the passed context. + pub fn init<'a>(cb: impl FnOnce(Context<'a>) -> anyhow::Result<Module<'a>>) -> anyhow::Result<Self> { + let jit = JIT::new()?; + let module = unsafe { cb(Context::from_ptr(LLVMOrcThreadSafeContextGetContext(jit.tsctx), true))?.into_ptr() }; + let tsm = unsafe { LLVMOrcCreateNewThreadSafeModule(module, jit.tsctx) }; + let rc = unsafe { LLVMOrcLLJITAddLLVMIRModule(jit.jit, jit.dylib, tsm) }; unsafe { llvm_expect!(rc, "failed to add the module into the jit") }; - Ok(self) + Ok(jit) } /// LookUp a symbol defined in the JIT. - pub fn lookup<'a>(&self, name: &'a str) -> anyhow::Result<VVRTSymbol<'a>> { + pub fn lookup(&self, symbol: &str) -> anyhow::Result<*const u8> { let mut addr = Default::default(); - let symbol = VVRTSymbol::try_from(name)?; - let str = CString::new(name).with_context(|| "CString::new failed")?; llvm_expect!(unsafe - LLVMOrcLLJITLookup(self.jit, &mut addr, str.as_ptr()), - "failed to lookup symbol `{name}`" + LLVMOrcLLJITLookup(self.jit, &mut addr, CString::new(symbol).with_context(|| "CString::new failed")?.as_ptr()), + "failed to lookup symbol `{symbol}`" ); - Ok(symbol.with_addr(addr)) - } - - /// Run the program on an ass file. - pub fn run_on_file(&self, ass: ASSContainer<VVRTTable>) -> anyhow::Result<ASSContainer<VVRTTable>> { - unimplemented!("use the ASS container and insert it into the JIT: {ass:#?}") + Ok(addr as *const u8) } } impl Drop for JIT { fn drop(&mut self) { - self.workers.pre_drop(); unsafe { LLVMOrcDisposeThreadSafeContext(self.tsctx); LLVMOrcDisposeLLJIT(self.jit); diff --git a/src/Rust/vvs_llvm/src/bindings/mod.rs b/src/Rust/vvs_llvm/src/bindings/mod.rs index a2e71ed63ca2454fd9e8bf774c38871a484ec943..830e44f524809682a2b81976d4bd72a9da2c55f9 100644 --- a/src/Rust/vvs_llvm/src/bindings/mod.rs +++ b/src/Rust/vvs_llvm/src/bindings/mod.rs @@ -6,6 +6,7 @@ pub mod basic_block; pub mod builder; pub mod context; pub mod function; +pub mod jit; pub mod module; pub mod types; pub mod value; @@ -26,8 +27,7 @@ macro_rules! declare { /// Create a new instance from a pointer. /// /// # Safety - /// Must be used from functions of the [crate::bindings::context::Context] to be sure that the - /// usage is correct... + /// Be sure that the usage is correct... You could mess up internal invariants here... pub unsafe fn from_ptr(inner: $llvm $($(, $field: $ty)*)?) -> Self { Self { inner $($(, $field)*)?, @@ -35,7 +35,9 @@ macro_rules! declare { } } - /// Get the inner pointer. + /// Get the inner pointer. Be aware that you are borrowing the pointer and thus not + /// responsible from freeing it. If it exists, you can use the [Self::into_ptr] + /// function to take the ownership out of this wrapper. pub fn as_ptr(&self) -> $llvm { self.inner } diff --git a/src/Rust/vvs_llvm/src/bindings/module.rs b/src/Rust/vvs_llvm/src/bindings/module.rs index 2e5b98283c437d65770832d40e34a0210e1255b3..8c44ccf44be9c64221e720612a0920054d45e535 100644 --- a/src/Rust/vvs_llvm/src/bindings/module.rs +++ b/src/Rust/vvs_llvm/src/bindings/module.rs @@ -2,9 +2,21 @@ use crate::prelude::*; use llvm_sys::{core::*, prelude::*, LLVMLinkage, LLVMVisibility}; use std::ffi::{CString, NulError}; -crate::bindings::declare! { mut LLVMModuleRef as Module<'a> } +crate::bindings::declare! { mut LLVMModuleRef as Module<'a> { + is_borrowed: bool, +} } + +impl<'a> Module<'a> { + /// Create a new module. + pub fn new(ctx: &Context<'a>, name: impl AsRef<str>) -> Result<Self, NulError> { + unsafe { + Ok(Module::from_ptr( + LLVMModuleCreateWithNameInContext(CString::new(name.as_ref())?.as_ptr(), ctx.as_ptr()), + false, + )) + } + } -impl Module<'_> { /// Add a new function in this module. /// /// Note that by default all functions are private. @@ -37,10 +49,20 @@ impl Module<'_> { }) .expect("valid utf8 module name") } + + /// Get out the pointer out of the struct, the caller is now responsible of managing the + /// lifetime of the returned pointer. + #[must_use] + pub(super) unsafe fn into_ptr(mut self) -> LLVMModuleRef { + self.is_borrowed = true; + self.inner + } } impl Drop for Module<'_> { fn drop(&mut self) { - unsafe { LLVMDisposeModule(self.inner) } + if !self.is_borrowed { + unsafe { LLVMDisposeModule(self.inner) } + } } } diff --git a/src/Rust/vvs_llvm/src/lib.rs b/src/Rust/vvs_llvm/src/lib.rs index bcedcae927e6e12c0e0bff3aadc5dcfbd889897d..34c4d538697eaa7764b5a6669cc5daa1808b8dd6 100644 --- a/src/Rust/vvs_llvm/src/lib.rs +++ b/src/Rust/vvs_llvm/src/lib.rs @@ -18,7 +18,8 @@ pub mod sys { #[cfg(feature = "bindings")] pub mod prelude { pub use crate::bindings::{ - basic_block::*, builder::*, context::*, function::*, module::*, types::*, value::*, Error as LLVMError, + basic_block::*, builder::*, context::*, function::*, jit::JIT, module::*, types::*, value::*, + Error as LLVMError, }; } diff --git a/src/Rust/vvs_runtime/src/lib.rs b/src/Rust/vvs_runtime/src/lib.rs index 4eb83d6c59bb490ee381fbdd0305f3bf5a72c620..9137c64df2addebbf76c8b0fa2ccd84006798250 100644 --- a/src/Rust/vvs_runtime/src/lib.rs +++ b/src/Rust/vvs_runtime/src/lib.rs @@ -1,6 +1,7 @@ -mod jit; +mod runtime; mod workers; +pub use runtime::Runtime; + // Re-exports -pub use crate::jit::*; pub use vvs_runtime_types::types; diff --git a/src/Rust/vvs_runtime/src/runtime.rs b/src/Rust/vvs_runtime/src/runtime.rs new file mode 100644 index 0000000000000000000000000000000000000000..3eb25e53ab62ef56d3b6baa27a710b8aacbbf49b --- /dev/null +++ b/src/Rust/vvs_runtime/src/runtime.rs @@ -0,0 +1,44 @@ +use crate::workers::Workers; +use anyhow::{bail, Context as _}; +use std::{ + path::Path, + sync::{ + atomic::{AtomicU64, Ordering}, + Arc, + }, + thread, +}; +use vvs_ass::{ass_container_from_file, ASSContainer}; +use vvs_llvm::prelude::*; +use vvs_runtime_types::types::VVRTTable; + +#[allow(dead_code)] +pub struct Runtime { + jit: JIT, + workers: Workers, +} + +impl Runtime { + pub fn new<'a>(init: impl FnOnce(Context<'a>) -> anyhow::Result<Module<'a>>) -> anyhow::Result<Self> { + Ok(Self { + jit: JIT::init(init)?, + workers: Workers::new(|flag: Arc<AtomicU64>| loop { + match flag.load(Ordering::SeqCst) { + 0 => thread::yield_now(), + u64::MAX => return Ok(()), + x => bail!("won't handle work package n°{x}"), + } + })?, + }) + } + + pub fn run_on_container(self, ass: ASSContainer<VVRTTable>) -> anyhow::Result<ASSContainer<VVRTTable>> { + todo!("run on {ass:?}") + } + + pub fn run_on_file(self, file: impl AsRef<Path>) -> anyhow::Result<ASSContainer<VVRTTable>> { + self.run_on_container( + ass_container_from_file::<VVRTTable>(file.as_ref()).context("failed to parse the subtitle file")?, + ) + } +} diff --git a/src/Rust/vvs_runtime/src/workers.rs b/src/Rust/vvs_runtime/src/workers.rs index 9c69cad1ffc5327b75d15e8b5c7c5141c8959d62..9cc00a4fa837f629d23b38e4f9cf817422052010 100644 --- a/src/Rust/vvs_runtime/src/workers.rs +++ b/src/Rust/vvs_runtime/src/workers.rs @@ -94,8 +94,10 @@ impl Workers { /// Pre-drop all the threads and cancel the work to do. pub fn pre_drop(&mut self) { let handles = std::mem::take(&mut self.handles); - cancel_threads(handles.iter().map(|(_, rc)| rc.clone())); - join_handles(handles.into_iter().map(|(hdl, _)| hdl)); + if !handles.is_empty() { + cancel_threads(handles.iter().map(|(_, rc)| rc.clone())); + join_handles(handles.into_iter().map(|(hdl, _)| hdl)); + } } }