Move futures.rs, ConditionalSend and BoxedFuture types to bevy_tasks (#16951)

# Objective

- Related to https://github.com/bevyengine/bevy/issues/11478

## Solution

- Moved `futures.rs`, `ConditionalSend` `ConditionalSendFuture` and
`BoxedFuture` from `bevy_utils` to `bevy_tasks`.

## Testing

- CI checks

## Migration Guide

- Several modules were moved from `bevy_utils` into `bevy_tasks`:
  - Replace `bevy_utils::futures` imports with `bevy_tasks::futures`.
- Replace `bevy_utils::ConditionalSend` with
`bevy_tasks::ConditionalSend`.
- Replace `bevy_utils::ConditionalSendFuture` with
`bevy_tasks::ConditionalSendFuture`.
  - Replace `bevy_utils::BoxedFuture` with `bevy_tasks::BoxedFuture`.
This commit is contained in:
Martín Maita 2024-12-29 20:29:53 +01:00 committed by GitHub
parent 847c3a1719
commit 5157c78651
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 51 additions and 49 deletions

View File

@ -22,7 +22,7 @@ pub use futures_lite::AsyncWriteExt;
pub use source::*;
use alloc::sync::Arc;
use bevy_utils::{BoxedFuture, ConditionalSendFuture};
use bevy_tasks::{BoxedFuture, ConditionalSendFuture};
use core::future::Future;
use core::{
mem::size_of,

View File

@ -8,7 +8,8 @@ use crate::{
};
use atomicow::CowArc;
use bevy_ecs::world::World;
use bevy_utils::{BoxedFuture, ConditionalSendFuture, HashMap, HashSet};
use bevy_tasks::{BoxedFuture, ConditionalSendFuture};
use bevy_utils::{HashMap, HashSet};
use core::any::{Any, TypeId};
use downcast_rs::{impl_downcast, Downcast};
use ron::error::SpannedError;

View File

@ -58,16 +58,15 @@ use crate::{
};
use alloc::{collections::VecDeque, sync::Arc};
use bevy_ecs::prelude::*;
#[cfg(feature = "trace")]
use bevy_tasks::ConditionalSendFuture;
use bevy_tasks::IoTaskPool;
#[cfg(feature = "trace")]
use bevy_utils::tracing::{info_span, instrument::Instrument};
use bevy_utils::{
tracing::{debug, error, trace, warn},
HashMap, HashSet,
};
#[cfg(feature = "trace")]
use bevy_utils::{
tracing::{info_span, instrument::Instrument},
ConditionalSendFuture,
};
use futures_io::ErrorKind;
use futures_lite::{AsyncReadExt, AsyncWriteExt, StreamExt};
use parking_lot::RwLock;

View File

@ -10,7 +10,7 @@ use crate::{
AssetLoadError, AssetLoader, AssetPath, DeserializeMetaError, ErasedLoadedAsset,
MissingAssetLoaderForExtensionError, MissingAssetLoaderForTypeNameError,
};
use bevy_utils::{BoxedFuture, ConditionalSendFuture};
use bevy_tasks::{BoxedFuture, ConditionalSendFuture};
use core::marker::PhantomData;
use serde::{Deserialize, Serialize};
use thiserror::Error;

View File

@ -3,7 +3,8 @@ use crate::{
ErasedLoadedAsset, Handle, LabeledAsset, UntypedHandle,
};
use atomicow::CowArc;
use bevy_utils::{BoxedFuture, ConditionalSendFuture, HashMap};
use bevy_tasks::{BoxedFuture, ConditionalSendFuture};
use bevy_utils::HashMap;
use core::{borrow::Borrow, hash::Hash, ops::Deref};
use serde::{Deserialize, Serialize};

View File

@ -4,13 +4,12 @@ use crate::{
};
use alloc::sync::Arc;
use async_broadcast::RecvError;
use bevy_tasks::IoTaskPool;
use bevy_utils::{tracing::warn, HashMap, TypeIdMap};
#[cfg(feature = "trace")]
use bevy_utils::{
tracing::{info_span, instrument::Instrument},
ConditionalSendFuture,
};
use bevy_tasks::ConditionalSendFuture;
use bevy_tasks::IoTaskPool;
#[cfg(feature = "trace")]
use bevy_utils::tracing::{info_span, instrument::Instrument};
use bevy_utils::{tracing::warn, HashMap, TypeIdMap};
use core::any::TypeId;
use thiserror::Error;

View File

@ -1,6 +1,7 @@
use crate::{meta::Settings, Asset, ErasedLoadedAsset, Handle, LabeledAsset, UntypedHandle};
use atomicow::CowArc;
use bevy_utils::{ConditionalSendFuture, HashMap};
use bevy_tasks::ConditionalSendFuture;
use bevy_utils::HashMap;
use core::{
borrow::Borrow,
convert::Infallible,

View File

@ -329,7 +329,7 @@ impl ShaderCache {
// So to keep the complexity of the ShaderCache low, we will only catch this error early on native platforms,
// and on wasm the error will be handled by wgpu and crash the application.
if let Some(Some(wgpu::Error::Validation { description, .. })) =
bevy_utils::futures::now_or_never(error)
bevy_tasks::futures::now_or_never(error)
{
return Err(PipelineCacheError::CreateShaderModule(description));
}
@ -874,7 +874,7 @@ impl PipelineCache {
}
CachedPipelineState::Creating(ref mut task) => {
match bevy_utils::futures::check_ready(task) {
match bevy_tasks::futures::check_ready(task) {
Some(Ok(pipeline)) => {
cached_pipeline.state = CachedPipelineState::Ok(pipeline);
return;

View File

@ -1,3 +1,5 @@
#![expect(unsafe_code, reason = "Futures require unsafe code.")]
//! Utilities for working with [`Future`]s.
use core::{
future::Future,

View File

@ -8,6 +8,35 @@
extern crate alloc;
#[cfg(not(target_arch = "wasm32"))]
mod conditional_send {
/// Use [`ConditionalSend`] to mark an optional Send trait bound. Useful as on certain platforms (eg. Wasm),
/// futures aren't Send.
pub trait ConditionalSend: Send {}
impl<T: Send> ConditionalSend for T {}
}
#[cfg(target_arch = "wasm32")]
#[expect(missing_docs, reason = "Not all docs are written yet (#3492).")]
mod conditional_send {
pub trait ConditionalSend {}
impl<T> ConditionalSend for T {}
}
pub use conditional_send::*;
/// Use [`ConditionalSendFuture`] for a future with an optional Send trait bound, as on certain platforms (eg. Wasm),
/// futures aren't Send.
pub trait ConditionalSendFuture: core::future::Future + ConditionalSend {}
impl<T: core::future::Future + ConditionalSend> ConditionalSendFuture for T {}
use alloc::boxed::Box;
/// An owned and dynamically typed Future used when you can't statically type your result or need to add some indirection.
pub type BoxedFuture<'a, T> = core::pin::Pin<Box<dyn ConditionalSendFuture<Output = T> + 'a>>;
pub mod futures;
mod executor;
mod slice;

View File

@ -1,7 +1,7 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![expect(
unsafe_code,
reason = "Some utilities, such as futures and cells, require unsafe code."
reason = "Some utilities, such as cells, require unsafe code."
)]
#![doc(
html_logo_url = "https://bevyengine.org/assets/icon.png",
@ -23,7 +23,6 @@ pub mod prelude {
pub use crate::default;
}
pub mod futures;
pub mod synccell;
pub mod syncunsafecell;
@ -64,9 +63,6 @@ pub use time::*;
#[cfg(feature = "tracing")]
pub use tracing;
#[cfg(feature = "alloc")]
use alloc::boxed::Box;
#[cfg(feature = "alloc")]
use core::any::TypeId;
use core::{
@ -77,32 +73,6 @@ use core::{
ops::Deref,
};
#[cfg(not(target_arch = "wasm32"))]
mod conditional_send {
/// Use [`ConditionalSend`] to mark an optional Send trait bound. Useful as on certain platforms (eg. Wasm),
/// futures aren't Send.
pub trait ConditionalSend: Send {}
impl<T: Send> ConditionalSend for T {}
}
#[cfg(target_arch = "wasm32")]
#[expect(missing_docs, reason = "Not all docs are written yet (#3492).")]
mod conditional_send {
pub trait ConditionalSend {}
impl<T> ConditionalSend for T {}
}
pub use conditional_send::*;
/// Use [`ConditionalSendFuture`] for a future with an optional Send trait bound, as on certain platforms (eg. Wasm),
/// futures aren't Send.
pub trait ConditionalSendFuture: core::future::Future + ConditionalSend {}
impl<T: core::future::Future + ConditionalSend> ConditionalSendFuture for T {}
/// An owned and dynamically typed Future used when you can't statically type your result or need to add some indirection.
#[cfg(feature = "alloc")]
pub type BoxedFuture<'a, T> = core::pin::Pin<Box<dyn ConditionalSendFuture<Output = T> + 'a>>;
/// A shortcut alias for [`hashbrown::hash_map::Entry`].
#[cfg(feature = "alloc")]
pub type Entry<'a, K, V, S = FixedHasher> = hashbrown::hash_map::Entry<'a, K, V, S>;