Mutex

Struct Mutex 

1.0.0 · Source
pub struct Mutex<T>
where T: ?Sized,
{ /* private fields */ }
Expand description

A mutual exclusion primitive useful for protecting shared data

This mutex will block threads waiting for the lock to become available. The mutex can be created via a new constructor. Each mutex has a type parameter which represents the data that it is protecting. The data can only be accessed through the RAII guards returned from lock and try_lock, which guarantees that the data is only ever accessed when the mutex is locked.

§Poisoning

The mutexes in this module implement a strategy called “poisoning” where a mutex becomes poisoned if it recognizes that the thread holding it has panicked.

Once a mutex is poisoned, all other threads are unable to access the data by default as it is likely tainted (some invariant is not being upheld). For a mutex, this means that the lock and try_lock methods return a Result which indicates whether a mutex has been poisoned or not. Most usage of a mutex will simply unwrap() these results, propagating panics among threads to ensure that a possibly invalid invariant is not witnessed.

Poisoning is only advisory: the PoisonError type has an into_inner method which will return the guard that would have otherwise been returned on a successful lock. This allows access to the data, despite the lock being poisoned.

In addition, the panic detection is not ideal, so even unpoisoned mutexes need to be handled with care, since certain panics may have been skipped. Here is a non-exhaustive list of situations where this might occur:

  • If a mutex is locked while a panic is underway, e.g. within a Drop implementation or a panic hook, panicking for the second time while the lock is held will leave the mutex unpoisoned. Note that while double panic usually aborts the program, catch_unwind can prevent this.

  • Locking and unlocking the mutex across different panic contexts, e.g. by storing the guard to a Cell within Drop::drop and accessing it outside, or vice versa, can affect poisoning status in an unexpected way.

  • Foreign exceptions do not currently trigger poisoning even in absence of other panics.

While this rarely happens in realistic code, unsafe code cannot rely on poisoning for soundness, since the behavior of poisoning can depend on outside context. Here’s an example of incorrect use of poisoning:

use std::sync::Mutex;

struct MutexBox<T> {
    data: Mutex<*mut T>,
}

impl<T> MutexBox<T> {
    pub fn new(value: T) -> Self {
        Self {
            data: Mutex::new(Box::into_raw(Box::new(value))),
        }
    }

    pub fn replace_with(&self, f: impl FnOnce(T) -> T) {
        let ptr = self.data.lock().expect("poisoned");
        // While `f` is running, the data is moved out of `*ptr`. If `f`
        // panics, `*ptr` keeps pointing at a dropped value. The intention
        // is that this will poison the mutex, so the following calls to
        // `replace_with` will panic without reading `*ptr`. But since
        // poisoning is not guaranteed to occur if this is run from a panic
        // hook, this can lead to use-after-free.
        unsafe {
            (*ptr).write(f((*ptr).read()));
        }
    }
}

§Examples

use std::sync::{Arc, Mutex};
use std::thread;
use std::sync::mpsc::channel;

const N: usize = 10;

// Spawn a few threads to increment a shared variable (non-atomically), and
// let the main thread know once all increments are done.
//
// Here we're using an Arc to share memory among threads, and the data inside
// the Arc is protected with a mutex.
let data = Arc::new(Mutex::new(0));

let (tx, rx) = channel();
for _ in 0..N {
    let (data, tx) = (Arc::clone(&data), tx.clone());
    thread::spawn(move || {
        // The shared state can only be accessed once the lock is held.
        // Our non-atomic increment is safe because we're the only thread
        // which can access the shared state when the lock is held.
        //
        // We unwrap() the return value to assert that we are not expecting
        // threads to ever fail while holding the lock.
        let mut data = data.lock().unwrap();
        *data += 1;
        if *data == N {
            tx.send(()).unwrap();
        }
        // the lock is unlocked here when `data` goes out of scope.
    });
}

rx.recv().unwrap();

To recover from a poisoned mutex:

use std::sync::{Arc, Mutex};
use std::thread;

let lock = Arc::new(Mutex::new(0_u32));
let lock2 = Arc::clone(&lock);

let _ = thread::spawn(move || -> () {
    // This thread will acquire the mutex first, unwrapping the result of
    // `lock` because the lock has not been poisoned.
    let _guard = lock2.lock().unwrap();

    // This panic while holding the lock (`_guard` is in scope) will poison
    // the mutex.
    panic!();
}).join();

// The lock is poisoned by this point, but the returned result can be
// pattern matched on to return the underlying guard on both branches.
let mut guard = match lock.lock() {
    Ok(guard) => guard,
    Err(poisoned) => poisoned.into_inner(),
};

*guard += 1;

To unlock a mutex guard sooner than the end of the enclosing scope, either create an inner scope or drop the guard manually.

use std::sync::{Arc, Mutex};
use std::thread;

const N: usize = 3;

let data_mutex = Arc::new(Mutex::new(vec![1, 2, 3, 4]));
let res_mutex = Arc::new(Mutex::new(0));

let mut threads = Vec::with_capacity(N);
(0..N).for_each(|_| {
    let data_mutex_clone = Arc::clone(&data_mutex);
    let res_mutex_clone = Arc::clone(&res_mutex);

    threads.push(thread::spawn(move || {
        // Here we use a block to limit the lifetime of the lock guard.
        let result = {
            let mut data = data_mutex_clone.lock().unwrap();
            // This is the result of some important and long-ish work.
            let result = data.iter().fold(0, |acc, x| acc + x * 2);
            data.push(result);
            result
            // The mutex guard gets dropped here, together with any other values
            // created in the critical section.
        };
        // The guard created here is a temporary dropped at the end of the statement, i.e.
        // the lock would not remain being held even if the thread did some additional work.
        *res_mutex_clone.lock().unwrap() += result;
    }));
});

let mut data = data_mutex.lock().unwrap();
// This is the result of some important and long-ish work.
let result = data.iter().fold(0, |acc, x| acc + x * 2);
data.push(result);
// We drop the `data` explicitly because it's not necessary anymore and the
// thread still has work to do. This allows other threads to start working on
// the data immediately, without waiting for the rest of the unrelated work
// to be done here.
//
// It's even more important here than in the threads because we `.join` the
// threads after that. If we had not dropped the mutex guard, a thread could
// be waiting forever for it, causing a deadlock.
// As in the threads, a block could have been used instead of calling the
// `drop` function.
drop(data);
// Here the mutex guard is not assigned to a variable and so, even if the
// scope does not end after this line, the mutex is still released: there is
// no deadlock.
*res_mutex.lock().unwrap() += result;

threads.into_iter().for_each(|thread| {
    thread
        .join()
        .expect("The thread creating or execution failed !")
});

assert_eq!(*res_mutex.lock().unwrap(), 800);

Implementations§

Source§

impl<T> Mutex<T>

1.0.0 (const: 1.63.0) · Source

pub const fn new(t: T) -> Mutex<T>

Creates a new mutex in an unlocked state ready for use.

§Examples
use std::sync::Mutex;

let mutex = Mutex::new(0);
Examples found in repository?
examples/3d/occlusion_culling.rs (line 142)
141    fn new() -> Self {
142        Self(Arc::new(Mutex::new(None)))
143    }
Source

pub fn get_cloned(&self) -> Result<T, PoisonError<()>>
where T: Clone,

🔬This is a nightly-only experimental API. (lock_value_accessors)

Returns the contained value by cloning it.

§Errors

If another user of this mutex panicked while holding the mutex, then this call will return an error instead.

§Examples
#![feature(lock_value_accessors)]

use std::sync::Mutex;

let mut mutex = Mutex::new(7);

assert_eq!(mutex.get_cloned().unwrap(), 7);
Source

pub fn set(&self, value: T) -> Result<(), PoisonError<T>>

🔬This is a nightly-only experimental API. (lock_value_accessors)

Sets the contained value.

§Errors

If another user of this mutex panicked while holding the mutex, then this call will return an error containing the provided value instead.

§Examples
#![feature(lock_value_accessors)]

use std::sync::Mutex;

let mut mutex = Mutex::new(7);

assert_eq!(mutex.get_cloned().unwrap(), 7);
mutex.set(11).unwrap();
assert_eq!(mutex.get_cloned().unwrap(), 11);
Source

pub fn replace(&self, value: T) -> Result<T, PoisonError<T>>

🔬This is a nightly-only experimental API. (lock_value_accessors)

Replaces the contained value with value, and returns the old contained value.

§Errors

If another user of this mutex panicked while holding the mutex, then this call will return an error containing the provided value instead.

§Examples
#![feature(lock_value_accessors)]

use std::sync::Mutex;

let mut mutex = Mutex::new(7);

assert_eq!(mutex.replace(11).unwrap(), 7);
assert_eq!(mutex.get_cloned().unwrap(), 11);
Source§

impl<T> Mutex<T>
where T: ?Sized,

1.0.0 · Source

pub fn lock(&self) -> Result<MutexGuard<'_, T>, PoisonError<MutexGuard<'_, T>>>

Acquires a mutex, blocking the current thread until it is able to do so.

This function will block the local thread until it is available to acquire the mutex. Upon returning, the thread is the only thread with the lock held. An RAII guard is returned to allow scoped unlock of the lock. When the guard goes out of scope, the mutex will be unlocked.

The exact behavior on locking a mutex in the thread which already holds the lock is left unspecified. However, this function will not return on the second call (it might panic or deadlock, for example).

§Errors

If another user of this mutex panicked while holding the mutex, then this call will return an error once the mutex is acquired. The acquired mutex guard will be contained in the returned error.

§Panics

This function might panic when called if the lock is already held by the current thread.

§Examples
use std::sync::{Arc, Mutex};
use std::thread;

let mutex = Arc::new(Mutex::new(0));
let c_mutex = Arc::clone(&mutex);

thread::spawn(move || {
    *c_mutex.lock().unwrap() = 10;
}).join().expect("thread::spawn failed");
assert_eq!(*mutex.lock().unwrap(), 10);
Examples found in repository?
examples/3d/occlusion_culling.rs (line 151)
146fn init_saved_indirect_parameters(
147    render_device: Res<RenderDevice>,
148    gpu_preprocessing_support: Res<GpuPreprocessingSupport>,
149    saved_indirect_parameters: Res<SavedIndirectParameters>,
150) {
151    let mut saved_indirect_parameters = saved_indirect_parameters.0.lock().unwrap();
152    *saved_indirect_parameters = Some(SavedIndirectParametersData {
153        data: vec![],
154        count: 0,
155        occlusion_culling_supported: gpu_preprocessing_support.is_culling_supported(),
156        // In order to determine how many meshes were culled, we look at the indirect count buffer
157        // that Bevy only populates if the platform supports `multi_draw_indirect_count`. So, if we
158        // don't have that feature, then we don't bother to display how many meshes were culled.
159        occlusion_culling_introspection_supported: render_device
160            .features()
161            .contains(WgpuFeatures::MULTI_DRAW_INDIRECT_COUNT),
162    });
163}
164
165/// The demo's current settings.
166#[derive(Resource)]
167struct AppStatus {
168    /// Whether occlusion culling is presently enabled.
169    ///
170    /// By default, this is set to true.
171    occlusion_culling: bool,
172}
173
174impl Default for AppStatus {
175    fn default() -> Self {
176        AppStatus {
177            occlusion_culling: true,
178        }
179    }
180}
181
182fn main() {
183    let render_debug_flags = RenderDebugFlags::ALLOW_COPIES_FROM_INDIRECT_PARAMETERS;
184
185    App::new()
186        .add_plugins(
187            DefaultPlugins
188                .set(WindowPlugin {
189                    primary_window: Some(Window {
190                        title: "Bevy Occlusion Culling Example".into(),
191                        ..default()
192                    }),
193                    ..default()
194                })
195                .set(RenderPlugin {
196                    debug_flags: render_debug_flags,
197                    ..default()
198                })
199                .set(PbrPlugin {
200                    debug_flags: render_debug_flags,
201                    ..default()
202                }),
203        )
204        .add_plugins(ReadbackIndirectParametersPlugin)
205        .init_resource::<AppStatus>()
206        .add_systems(Startup, setup)
207        .add_systems(Update, spin_small_cubes)
208        .add_systems(Update, spin_large_cube)
209        .add_systems(Update, update_status_text)
210        .add_systems(Update, toggle_occlusion_culling_on_request)
211        .run();
212}
213
214impl Plugin for ReadbackIndirectParametersPlugin {
215    fn build(&self, app: &mut App) {
216        // Create the `SavedIndirectParameters` resource that we're going to use
217        // to communicate between the thread that the GPU-to-CPU readback
218        // callback runs on and the main application threads. This resource is
219        // atomically reference counted. We store one reference to the
220        // `SavedIndirectParameters` in the main app and another reference in
221        // the render app.
222        let saved_indirect_parameters = SavedIndirectParameters::new();
223        app.insert_resource(saved_indirect_parameters.clone());
224
225        // Fetch the render app.
226        let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
227            return;
228        };
229
230        render_app
231            // Insert another reference to the `SavedIndirectParameters`.
232            .insert_resource(saved_indirect_parameters)
233            // Setup the parameters in RenderStartup.
234            .add_systems(RenderStartup, init_saved_indirect_parameters)
235            .init_resource::<IndirectParametersStagingBuffers>()
236            .add_systems(ExtractSchedule, readback_indirect_parameters)
237            .add_systems(
238                Render,
239                create_indirect_parameters_staging_buffers
240                    .in_set(RenderSystems::PrepareResourcesFlush),
241            )
242            // Add the node that allows us to read the indirect parameters back
243            // from the GPU to the CPU, which allows us to determine how many
244            // meshes were culled.
245            .add_render_graph_node::<ReadbackIndirectParametersNode>(
246                Core3d,
247                ReadbackIndirectParameters,
248            )
249            // We read back the indirect parameters any time after
250            // `EndMainPass`. Readback doesn't particularly need to execute
251            // before `EndMainPassPostProcessing`, but we specify that anyway
252            // because we want to make the indirect parameters run before
253            // *something* in the graph, and `EndMainPassPostProcessing` is a
254            // good a node as any other.
255            .add_render_graph_edges(
256                Core3d,
257                (
258                    Node3d::EndMainPass,
259                    ReadbackIndirectParameters,
260                    Node3d::EndMainPassPostProcessing,
261                ),
262            );
263    }
264}
265
266/// Spawns all the objects in the scene.
267fn setup(
268    mut commands: Commands,
269    asset_server: Res<AssetServer>,
270    mut meshes: ResMut<Assets<Mesh>>,
271    mut materials: ResMut<Assets<StandardMaterial>>,
272) {
273    spawn_small_cubes(&mut commands, &mut meshes, &mut materials);
274    spawn_large_cube(&mut commands, &asset_server, &mut meshes, &mut materials);
275    spawn_light(&mut commands);
276    spawn_camera(&mut commands);
277    spawn_help_text(&mut commands);
278}
279
280/// Spawns the rotating sphere of small cubes.
281fn spawn_small_cubes(
282    commands: &mut Commands,
283    meshes: &mut Assets<Mesh>,
284    materials: &mut Assets<StandardMaterial>,
285) {
286    // Add the cube mesh.
287    let small_cube = meshes.add(Cuboid::new(
288        SMALL_CUBE_SIZE,
289        SMALL_CUBE_SIZE,
290        SMALL_CUBE_SIZE,
291    ));
292
293    // Add the cube material.
294    let small_cube_material = materials.add(StandardMaterial {
295        base_color: SILVER.into(),
296        ..default()
297    });
298
299    // Create the entity that the small cubes will be parented to. This is the
300    // entity that we rotate.
301    let sphere_parent = commands
302        .spawn(Transform::from_translation(Vec3::ZERO))
303        .insert(Visibility::default())
304        .insert(SphereParent)
305        .id();
306
307    // Now we have to figure out where to place the cubes. To do that, we create
308    // a sphere mesh, but we don't add it to the scene. Instead, we inspect the
309    // sphere mesh to find the positions of its vertices, and spawn a small cube
310    // at each one. That way, we end up with a bunch of cubes arranged in a
311    // spherical shape.
312
313    // Create the sphere mesh, and extract the positions of its vertices.
314    let sphere = Sphere::new(OUTER_RADIUS)
315        .mesh()
316        .ico(OUTER_SUBDIVISION_COUNT)
317        .unwrap();
318    let sphere_positions = sphere.attribute(Mesh::ATTRIBUTE_POSITION).unwrap();
319
320    // At each vertex, create a small cube.
321    for sphere_position in sphere_positions.as_float3().unwrap() {
322        let sphere_position = Vec3::from_slice(sphere_position);
323        let small_cube = commands
324            .spawn(Mesh3d(small_cube.clone()))
325            .insert(MeshMaterial3d(small_cube_material.clone()))
326            .insert(Transform::from_translation(sphere_position))
327            .id();
328        commands.entity(sphere_parent).add_child(small_cube);
329    }
330}
331
332/// Spawns the large cube at the center of the screen.
333///
334/// This cube rotates chaotically and occludes small cubes behind it.
335fn spawn_large_cube(
336    commands: &mut Commands,
337    asset_server: &AssetServer,
338    meshes: &mut Assets<Mesh>,
339    materials: &mut Assets<StandardMaterial>,
340) {
341    commands
342        .spawn(Mesh3d(meshes.add(Cuboid::new(
343            LARGE_CUBE_SIZE,
344            LARGE_CUBE_SIZE,
345            LARGE_CUBE_SIZE,
346        ))))
347        .insert(MeshMaterial3d(materials.add(StandardMaterial {
348            base_color: WHITE.into(),
349            base_color_texture: Some(asset_server.load("branding/icon.png")),
350            ..default()
351        })))
352        .insert(Transform::IDENTITY)
353        .insert(LargeCube);
354}
355
356// Spins the outer sphere a bit every frame.
357//
358// This ensures that the set of cubes that are hidden and shown varies over
359// time.
360fn spin_small_cubes(mut sphere_parents: Query<&mut Transform, With<SphereParent>>) {
361    for mut sphere_parent_transform in &mut sphere_parents {
362        sphere_parent_transform.rotate_y(ROTATION_SPEED);
363    }
364}
365
366/// Spins the large cube a bit every frame.
367///
368/// The chaotic rotation adds a bit of randomness to the scene to better
369/// demonstrate the dynamicity of the occlusion culling.
370fn spin_large_cube(mut large_cubes: Query<&mut Transform, With<LargeCube>>) {
371    for mut transform in &mut large_cubes {
372        transform.rotate(Quat::from_euler(
373            EulerRot::XYZ,
374            0.13 * ROTATION_SPEED,
375            0.29 * ROTATION_SPEED,
376            0.35 * ROTATION_SPEED,
377        ));
378    }
379}
380
381/// Spawns a directional light to illuminate the scene.
382fn spawn_light(commands: &mut Commands) {
383    commands
384        .spawn(DirectionalLight::default())
385        .insert(Transform::from_rotation(Quat::from_euler(
386            EulerRot::ZYX,
387            0.0,
388            PI * -0.15,
389            PI * -0.15,
390        )));
391}
392
393/// Spawns a camera that includes the depth prepass and occlusion culling.
394fn spawn_camera(commands: &mut Commands) {
395    commands
396        .spawn(Camera3d::default())
397        .insert(Transform::from_xyz(0.0, 0.0, 9.0).looking_at(Vec3::ZERO, Vec3::Y))
398        .insert(DepthPrepass)
399        .insert(OcclusionCulling);
400}
401
402/// Spawns the help text at the upper left of the screen.
403fn spawn_help_text(commands: &mut Commands) {
404    commands.spawn((
405        Text::new(""),
406        Node {
407            position_type: PositionType::Absolute,
408            top: px(12),
409            left: px(12),
410            ..default()
411        },
412    ));
413}
414
415impl render_graph::Node for ReadbackIndirectParametersNode {
416    fn run<'w>(
417        &self,
418        _: &mut RenderGraphContext,
419        render_context: &mut RenderContext<'w>,
420        world: &'w World,
421    ) -> Result<(), NodeRunError> {
422        // Extract the buffers that hold the GPU indirect draw parameters from
423        // the world resources. We're going to read those buffers to determine
424        // how many meshes were actually drawn.
425        let (Some(indirect_parameters_buffers), Some(indirect_parameters_mapping_buffers)) = (
426            world.get_resource::<IndirectParametersBuffers>(),
427            world.get_resource::<IndirectParametersStagingBuffers>(),
428        ) else {
429            return Ok(());
430        };
431
432        // Get the indirect parameters buffers corresponding to the opaque 3D
433        // phase, since all our meshes are in that phase.
434        let Some(phase_indirect_parameters_buffers) =
435            indirect_parameters_buffers.get(&TypeId::of::<Opaque3d>())
436        else {
437            return Ok(());
438        };
439
440        // Grab both the buffers we're copying from and the staging buffers
441        // we're copying to. Remember that we can't map the indirect parameters
442        // buffers directly, so we have to copy their contents to a staging
443        // buffer.
444        let (
445            Some(indexed_data_buffer),
446            Some(indexed_batch_sets_buffer),
447            Some(indirect_parameters_staging_data_buffer),
448            Some(indirect_parameters_staging_batch_sets_buffer),
449        ) = (
450            phase_indirect_parameters_buffers.indexed.data_buffer(),
451            phase_indirect_parameters_buffers
452                .indexed
453                .batch_sets_buffer(),
454            indirect_parameters_mapping_buffers.data.as_ref(),
455            indirect_parameters_mapping_buffers.batch_sets.as_ref(),
456        )
457        else {
458            return Ok(());
459        };
460
461        // Copy from the indirect parameters buffers to the staging buffers.
462        render_context.command_encoder().copy_buffer_to_buffer(
463            indexed_data_buffer,
464            0,
465            indirect_parameters_staging_data_buffer,
466            0,
467            indexed_data_buffer.size(),
468        );
469        render_context.command_encoder().copy_buffer_to_buffer(
470            indexed_batch_sets_buffer,
471            0,
472            indirect_parameters_staging_batch_sets_buffer,
473            0,
474            indexed_batch_sets_buffer.size(),
475        );
476
477        Ok(())
478    }
479}
480
481/// Creates the staging buffers that we use to read back the indirect parameters
482/// from the GPU to the CPU.
483///
484/// We read the indirect parameters from the GPU to the CPU in order to display
485/// the number of meshes that were culled each frame.
486///
487/// We need these staging buffers because `wgpu` doesn't allow us to read the
488/// contents of the indirect parameters buffers directly. We must first copy
489/// them from the GPU to a staging buffer, and then read the staging buffer.
490fn create_indirect_parameters_staging_buffers(
491    mut indirect_parameters_staging_buffers: ResMut<IndirectParametersStagingBuffers>,
492    indirect_parameters_buffers: Res<IndirectParametersBuffers>,
493    render_device: Res<RenderDevice>,
494) {
495    let Some(phase_indirect_parameters_buffers) =
496        indirect_parameters_buffers.get(&TypeId::of::<Opaque3d>())
497    else {
498        return;
499    };
500
501    // Fetch the indirect parameters buffers that we're going to copy from.
502    let (Some(indexed_data_buffer), Some(indexed_batch_set_buffer)) = (
503        phase_indirect_parameters_buffers.indexed.data_buffer(),
504        phase_indirect_parameters_buffers
505            .indexed
506            .batch_sets_buffer(),
507    ) else {
508        return;
509    };
510
511    // Build the staging buffers. Make sure they have the same sizes as the
512    // buffers we're copying from.
513    indirect_parameters_staging_buffers.data =
514        Some(render_device.create_buffer(&BufferDescriptor {
515            label: Some("indexed data staging buffer"),
516            size: indexed_data_buffer.size(),
517            usage: BufferUsages::MAP_READ | BufferUsages::COPY_DST,
518            mapped_at_creation: false,
519        }));
520    indirect_parameters_staging_buffers.batch_sets =
521        Some(render_device.create_buffer(&BufferDescriptor {
522            label: Some("indexed batch set staging buffer"),
523            size: indexed_batch_set_buffer.size(),
524            usage: BufferUsages::MAP_READ | BufferUsages::COPY_DST,
525            mapped_at_creation: false,
526        }));
527}
528
529/// Updates the app status text at the top of the screen.
530fn update_status_text(
531    saved_indirect_parameters: Res<SavedIndirectParameters>,
532    mut texts: Query<&mut Text>,
533    meshes: Query<Entity, With<Mesh3d>>,
534    app_status: Res<AppStatus>,
535) {
536    // How many meshes are in the scene?
537    let total_mesh_count = meshes.iter().count();
538
539    // Sample the rendered object count. Note that we don't synchronize beyond
540    // locking the data and therefore this will value will generally at least
541    // one frame behind. This is fine; this app is just a demonstration after
542    // all.
543    let (
544        rendered_object_count,
545        occlusion_culling_supported,
546        occlusion_culling_introspection_supported,
547    ): (u32, bool, bool) = {
548        let saved_indirect_parameters = saved_indirect_parameters.lock().unwrap();
549        let Some(saved_indirect_parameters) = saved_indirect_parameters.as_ref() else {
550            // Bail out early if the resource isn't initialized yet.
551            return;
552        };
553        (
554            saved_indirect_parameters
555                .data
556                .iter()
557                .take(saved_indirect_parameters.count as usize)
558                .map(|indirect_parameters| indirect_parameters.instance_count)
559                .sum(),
560            saved_indirect_parameters.occlusion_culling_supported,
561            saved_indirect_parameters.occlusion_culling_introspection_supported,
562        )
563    };
564
565    // Change the text.
566    for mut text in &mut texts {
567        text.0 = String::new();
568        if !occlusion_culling_supported {
569            text.0
570                .push_str("Occlusion culling not supported on this platform");
571            continue;
572        }
573
574        let _ = writeln!(
575            &mut text.0,
576            "Occlusion culling {} (Press Space to toggle)",
577            if app_status.occlusion_culling {
578                "ON"
579            } else {
580                "OFF"
581            },
582        );
583
584        if !occlusion_culling_introspection_supported {
585            continue;
586        }
587
588        let _ = write!(
589            &mut text.0,
590            "{rendered_object_count}/{total_mesh_count} meshes rendered"
591        );
592    }
593}
594
595/// A system that reads the indirect parameters back from the GPU so that we can
596/// report how many meshes were culled.
597fn readback_indirect_parameters(
598    mut indirect_parameters_staging_buffers: ResMut<IndirectParametersStagingBuffers>,
599    saved_indirect_parameters: Res<SavedIndirectParameters>,
600) {
601    // If culling isn't supported on this platform, bail.
602    if !saved_indirect_parameters
603        .lock()
604        .unwrap()
605        .as_ref()
606        .unwrap()
607        .occlusion_culling_supported
608    {
609        return;
610    }
611
612    // Grab the staging buffers.
613    let (Some(data_buffer), Some(batch_sets_buffer)) = (
614        indirect_parameters_staging_buffers.data.take(),
615        indirect_parameters_staging_buffers.batch_sets.take(),
616    ) else {
617        return;
618    };
619
620    // Read the GPU buffers back.
621    let saved_indirect_parameters_0 = (**saved_indirect_parameters).clone();
622    let saved_indirect_parameters_1 = (**saved_indirect_parameters).clone();
623    readback_buffer::<IndirectParametersIndexed>(data_buffer, move |indirect_parameters| {
624        saved_indirect_parameters_0
625            .lock()
626            .unwrap()
627            .as_mut()
628            .unwrap()
629            .data = indirect_parameters.to_vec();
630    });
631    readback_buffer::<u32>(batch_sets_buffer, move |indirect_parameters_count| {
632        saved_indirect_parameters_1
633            .lock()
634            .unwrap()
635            .as_mut()
636            .unwrap()
637            .count = indirect_parameters_count[0];
638    });
639}
1.0.0 · Source

pub fn try_lock( &self, ) -> Result<MutexGuard<'_, T>, TryLockError<MutexGuard<'_, T>>>

Attempts to acquire this lock.

If the lock could not be acquired at this time, then Err is returned. Otherwise, an RAII guard is returned. The lock will be unlocked when the guard is dropped.

This function does not block.

§Errors

If another user of this mutex panicked while holding the mutex, then this call will return the Poisoned error if the mutex would otherwise be acquired. An acquired lock guard will be contained in the returned error.

If the mutex could not be acquired because it is already locked, then this call will return the WouldBlock error.

§Examples
use std::sync::{Arc, Mutex};
use std::thread;

let mutex = Arc::new(Mutex::new(0));
let c_mutex = Arc::clone(&mutex);

thread::spawn(move || {
    let mut lock = c_mutex.try_lock();
    if let Ok(ref mut mutex) = lock {
        **mutex = 10;
    } else {
        println!("try_lock failed");
    }
}).join().expect("thread::spawn failed");
assert_eq!(*mutex.lock().unwrap(), 10);
1.2.0 · Source

pub fn is_poisoned(&self) -> bool

Determines whether the mutex is poisoned.

If another thread is active, the mutex can still become poisoned at any time. You should not trust a false value for program correctness without additional synchronization.

§Examples
use std::sync::{Arc, Mutex};
use std::thread;

let mutex = Arc::new(Mutex::new(0));
let c_mutex = Arc::clone(&mutex);

let _ = thread::spawn(move || {
    let _lock = c_mutex.lock().unwrap();
    panic!(); // the mutex gets poisoned
}).join();
assert_eq!(mutex.is_poisoned(), true);
1.77.0 · Source

pub fn clear_poison(&self)

Clear the poisoned state from a mutex.

If the mutex is poisoned, it will remain poisoned until this function is called. This allows recovering from a poisoned state and marking that it has recovered. For example, if the value is overwritten by a known-good value, then the mutex can be marked as un-poisoned. Or possibly, the value could be inspected to determine if it is in a consistent state, and if so the poison is removed.

§Examples
use std::sync::{Arc, Mutex};
use std::thread;

let mutex = Arc::new(Mutex::new(0));
let c_mutex = Arc::clone(&mutex);

let _ = thread::spawn(move || {
    let _lock = c_mutex.lock().unwrap();
    panic!(); // the mutex gets poisoned
}).join();

assert_eq!(mutex.is_poisoned(), true);
let x = mutex.lock().unwrap_or_else(|mut e| {
    **e.get_mut() = 1;
    mutex.clear_poison();
    e.into_inner()
});
assert_eq!(mutex.is_poisoned(), false);
assert_eq!(*x, 1);
1.6.0 · Source

pub fn into_inner(self) -> Result<T, PoisonError<T>>

Consumes this mutex, returning the underlying data.

§Errors

If another user of this mutex panicked while holding the mutex, then this call will return an error containing the underlying data instead.

§Examples
use std::sync::Mutex;

let mutex = Mutex::new(0);
assert_eq!(mutex.into_inner().unwrap(), 0);
1.6.0 · Source

pub fn get_mut(&mut self) -> Result<&mut T, PoisonError<&mut T>>

Returns a mutable reference to the underlying data.

Since this call borrows the Mutex mutably, no actual locking needs to take place – the mutable borrow statically guarantees no new locks can be acquired while this reference exists. Note that this method does not clear any previous abandoned locks (e.g., via forget() on a MutexGuard).

§Errors

If another user of this mutex panicked while holding the mutex, then this call will return an error containing a mutable reference to the underlying data instead.

§Examples
use std::sync::Mutex;

let mut mutex = Mutex::new(0);
*mutex.get_mut().unwrap() = 10;
assert_eq!(*mutex.lock().unwrap(), 10);
Source

pub const fn data_ptr(&self) -> *mut T

🔬This is a nightly-only experimental API. (mutex_data_ptr)

Returns a raw pointer to the underlying data.

The returned pointer is always non-null and properly aligned, but it is the user’s responsibility to ensure that any reads and writes through it are properly synchronized to avoid data races, and that it is not read or written through after the mutex is dropped.

Trait Implementations§

Source§

impl<T> Clear for Mutex<T>
where T: Clear,

Source§

fn clear(&mut self)

Clear all data in self, retaining the allocated capacithy.
Source§

impl<C> ClockSequence for Mutex<C>

Source§

type Output = <C as ClockSequence>::Output

The type of sequence returned by this counter.
Source§

fn generate_sequence( &self, seconds: u64, subsec_nanos: u32, ) -> <Mutex<C> as ClockSequence>::Output

Get the next value in the sequence to feed into a timestamp. Read more
Source§

fn generate_timestamp_sequence( &self, seconds: u64, subsec_nanos: u32, ) -> (<Mutex<C> as ClockSequence>::Output, u64, u32)

Get the next value in the sequence, potentially also adjusting the timestamp. Read more
Source§

fn usable_bits(&self) -> usize
where <Mutex<C> as ClockSequence>::Output: Sized,

The number of usable bits from the least significant bit in the result of ClockSequence::generate_sequence or ClockSequence::generate_timestamp_sequence. Read more
1.0.0 · Source§

impl<T> Debug for Mutex<T>
where T: Debug + ?Sized,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
1.10.0 · Source§

impl<T> Default for Mutex<T>
where T: Default + ?Sized,

Source§

fn default() -> Mutex<T>

Creates a Mutex<T>, with the Default value for T.

Source§

impl<'de, T> Deserialize<'de> for Mutex<T>
where T: Deserialize<'de>,

Source§

fn deserialize<D>( deserializer: D, ) -> Result<Mutex<T>, <D as Deserializer<'de>>::Error>
where D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
1.24.0 · Source§

impl<T> From<T> for Mutex<T>

Source§

fn from(t: T) -> Mutex<T>

Creates a new mutex in an unlocked state ready for use. This is equivalent to Mutex::new.

Source§

impl<'a, W> MakeWriter<'a> for Mutex<W>
where W: Write + 'a,

Source§

type Writer = MutexGuardWriter<'a, W>

The concrete io::Write implementation returned by make_writer.
Source§

fn make_writer(&'a self) -> <Mutex<W> as MakeWriter<'a>>::Writer

Returns an instance of Writer. Read more
Source§

fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer

Returns a Writer for writing data from the span or event described by the provided Metadata. Read more
Source§

impl<T> Serialize for Mutex<T>
where T: Serialize + ?Sized,

Source§

fn serialize<S>( &self, serializer: S, ) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
where S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl SubscriberList for Mutex<HashSet<ReactiveContext>>

Source§

fn add(&self, subscriber: ReactiveContext)

Add a subscriber to the list.
Source§

fn remove(&self, subscriber: &ReactiveContext)

Remove a subscriber from the list.
Source§

fn visit(&self, f: &mut dyn FnMut(&ReactiveContext))

Visit all subscribers in the list.
Source§

impl<T> Type for Mutex<T>
where T: Type + ?Sized,

Source§

const SIGNATURE: &'static Signature = T::SIGNATURE

The signature for the implementing type, in parsed format. Read more
1.12.0 · Source§

impl<T> RefUnwindSafe for Mutex<T>
where T: ?Sized,

1.0.0 · Source§

impl<T> Send for Mutex<T>
where T: Send + ?Sized,

T must be Send for a Mutex to be Send because it is possible to acquire the owned T from the Mutex via into_inner.

1.0.0 · Source§

impl<T> Sync for Mutex<T>
where T: Send + ?Sized,

T must be Send for Mutex to be Sync. This ensures that the protected data can be accessed safely from multiple threads without causing data races or other unsafe behavior.

Mutex<T> provides mutable access to T to one thread at a time. However, it’s essential for T to be Send because it’s not safe for non-Send structures to be accessed in this manner. For instance, consider Rc, a non-atomic reference counted smart pointer, which is not Send. With Rc, we can have multiple copies pointing to the same heap allocation with a non-atomic reference count. If we were to use Mutex<Rc<_>>, it would only protect one instance of Rc from shared access, leaving other copies vulnerable to potential data races.

Also note that it is not necessary for T to be Sync as &T is only made available to one thread at a time if T is not Sync.

1.9.0 · Source§

impl<T> UnwindSafe for Mutex<T>
where T: ?Sized,

Auto Trait Implementations§

§

impl<T> !Freeze for Mutex<T>

§

impl<T> Unpin for Mutex<T>
where T: Unpin + ?Sized,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T, U> AsBindGroupShaderType<U> for T
where U: ShaderType, &'a T: for<'a> Into<U>,

Source§

fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U

Return the T ShaderType for self. When used in AsBindGroup derives, it is safe to assume that all images in self exist.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts 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>

Converts 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)

Converts &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)

Converts &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 T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert 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>

Convert 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)

Convert &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)

Convert &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
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<'de, T> DynamicDeserialize<'de> for T
where T: Type + Deserialize<'de>,

Source§

type Deserializer = PhantomData<T>

A DeserializeSeed implementation for this type.
Source§

fn deserializer_for_signature( signature: &Signature, ) -> Result<<T as DynamicDeserialize<'de>>::Deserializer, Error>

Get a deserializer compatible with this parsed signature.
Source§

impl<T> DynamicType for T
where T: Type + ?Sized,

Source§

fn signature(&self) -> Signature

The type signature for self. Read more
Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<!> for T

Source§

fn from(t: !) -> T

Converts to this type from the input type.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T> FromWorld for T
where T: Default,

Source§

fn from_world(_world: &mut World) -> T

Creates Self using default().

Source§

impl<T, W> HasTypeWitness<W> for T
where W: MakeTypeWitness<Arg = T>, T: ?Sized,

Source§

const WITNESS: W = W::MAKE

A constant of the type witness
Source§

impl<T> Identity for T
where T: ?Sized,

Source§

const TYPE_EQ: TypeEq<T, <T as Identity>::Type> = TypeEq::NEW

Proof that Self is the same type as Self::Type, provides methods for casting between Self and Self::Type.
Source§

type Type = T

The same type as Self, used to emulate type equality bounds (T == U) with associated type equality constraints (T: Identity<Type = U>).
Source§

impl<T> InitializeFromFunction<T> for T

Source§

fn initialize_from_function(f: fn() -> T) -> T

Create an instance of this type from an initialization function
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> IntoResult<T> for T

Source§

fn into_result(self) -> Result<T, RunSystemError>

Converts this type into the system output type.
Source§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<A> Is for A
where A: Any,

Source§

fn is<T>() -> bool
where T: Any,

Checks if the current type “is” another type, using a TypeId equality comparison. This is most useful in the context of generic logic. Read more
Source§

impl<'a, M> MakeWriterExt<'a> for M
where M: MakeWriter<'a>,

Source§

fn with_max_level(self, level: Level) -> WithMaxLevel<Self>
where Self: Sized,

Wraps self and returns a MakeWriter that will only write output for events at or below the provided verbosity Level. For instance, Level::TRACE is considered to be _more verbosethanLevel::INFO`. Read more
Source§

fn with_min_level(self, level: Level) -> WithMinLevel<Self>
where Self: Sized,

Wraps self and returns a MakeWriter that will only write output for events at or above the provided verbosity Level. Read more
Source§

fn with_filter<F>(self, filter: F) -> WithFilter<Self, F>
where Self: Sized, F: Fn(&Metadata<'_>) -> bool,

Wraps self with a predicate that takes a span or event’s Metadata and returns a bool. The returned MakeWriter’s MakeWriter::make_writer_for method will check the predicate to determine if a writer should be produced for a given span or event. Read more
Source§

fn and<B>(self, other: B) -> Tee<Self, B>
where Self: Sized, B: MakeWriter<'a>,

Combines self with another type implementing MakeWriter, returning a new MakeWriter that produces writers that write to both outputs. Read more
Source§

fn or_else<W, B>(self, other: B) -> OrElse<Self, B>
where Self: Sized + MakeWriter<'a, Writer = EitherWriter<W, Sink>>, B: MakeWriter<'a>, W: Write,

Combines self with another type implementing MakeWriter, returning a new MakeWriter that calls other’s make_writer if self’s make_writer returns OptionalWriter::none. Read more
Source§

impl<T> NoneValue for T
where T: Default,

Source§

type NoneType = T

Source§

fn null_value() -> T

The none-equivalent value.
Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
Source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
Source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<R, P> ReadPrimitive<R> for P
where R: Read + ReadEndian<P>, P: Default,

Source§

fn read_from_little_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_little_endian().
Source§

fn read_from_big_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_big_endian().
Source§

fn read_from_native_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_native_endian().
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Serialize for T
where T: Serialize + ?Sized,

Source§

fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>

Source§

fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>

Source§

impl<Ret> SpawnIfAsync<(), Ret> for Ret

Source§

fn spawn(self) -> Ret

Spawn the value into the dioxus runtime if it is an async block
Source§

impl<T, O> SuperFrom<T> for O
where O: From<T>,

Source§

fn super_from(input: T) -> O

Convert from a type to another type.
Source§

impl<T, O, M> SuperInto<O, M> for T
where O: SuperFrom<T, M>,

Source§

fn super_into(self) -> O

Convert from a type to another type.
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ConditionalSend for T
where T: Send,

Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> Settings for T
where T: 'static + Send + Sync,

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,