#Problem with global Vector using trait type

37 messages · Page 1 of 1 (latest)

muted yew
#

Hi!
I come from C++ and C, usually I undersand locking but apparently in rust i ma missing some knowledge?
I am trying to hold a vector of objects in a global variable list so that several threads can work on it in parallel/interleaved manner.
In this case i want a thread to handle all the physics updates.

I don't understand how to create that variable. In C++/C I'd lock the lock manually and all is good, but here the lock is part of the declaration and I am having torouble making a trait be the type of the vector?

use std::{
    sync::{LazyLock, Mutex},
    thread,
    time::Duration,
};

use object::{Object, PhysicsUpdated};

pub mod cube;
pub mod object;

static OBJECT_MANAGER: LazyLock<Mutex<ObjectManager>> =
    LazyLock::new(|| Mutex::new(ObjectManager::new()));

struct ObjectManager {
    objects: Vec<Box<dyn PhysicsUpdated>>,

    physics_thread_handle: thread::JoinHandle<()>,
}

impl ObjectManager {
    fn new() -> ObjectManager {
        // create a thread that automatically updates the inside objects

        let handle = thread::spawn(|| {
            {
                let mut obj_m = OBJECT_MANAGER.lock().unwrap();

                obj_m.objects.iter_mut().for_each(|object| {
                    object.physics_update(1000.0);
                });
            }

            thread::sleep(Duration::from_secs(1));
        });

        ObjectManager {
            objects: Vec::new(),
            physics_thread_handle: handle,
        }
    }

}



Reading and googling the error message, I know that theere seems to be the issue of my trait not having a fixed size for the object that it implements, fair enough but i was hoping that Box<PhysicsUpdated> could fix that as a 'fat pointer' ?

#

Problem with global Vector using trait type

naive ruin
#

can you post the full error message

muted yew
#

yep, in stages

#

its bigger than the max char limit

#
error[E0277]: `(dyn PhysicsUpdated + 'static)` cannot be sent between threads safely
   --> src/object/mod.rs:12:24
    |
12  | static OBJECT_MANAGER: LazyLock<Mutex<ObjectManager>> =
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn PhysicsUpdated + 'static)` cannot be sent between threads safely
    |
    = help: the trait `Send` is not implemented for `(dyn PhysicsUpdated + 'static)`
    = note: required for `Unique<(dyn PhysicsUpdated + 'static)>` to implement `Send`
note: required because it appears within the type `Box<(dyn PhysicsUpdated + 'static)>`
   --> /home/zweieuro/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:231:12
    |
231 | pub struct Box<
#
    |            ^^^
note: required because it appears within the type `PhantomData<Box<(dyn PhysicsUpdated + 'static)>>`
   --> /home/zweieuro/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/marker.rs:757:12
    |
757 | pub struct PhantomData<T: ?Sized>;
    |            ^^^^^^^^^^^
note: required because it appears within the type `alloc::raw_vec::RawVec<Box<(dyn PhysicsUpdated + 'static)>>`
   --> /home/zweieuro/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:76:19
    |
76  | pub(crate) struct RawVec<T, A: Allocator = Global> {
    |                   ^^^^^^
note: required because it appears within the type `Vec<Box<(dyn PhysicsUpdated + 'static)>>`
   --> /home/zweieuro/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:397:12
    |
397 | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
    |            ^^^
note: required because it appears within the type `ObjectManager`
   --> src/object/mod.rs:15:8
    |
15  | struct ObjectManager {
    |        ^^^^^^^^^^^^^
    = note: required for `Mutex<ObjectManager>` to implement `Sync`
    = note: 1 redundant requirement hidden
    = note: required for `LazyLock<Mutex<ObjectManager>>` to implement `Sync`
    = note: shared static variables must have a type that implements `Sync`


naive ruin
#

oh that

muted yew
#

I know this ties together with my in-clarity of how to use global states in rust. If i want to have objects worked on by 2 things i need it somewhat global

naive ruin
#

can you require PhysicsUpdated to be Send + Sync i.e. trait PhysicsUpdated: Send + Sync

#

or if you don't want that, do dyn PhysicsUpdated + Send + Sync + 'static

muted yew
#

Can i derive them somehow or do i need to implement em myself ?

naive ruin
#

Send and Sync are auto traits, meaning they are automatically implemented if all the fields also implements the respective traits

muted yew
#
pub trait PhysicsUpdated {
    fn physics_update(&mut self, delta_time_s: f32);
}

impl<T> PhysicsUpdated for Object<T>
where
    T: Shape,
{
    fn physics_update(&mut self, delta_time: f32) {
        self.world_space_position += self.speed * delta_time;
    }
}

this is what physicsupdated looks like rn, where should i add that ?

naive ruin
#

have you read chapter 16 of the rust book by any chance

#

or the rust book for that matter

muted yew
#

I have, its just .... a lot

naive ruin
muted yew
#

That actually fixed it, wow

naive ruin
#

probably

#

idk

muted yew
#

yeah that fixes it

#

i am guessing that it should also work but i am unsure yet

naive ruin
#

yea for reading the error messages, check the help: notes

muted yew
#

So the problem was that rust didn't know how to sync my traits ?

naive ruin
#

no.

#

it's that you could implement PhysicsUpdated for a type that isnt Send or Sync, however you are using dyn PhysicsUpdated that requires it , so rust stops you from shooting ur foot

#

are you familiar with Send and Sync?

muted yew
#

ah, okay that makes a lot of sense

muted yew
naive ruin
#

it's just marker traits to tell you that for Send, it allows you to send a value to another thread, and for Sync, it allows you to share the value to multiple threads

muted yew
#

okay, i gotta read chapter 16 again

#

so it doesn't actually do anything specifically, i just explicitly tell it with that marker that "yeah you CAN sync this"?

naive ruin
#

yeah those traits literally have no methods

muted yew
#

As a sidenote, the "Box" is needed for me ,right ?

muted yew
naive ruin