pub struct Messages<E>where
E: Message,{ /* private fields */ }
Expand description
A message collection that represents the messages that occurred within the last two
Messages::update
calls.
Messages can be written to using a MessageWriter
and are typically cheaply read using a MessageReader
.
Each message can be consumed by multiple systems, in parallel,
with consumption tracked by the MessageReader
on a per-system basis.
If no ordering
is applied between writing and reading systems, there is a risk of a race condition.
This means that whether the messages arrive before or after the next Messages::update
is unpredictable.
This collection is meant to be paired with a system that calls
Messages::update
exactly once per update/frame.
message_update_system
is a system that does this, typically initialized automatically using
add_message
.
MessageReader
s are expected to read messages from this collection at least once per loop/frame.
Messages will persist across a single frame boundary and so ordering of message producers and
consumers is not critical (although poorly-planned ordering may cause accumulating lag).
If messages are not handled by the end of the frame after they are updated, they will be
dropped silently.
§Example
use bevy_ecs::message::{Message, Messages};
#[derive(Message)]
struct MyMessage {
value: usize
}
// setup
let mut messages = Messages::<MyMessage>::default();
let mut cursor = messages.get_cursor();
// run this once per update/frame
messages.update();
// somewhere else: write a message
messages.write(MyMessage { value: 1 });
// somewhere else: read the messages
for message in cursor.read(&messages) {
assert_eq!(message.value, 1)
}
// messages are only processed once per reader
assert_eq!(cursor.read(&messages).count(), 0);
§Details
Messages
is implemented using a variation of a double buffer strategy.
Each call to update
swaps buffers and clears out the oldest one.
MessageReader
s will read messages from both buffers.MessageReader
s that read at least once per update will never drop messages.MessageReader
s that read once within two updates might still receive some messagesMessageReader
s that read after two updates are guaranteed to drop all messages that occurred before those updates.
The buffers in Messages
will grow indefinitely if update
is never called.
An alternative call pattern would be to call update
manually across frames to control when messages are cleared.
This complicates consumption and risks ever-expanding memory usage if not cleaned up,
but can be done by adding your message as a resource instead of using
add_message
.
Implementations§
Source§impl<M> Messages<M>where
M: Message,
impl<M> Messages<M>where
M: Message,
Sourcepub fn oldest_message_count(&self) -> usize
pub fn oldest_message_count(&self) -> usize
Returns the index of the oldest message stored in the message buffer.
Sourcepub fn write(&mut self, message: M) -> MessageId<M>
pub fn write(&mut self, message: M) -> MessageId<M>
Writes an message
to the current message buffer.
MessageReader
s can then read the message.
This method returns the ID of the written message
.
Sourcepub fn write_batch(
&mut self,
messages: impl IntoIterator<Item = M>,
) -> WriteBatchIds<M> ⓘ
pub fn write_batch( &mut self, messages: impl IntoIterator<Item = M>, ) -> WriteBatchIds<M> ⓘ
Writes a list of messages
all at once, which can later be read by MessageReader
s.
This is more efficient than writing each message individually.
This method returns the IDs of the written messages
.
Sourcepub fn write_default(&mut self) -> MessageId<M>where
M: Default,
pub fn write_default(&mut self) -> MessageId<M>where
M: Default,
Writes the default value of the message. Useful when the message is an empty struct.
This method returns the ID of the written message
.
Sourcepub fn send(&mut self, message: M) -> MessageId<M>
👎Deprecated since 0.17.0: Use Messages<E>::write
instead.
pub fn send(&mut self, message: M) -> MessageId<M>
Messages<E>::write
instead.“Sends” an message
by writing it to the current message buffer.
MessageReader
s can then read the message.
This method returns the ID of the sent message
.
Sourcepub fn send_batch(
&mut self,
messages: impl IntoIterator<Item = M>,
) -> WriteBatchIds<M> ⓘ
👎Deprecated since 0.17.0: Use Messages<E>::write_batch
instead.
pub fn send_batch( &mut self, messages: impl IntoIterator<Item = M>, ) -> WriteBatchIds<M> ⓘ
Messages<E>::write_batch
instead.Sends a list of messages
all at once, which can later be read by MessageReader
s.
This is more efficient than sending each message individually.
This method returns the IDs of the sent messages
.
Sourcepub fn send_default(&mut self) -> MessageId<M>where
M: Default,
👎Deprecated since 0.17.0: Use Messages<E>::write_default
instead.
pub fn send_default(&mut self) -> MessageId<M>where
M: Default,
Messages<E>::write_default
instead.Sends the default value of the message. Useful when the message is an empty struct.
This method returns the ID of the sent message
.
Sourcepub fn get_cursor(&self) -> MessageCursor<M>
pub fn get_cursor(&self) -> MessageCursor<M>
Gets a new MessageCursor
. This will include all messages already in the message buffers.
Sourcepub fn get_cursor_current(&self) -> MessageCursor<M>
pub fn get_cursor_current(&self) -> MessageCursor<M>
Gets a new MessageCursor
. This will ignore all messages already in the message buffers.
It will read all future messages.
Sourcepub fn update(&mut self)
pub fn update(&mut self)
Swaps the message buffers and clears the oldest message buffer. In general, this should be called once per frame/update.
If you need access to the messages that were removed, consider using Messages::update_drain
.
Sourcepub fn update_drain(&mut self) -> impl Iterator<Item = M>
pub fn update_drain(&mut self) -> impl Iterator<Item = M>
Swaps the message buffers and drains the oldest message buffer, returning an iterator of all messages that were removed. In general, this should be called once per frame/update.
If you do not need to take ownership of the removed messages, use Messages::update
instead.
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of messages currently stored in the message buffer.
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if there are no messages currently stored in the message buffer.
Sourcepub fn drain(&mut self) -> impl Iterator<Item = M>
pub fn drain(&mut self) -> impl Iterator<Item = M>
Creates a draining iterator that removes all messages.
Sourcepub fn iter_current_update_messages(&self) -> impl ExactSizeIterator
pub fn iter_current_update_messages(&self) -> impl ExactSizeIterator
Iterates over messages that happened since the last “update” call.
WARNING: You probably don’t want to use this call. In most cases you should use an
MessageReader
. You should only use this if you know you only need to consume messages
between the last update()
call and your call to iter_current_update_messages
.
If messages happen outside that window, they will not be handled. For example, any messages that
happen after this call and before the next update()
call will be dropped.
Trait Implementations§
Source§impl<E> Extend<E> for Messages<E>where
E: Message,
impl<E> Extend<E> for Messages<E>where
E: Message,
Source§fn extend<I>(&mut self, iter: I)where
I: IntoIterator<Item = E>,
fn extend<I>(&mut self, iter: I)where
I: IntoIterator<Item = E>,
Source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one
)Source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one
)Source§impl<E> FromReflect for Messages<E>
impl<E> FromReflect for Messages<E>
Source§fn from_reflect(reflect: &(dyn PartialReflect + 'static)) -> Option<Messages<E>>
fn from_reflect(reflect: &(dyn PartialReflect + 'static)) -> Option<Messages<E>>
Self
from a reflected value.Source§fn take_from_reflect(
reflect: Box<dyn PartialReflect>,
) -> Result<Self, Box<dyn PartialReflect>>
fn take_from_reflect( reflect: Box<dyn PartialReflect>, ) -> Result<Self, Box<dyn PartialReflect>>
Self
using,
constructing the value using from_reflect
if that fails. Read moreSource§impl<E> GetTypeRegistration for Messages<E>
impl<E> GetTypeRegistration for Messages<E>
Source§fn get_type_registration() -> TypeRegistration
fn get_type_registration() -> TypeRegistration
TypeRegistration
for this type.Source§fn register_type_dependencies(registry: &mut TypeRegistry)
fn register_type_dependencies(registry: &mut TypeRegistry)
Source§impl<E> PartialReflect for Messages<E>
impl<E> PartialReflect for Messages<E>
Source§fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
Source§fn try_apply(
&mut self,
value: &(dyn PartialReflect + 'static),
) -> Result<(), ApplyError>
fn try_apply( &mut self, value: &(dyn PartialReflect + 'static), ) -> Result<(), ApplyError>
Source§fn reflect_kind(&self) -> ReflectKind
fn reflect_kind(&self) -> ReflectKind
Source§fn reflect_ref(&self) -> ReflectRef<'_>
fn reflect_ref(&self) -> ReflectRef<'_>
Source§fn reflect_mut(&mut self) -> ReflectMut<'_>
fn reflect_mut(&mut self) -> ReflectMut<'_>
Source§fn reflect_owned(self: Box<Messages<E>>) -> ReflectOwned
fn reflect_owned(self: Box<Messages<E>>) -> ReflectOwned
Source§fn try_into_reflect(
self: Box<Messages<E>>,
) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>
fn try_into_reflect( self: Box<Messages<E>>, ) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>
Source§fn try_as_reflect(&self) -> Option<&(dyn Reflect + 'static)>
fn try_as_reflect(&self) -> Option<&(dyn Reflect + 'static)>
Source§fn try_as_reflect_mut(&mut self) -> Option<&mut (dyn Reflect + 'static)>
fn try_as_reflect_mut(&mut self) -> Option<&mut (dyn Reflect + 'static)>
Source§fn into_partial_reflect(self: Box<Messages<E>>) -> Box<dyn PartialReflect>
fn into_partial_reflect(self: Box<Messages<E>>) -> Box<dyn PartialReflect>
Source§fn as_partial_reflect(&self) -> &(dyn PartialReflect + 'static)
fn as_partial_reflect(&self) -> &(dyn PartialReflect + 'static)
Source§fn as_partial_reflect_mut(&mut self) -> &mut (dyn PartialReflect + 'static)
fn as_partial_reflect_mut(&mut self) -> &mut (dyn PartialReflect + 'static)
Source§fn reflect_partial_eq(
&self,
value: &(dyn PartialReflect + 'static),
) -> Option<bool>
fn reflect_partial_eq( &self, value: &(dyn PartialReflect + 'static), ) -> Option<bool>
Source§fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError>
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError>
Self
using reflection. Read moreSource§fn apply(&mut self, value: &(dyn PartialReflect + 'static))
fn apply(&mut self, value: &(dyn PartialReflect + 'static))
Source§fn to_dynamic(&self) -> Box<dyn PartialReflect>
fn to_dynamic(&self) -> Box<dyn PartialReflect>
Source§fn reflect_clone_and_take<T>(&self) -> Result<T, ReflectCloneError>
fn reflect_clone_and_take<T>(&self) -> Result<T, ReflectCloneError>
PartialReflect
, combines reflect_clone
and
take
in a useful fashion, automatically constructing an appropriate
ReflectCloneError
if the downcast fails. Read moreSource§fn reflect_hash(&self) -> Option<u64>
fn reflect_hash(&self) -> Option<u64>
Source§fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>
fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>
Source§fn is_dynamic(&self) -> bool
fn is_dynamic(&self) -> bool
Source§impl<E> Reflect for Messages<E>
impl<E> Reflect for Messages<E>
Source§fn into_any(self: Box<Messages<E>>) -> Box<dyn Any>
fn into_any(self: Box<Messages<E>>) -> Box<dyn Any>
Box<dyn Any>
. Read moreSource§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut dyn Any
. Read moreSource§fn into_reflect(self: Box<Messages<E>>) -> Box<dyn Reflect>
fn into_reflect(self: Box<Messages<E>>) -> Box<dyn Reflect>
Source§fn as_reflect(&self) -> &(dyn Reflect + 'static)
fn as_reflect(&self) -> &(dyn Reflect + 'static)
Source§fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)
fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)
Source§impl<E> Struct for Messages<E>
impl<E> Struct for Messages<E>
Source§fn field(&self, name: &str) -> Option<&(dyn PartialReflect + 'static)>
fn field(&self, name: &str) -> Option<&(dyn PartialReflect + 'static)>
name
as a &dyn PartialReflect
.Source§fn field_mut(
&mut self,
name: &str,
) -> Option<&mut (dyn PartialReflect + 'static)>
fn field_mut( &mut self, name: &str, ) -> Option<&mut (dyn PartialReflect + 'static)>
name
as a
&mut dyn PartialReflect
.Source§fn field_at(&self, index: usize) -> Option<&(dyn PartialReflect + 'static)>
fn field_at(&self, index: usize) -> Option<&(dyn PartialReflect + 'static)>
index
as a
&dyn PartialReflect
.Source§fn field_at_mut(
&mut self,
index: usize,
) -> Option<&mut (dyn PartialReflect + 'static)>
fn field_at_mut( &mut self, index: usize, ) -> Option<&mut (dyn PartialReflect + 'static)>
index
as a &mut dyn PartialReflect
.Source§fn name_at(&self, index: usize) -> Option<&str>
fn name_at(&self, index: usize) -> Option<&str>
index
.Source§fn iter_fields(&self) -> FieldIter<'_> ⓘ
fn iter_fields(&self) -> FieldIter<'_> ⓘ
Source§fn to_dynamic_struct(&self) -> DynamicStruct
fn to_dynamic_struct(&self) -> DynamicStruct
DynamicStruct
from this struct.Source§fn get_represented_struct_info(&self) -> Option<&'static StructInfo>
fn get_represented_struct_info(&self) -> Option<&'static StructInfo>
None
if TypeInfo
is not available.Source§impl<E> TypePath for Messages<E>
impl<E> TypePath for Messages<E>
Source§fn type_path() -> &'static str
fn type_path() -> &'static str
Source§fn short_type_path() -> &'static str
fn short_type_path() -> &'static str
Source§fn type_ident() -> Option<&'static str>
fn type_ident() -> Option<&'static str>
Source§fn crate_name() -> Option<&'static str>
fn crate_name() -> Option<&'static str>
impl<E> Resource for Messages<E>
Auto Trait Implementations§
impl<E> Freeze for Messages<E>
impl<E> RefUnwindSafe for Messages<E>where
E: RefUnwindSafe,
impl<E> Send for Messages<E>
impl<E> Sync for Messages<E>
impl<E> Unpin for Messages<E>where
E: Unpin,
impl<E> UnwindSafe for Messages<E>where
E: UnwindSafe,
Blanket Implementations§
Source§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
Source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T
ShaderType
for self
. When used in AsBindGroup
derives, it is safe to assume that all images in self
exist.Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
, which can then be
downcast
into Box<dyn ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
, which can then be further
downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> DynamicTypePath for Twhere
T: TypePath,
impl<T> DynamicTypePath for Twhere
T: TypePath,
Source§fn reflect_type_path(&self) -> &str
fn reflect_type_path(&self) -> &str
TypePath::type_path
.Source§fn reflect_short_type_path(&self) -> &str
fn reflect_short_type_path(&self) -> &str
Source§fn reflect_type_ident(&self) -> Option<&str>
fn reflect_type_ident(&self) -> Option<&str>
TypePath::type_ident
.Source§fn reflect_crate_name(&self) -> Option<&str>
fn reflect_crate_name(&self) -> Option<&str>
TypePath::crate_name
.Source§fn reflect_module_path(&self) -> Option<&str>
fn reflect_module_path(&self) -> Option<&str>
Source§impl<T> DynamicTyped for Twhere
T: Typed,
impl<T> DynamicTyped for Twhere
T: Typed,
Source§fn reflect_type_info(&self) -> &'static TypeInfo
fn reflect_type_info(&self) -> &'static TypeInfo
Typed::type_info
.Source§impl<T> FromWorld for Twhere
T: Default,
impl<T> FromWorld for Twhere
T: Default,
Source§fn from_world(_world: &mut World) -> T
fn from_world(_world: &mut World) -> T
Creates Self
using default()
.
Source§impl<S> GetField for Swhere
S: Struct,
impl<S> GetField for Swhere
S: Struct,
Source§impl<T> GetPath for T
impl<T> GetPath for T
Source§fn reflect_path<'p>(
&self,
path: impl ReflectPath<'p>,
) -> Result<&(dyn PartialReflect + 'static), ReflectPathError<'p>>
fn reflect_path<'p>( &self, path: impl ReflectPath<'p>, ) -> Result<&(dyn PartialReflect + 'static), ReflectPathError<'p>>
path
. Read moreSource§fn reflect_path_mut<'p>(
&mut self,
path: impl ReflectPath<'p>,
) -> Result<&mut (dyn PartialReflect + 'static), ReflectPathError<'p>>
fn reflect_path_mut<'p>( &mut self, path: impl ReflectPath<'p>, ) -> Result<&mut (dyn PartialReflect + 'static), ReflectPathError<'p>>
path
. Read moreSource§fn path<'p, T>(
&self,
path: impl ReflectPath<'p>,
) -> Result<&T, ReflectPathError<'p>>where
T: Reflect,
fn path<'p, T>(
&self,
path: impl ReflectPath<'p>,
) -> Result<&T, ReflectPathError<'p>>where
T: Reflect,
path
. Read moreSource§fn path_mut<'p, T>(
&mut self,
path: impl ReflectPath<'p>,
) -> Result<&mut T, ReflectPathError<'p>>where
T: Reflect,
fn path_mut<'p, T>(
&mut self,
path: impl ReflectPath<'p>,
) -> Result<&mut T, ReflectPathError<'p>>where
T: Reflect,
path
. Read moreSource§impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
Source§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more