1

Here is the simplified code I am trying to write:

use parking_lot::RwLock;

let buffers: Box<[RwLock<MyBuffer>]> = Box::new([ ... ]);
let (sender, receiver) = std::sync::mpsc::channel();

thread::spawn(move || {
    let guard = buffers[ ... ].write().unwrap();
    expensive_computation(&mut *guard);
    sender.send(guard.downgrade()).unwrap();
});

for message in receiver.iter() {
    // Handle the message
}

However, RwLockReadGuard is not Send, so this code does not compile.

How should I solve the problem of sending a RwLockReadGuard across the thread boundary?

Coder-256
  • 5,212
  • 2
  • 23
  • 51
  • 1
    From a quick look, I'd guess you should wrap the `RwLock` in an `Arc`, and send a reference to the lock rather then the lock guard. (I.e. use `Arc>` as the item type in your slice.) – Sven Marnach Nov 30 '19 at 22:22
  • @SvenMarnach That's a good idea, but the problem is that now writers can race for the lock while it's sitting in the mpsc queue. – Coder-256 Dec 01 '19 at 21:26
  • The race should be prevented by `RwLock`. Or why do you think that `Box<...>` is better thant `Arc<...>`. @Sven Marnach: I suppose you mean `Arc<[RwLock]>`? – CoronA Dec 02 '19 at 05:30
  • @CoronA No, I meant what I said. The thread tries to return a reference to a specific item in the slice, so we need an `Arc` for each item. – Sven Marnach Dec 02 '19 at 09:35
  • @Coder-256 You'll probably have to come up with a separate mechanism to prevent that, like moving the items that have already been processed out of the slice. I don't have enough context to make a good suggestion here. – Sven Marnach Dec 02 '19 at 09:37
  • First, thank you both for helping. I am trying to implement triple buffering. The goal is to have one thread that repeatedly writes data into one of three buffers, then passes a read lock back to the main thread, and alternates writing to the two remaining buffers so that the main thread can easily access the most recently updated buffer. I created a workaround by sending the `RwLock` for the most recent buffer then leaving it up to the main thread to actually lock it; however, I want to avoid unlocking/relocking and manually updating. – Coder-256 Dec 02 '19 at 11:15
  • Also I should mention that in my particular case I am using `Box::leak` to get a `&'static [RwLock]` reference since I use the buffers during the whole program and it's more efficient this way, but otherwise you would be right, I would need an `Arc` in order to access the `RwLock` from 2 threads at a time. I write a reference to the freshest `RwLock` into a mutex (but I will probably switch to an atomic pointer for performance since I'm using the static lifetime anyway). – Coder-256 Dec 02 '19 at 17:38

0 Answers0