2

I am trying to create a struct which holds multiple blocks of bytes where each block of bytes is held in an individual RwLock.

This is for a voxel engine where performance is very important. Each block of bytes will need to be read/written by multiple threads. Multiple RwLocks are needed so that only a specific block will be locked leaving the rest of the blocks free to be read/written by other threads; locking the full struct would cause locking of all threads that are performing work.

Most other structs will be assigned a specific slot, the block of bytes needs to be stack allocated.

The compiler complains that it cannot copy the RwLocks as there is no Copy trait on RwLock, which I don't want to copy but instance multiple RwLocks.

mod constants {
    pub const CHUNK_BASE_SIZE: usize = 7;
    pub const CHUNK_ALLOC_COUNT: usize = 11;
}

mod example {
    use std::sync::RwLock;
    use super::constants;

    // =====================================================================
    struct BU8 {
        bytes: [[u8; constants::CHUNK_BASE_SIZE]; constants::CHUNK_BASE_SIZE],
    }

    impl BU8 {
        pub fn new() -> BU8 {
            BU8 {
                bytes: [[0; constants::CHUNK_BASE_SIZE]; constants::CHUNK_BASE_SIZE],
            }
        }
    }

    // =====================================================================
    pub struct Bytes {
        block: RwLock<BU8>,
    }

    impl Bytes {
        pub fn new() -> Bytes {
            Bytes {
                block: RwLock::new(BU8::new()),
            }
        }

        pub fn read(&self, y: usize, xz: usize) -> u8 {
            self.block.read().unwrap().bytes[y][xz]
        }

        pub fn write(&mut self, y: usize, xz: usize, value: u8) {
            self.block.write().unwrap().bytes[y][xz] = value;
        }
    }

    // =====================================================================
    pub struct Stacks {
        slots: [Bytes; constants::CHUNK_ALLOC_COUNT],
    }

    impl Stacks {
        pub fn new() -> Stacks {
            Stacks {
                // Cannot Copy, I dont want a Copy I want to instance a fixed sized array of RwLocks<BU8> blocks
                slots: [Bytes::new(); constants::CHUNK_ALLOC_COUNT],
            }
        }
    }
}

fn main() {}
error[E0277]: the trait bound `example::Bytes: std::marker::Copy` is not satisfied
  --> src/main.rs:53:24
   |
53 |                 slots: [Bytes::new(); constants::CHUNK_ALLOC_COUNT],
   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `example::Bytes`
   |
   = note: the `Copy` trait is required because the repeated element will be copied

The main thread spawns a child thread that will hold all game/core data on and will be accessible through each worker thread the child thread will spawn.

Each worker thread will be assigned workloads to read/write data on an assigned Block on the Stacks, but I don't know how to instance multiple RwLocks this way or any other way without using the collections.

I tried adding #[derive(Copy, Clone)] for each struct but the Bytes struct error is:

error[E0204]: the trait `Copy` may not be implemented for this type
  --> src/main.rs:24:18
   |
24 |         #[derive(Copy, Clone)]
   |                  ^^^^
25 |         pub struct Bytes {
26 |             block: RwLock<BU8>,
   |             ------------------ this field does not implement `Copy`

I'm guessing RwLock size cannot known at compile time so would a vector of pointers to each block of bytes work? If so how do I implement that safely?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • Can you explain what you mean by "I don't want to copy but instance multiple"? I think some translation error is happening here. – Shepmaster Feb 26 '18 at 18:52
  • Rwlock doesn't implement Copy/Clone traits so i was guessing that I would need to call RwLock::new to create multiple instances however if RwLock size cannot be known at compile time it would explain why Copy trait was never implemented into RwLock, Wont know for sure unless I look at its source code but my rust is lacking to look that far under the hood. after a little more research Boxing the RwLock (from sheps post) with a fixed sized Array I found that the box approach would create the array on the stack and then the box would then move it onto the heap. – HappyGoKaboom Feb 26 '18 at 21:30
  • Oh by copy from rust docs it copies the bits of a data to form the new instance(copy) of it rather than simply creating a new instance.... (im coming from a web dev background first system lang i`ve so its all new to me) – HappyGoKaboom Feb 26 '18 at 21:34
  • after looking at how my data structs would need to work, a read and write should never occur at the same time regardless of concurrency/parreleism so direct memory manipulation in unsafe code should work with no problems, however if i mess it up..leaks...no thread safety..fubar could be the result.. me gotta learn more – HappyGoKaboom Feb 26 '18 at 21:37
  • 2 usefull insights into Box and Vec collections data. For others who run into the same issues, Box and Vec elements are on the heap, for Box any stack allocation type gets moved onto the heap https://www.reddit.com/r/rust/comments/6mrn0i/rust_box_memory_allocation/ – HappyGoKaboom Feb 26 '18 at 22:33
  • Note: For the main thread stack allocation is limited, spawn a child thread with a specific stack size if you need more, this post shows the issue of stack allocations via collections(Box) gets moved onto the heap but initially uses stack, and the main threads stack is limited. https://www.reddit.com/r/rust/comments/3vngdd/why_is_box_not_allocating_memory_on_the_heap/ – HappyGoKaboom Feb 26 '18 at 22:33

0 Answers0