-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove Sync bound on Component and Resource #4680
Changes from all commits
87ec70a
16e86ac
998b4bf
dd6fcd3
f101e84
61f4d7c
01669da
62d0c4b
4feca9d
3f7a0a3
6deee18
7b40740
dd63b22
e6cb45c
f5b2b4b
f1e3983
6251294
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -292,6 +292,31 @@ use std::{cell::UnsafeCell, marker::PhantomData}; | |
/// | ||
/// # bevy_ecs::system::assert_is_system(my_system); | ||
/// ``` | ||
/// | ||
/// ## Non-Sync Queries | ||
/// | ||
/// Non-`Sync` components are supported, but cannot be accessed as `&T`, | ||
/// as the type cannot be safely read from multiple threads at the same | ||
/// time. These components must be accessed via a `&mut T` to guarentee | ||
/// that the system has exclusive access to the components. | ||
/// | ||
/// ```compile_fail,E0277 | ||
/// # use bevy_ecs::prelude::*; | ||
/// # use std::cell::Cell; | ||
/// | ||
/// #[derive(Component)] | ||
/// struct NotSync(Cell<usize>); | ||
/// | ||
/// // This will not compile! | ||
/// fn my_system(query: Query<&NotSync>) { | ||
/// for _ in query.iter() {} | ||
/// } | ||
/// | ||
/// // This will compile! | ||
/// fn my_system_mut(query: Query<&mut NotSync>) { | ||
/// for _ in query.iter() {} | ||
/// } | ||
/// ``` | ||
pub trait WorldQuery: for<'w> WorldQueryGats<'w, _State = Self::State> { | ||
type State: FetchState; | ||
|
||
|
@@ -541,7 +566,7 @@ impl<'w> Fetch<'w> for EntityFetch<'w> { | |
} | ||
} | ||
|
||
impl<T: Component> WorldQuery for &T { | ||
impl<T: Component + Sync> WorldQuery for &T { | ||
type State = ReadState<T>; | ||
|
||
fn shrink<'wlong: 'wshort, 'wshort>(item: QueryItem<'wlong, Self>) -> QueryItem<'wshort, Self> { | ||
|
@@ -553,12 +578,12 @@ impl<T: Component> WorldQuery for &T { | |
#[doc(hidden)] | ||
pub struct ReadState<T> { | ||
component_id: ComponentId, | ||
marker: PhantomData<T>, | ||
marker: PhantomData<fn() -> T>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This aligns with my mental model of how this should be modelled, but this is subtle enough that it deserves a comment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I don't really think it's needed. This is very much the standard way to express 'this represents something which can produce a It's no more strange than the initial use of |
||
} | ||
|
||
// SAFETY: component access and archetype component access are properly updated to reflect that T is | ||
// read | ||
unsafe impl<T: Component> FetchState for ReadState<T> { | ||
unsafe impl<T: Component + Sync> FetchState for ReadState<T> { | ||
fn init(world: &mut World) -> Self { | ||
let component_id = world.init_component::<T>(); | ||
ReadState { | ||
|
@@ -620,15 +645,15 @@ impl<T> Clone for ReadFetch<'_, T> { | |
} | ||
|
||
/// SAFETY: access is read only | ||
unsafe impl<'w, T: Component> ReadOnlyFetch for ReadFetch<'w, T> {} | ||
unsafe impl<'w, T: Component + Sync> ReadOnlyFetch for ReadFetch<'w, T> {} | ||
|
||
impl<'w, T: Component> WorldQueryGats<'w> for &T { | ||
impl<'w, T: Component + Sync> WorldQueryGats<'w> for &T { | ||
type Fetch = ReadFetch<'w, T>; | ||
type ReadOnlyFetch = ReadFetch<'w, T>; | ||
type _State = ReadState<T>; | ||
} | ||
|
||
impl<'w, T: Component> Fetch<'w> for ReadFetch<'w, T> { | ||
impl<'w, T: Component + Sync> Fetch<'w> for ReadFetch<'w, T> { | ||
type Item = &'w T; | ||
type State = ReadState<T>; | ||
|
||
|
@@ -790,7 +815,7 @@ impl<T> Clone for ReadOnlyWriteFetch<'_, T> { | |
#[doc(hidden)] | ||
pub struct WriteState<T> { | ||
component_id: ComponentId, | ||
marker: PhantomData<T>, | ||
marker: PhantomData<fn() -> T>, | ||
} | ||
|
||
// SAFETY: component access and archetype component access are properly updated to reflect that T is | ||
|
@@ -1256,7 +1281,7 @@ impl<T: Component> WorldQuery for ChangeTrackers<T> { | |
#[doc(hidden)] | ||
pub struct ChangeTrackersState<T> { | ||
component_id: ComponentId, | ||
marker: PhantomData<T>, | ||
marker: PhantomData<fn() -> T>, | ||
} | ||
|
||
// SAFETY: component access and archetype component access are properly updated to reflect that T is | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,7 @@ use std::marker::PhantomData; | |
use super::Resource; | ||
|
||
/// A [`World`] mutation. | ||
pub trait Command: Send + Sync + 'static { | ||
pub trait Command: Send + 'static { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we'll also want to do the same transformation for Note that doing that requires we keep proper main thread management - it requires a lot of care. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the Send + Sync necessary when the target is wasm? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Eventually we'll want Web Worker-based multithreading, so it will still be required. |
||
fn write(self, world: &mut World); | ||
} | ||
|
||
|
@@ -261,7 +261,7 @@ impl<'w, 's> Commands<'w, 's> { | |
/// worked out to share an ID space (which doesn't happen by default). | ||
pub fn insert_or_spawn_batch<I, B>(&mut self, bundles_iter: I) | ||
where | ||
I: IntoIterator + Send + Sync + 'static, | ||
I: IntoIterator + Send + 'static, | ||
I::IntoIter: Iterator<Item = (Entity, B)>, | ||
B: Bundle, | ||
{ | ||
|
@@ -640,7 +640,7 @@ where | |
|
||
pub struct InsertOrSpawnBatch<I, B> | ||
where | ||
I: IntoIterator + Send + Sync + 'static, | ||
I: IntoIterator + Send + 'static, | ||
B: Bundle, | ||
I::IntoIter: Iterator<Item = (Entity, B)>, | ||
{ | ||
|
@@ -649,7 +649,7 @@ where | |
|
||
impl<I, B> Command for InsertOrSpawnBatch<I, B> | ||
where | ||
I: IntoIterator + Send + Sync + 'static, | ||
I: IntoIterator + Send + 'static, | ||
B: Bundle, | ||
I::IntoIter: Iterator<Item = (Entity, B)>, | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These docs are great; add a copy of this to
Res
andNonSend
?We should also try to deduplicate these docs with the
include_str!
doc macro trick; these are subtle and critical enough that I really don't want that duplication.