use std::future::Future;
use std::sync::OnceLock;
use crate::CoreResult;
#[cfg(feature = "frb-spawn")]
#[cfg(all(feature = "frb-spawn", target_arch = "wasm32"))]
pub type ThreadPool = &'static std::thread::LocalKey<flutter_rust_bridge::SimpleThreadPool>;
#[cfg(all(feature = "frb-spawn", not(target_arch = "wasm32")))]
pub type ThreadPool = &'static flutter_rust_bridge::SimpleThreadPool;
#[cfg(feature = "frb-spawn")]
type ThreadPoolProvider = fn() -> ThreadPool;
#[cfg(not(feature = "frb-spawn"))]
type ThreadPoolProvider = fn() -> ();
#[cfg(feature = "frb-spawn")]
static THREAD_POOL_PROVIDER: OnceLock<ThreadPoolProvider> = OnceLock::new();
#[cfg(feature = "frb-spawn")]
static INITIALIZED: OnceLock<()> = OnceLock::new();
#[cfg(feature = "frb-spawn")]
pub fn init(thread_pool_provider: ThreadPoolProvider) -> bool {
let provider_set = THREAD_POOL_PROVIDER.set(thread_pool_provider).is_ok();
let init_set = INITIALIZED.set(()).is_ok();
provider_set && init_set
}
#[cfg(feature = "frb-spawn")]
pub fn ensure_initialized() -> CoreResult<()> {
if INITIALIZED.get().is_some() && THREAD_POOL_PROVIDER.get().is_some() {
return Ok(());
}
Err(crate::OxideError::Validation {
message:
"oxide_core runtime not initialized; call initOxide() from Dart main after RustLib.init()"
.to_string(),
})
}
#[cfg(feature = "frb-spawn")]
pub fn thread_pool() -> CoreResult<ThreadPool> {
ensure_initialized()?;
let provider = THREAD_POOL_PROVIDER
.get()
.expect("thread pool provider present after ensure_initialized");
Ok(provider())
}
#[cfg(feature = "frb-spawn")]
pub fn spawn<F>(future: F) -> flutter_rust_bridge::JoinHandle<F::Output>
where
F: Future + Send + 'static,
F::Output: Send + 'static,
{
ensure_initialized().expect("oxide_core runtime must be initialized before spawning");
flutter_rust_bridge::spawn(future)
}
#[cfg(all(feature = "frb-spawn", target_arch = "wasm32", target_os = "unknown"))]
pub fn spawn_local<F>(future: F)
where
F: Future<Output = ()> + 'static,
{
ensure_initialized().expect("oxide_core runtime must be initialized before spawning");
wasm_bindgen_futures::spawn_local(future);
}
#[cfg(all(feature = "frb-spawn", target_arch = "wasm32", target_os = "unknown"))]
pub fn safe_spawn<F>(future: F)
where
F: Future<Output = ()> + 'static,
{
spawn_local(future);
}
#[cfg(all(feature = "frb-spawn", not(target_arch = "wasm32")))]
pub fn safe_spawn<F>(future: F)
where
F: Future<Output = ()> + Send + 'static,
{
spawn(future);
}
#[cfg(all(feature = "frb-spawn", target_arch = "wasm32", target_os = "wasi"))]
pub fn safe_spawn<F>(future: F)
where
F: Future<Output = ()> + Send + 'static,
{
spawn(future);
}
#[cfg(feature = "frb-spawn")]
pub fn spawn_blocking<F, R>(f: F) -> flutter_rust_bridge::JoinHandle<R>
where
F: FnOnce() -> R + Send + 'static,
R: Send + 'static,
{
ensure_initialized().expect("oxide_core runtime must be initialized before spawning");
let pool = thread_pool().expect("thread pool present after ensure_initialized");
#[cfg(target_arch = "wasm32")]
{
flutter_rust_bridge::spawn_blocking_with(f, &pool)
}
#[cfg(not(target_arch = "wasm32"))]
{
flutter_rust_bridge::spawn_blocking_with(f, pool)
}
}
#[cfg(not(feature = "frb-spawn"))]
pub fn init(_: ThreadPoolProvider) -> bool {
false
}
#[cfg(not(feature = "frb-spawn"))]
pub fn ensure_initialized() -> CoreResult<()> {
Err(crate::OxideError::Validation {
message: "oxide_core built without frb-spawn; enable the `frb-spawn` feature".to_string(),
})
}
#[cfg(not(feature = "frb-spawn"))]
pub fn spawn<F>(_future: F) -> ()
where
F: Future + Send + 'static,
F::Output: Send + 'static,
{
unreachable!("oxide_core built without frb-spawn; enable the `frb-spawn` feature")
}
#[cfg(not(feature = "frb-spawn"))]
pub fn safe_spawn<F>(_future: F)
where
F: Future<Output = ()> + 'static,
{
unreachable!("oxide_core built without frb-spawn; enable the `frb-spawn` feature")
}
#[cfg(not(feature = "frb-spawn"))]
pub fn spawn_blocking<F, R>(_f: F) -> ()
where
F: FnOnce() -> R + Send + 'static,
R: Send + 'static,
{
unreachable!("oxide_core built without frb-spawn; enable the `frb-spawn` feature")
}