I need a struct containing several fields that should be usable in a concurrent context.
struct Foo {
number: u32,
collection: Vec<u32>,
}
In C I would add a Mutex to the struct and (un)lock that, but doing this in rust, using a Mutex<()> is not possible, as the struct is located somewhere inside an Arc. This means I need the Mutex around the fields if I want to mutate them.
However this leads to problems if I want to extract functionality into private methods, as Mutex is not reentrant.
[Edit]
If the fields in question are needed in both the main method and the helper method, locking multiple times is not the solution, as I would like the whole block to be treated as one unit, otherwise it would be possible to change something inbetween from another thread.
[/Edit]
In the simeple case like above, the solution would probably be to not make it concurrent at all and let the caller deal with it, i.e. use Mutex<Foo> and deal with the locking every time it is used.
However, in some situations, a CondVar is needed, to wait on the collection being filled or emptied, in which case I need a MutexGuard to wait on.
I guess I could move the CondVar to the outside as well, but then I would need to be concerned with the inner workings of my struct on the outside, which I don't like at all.
I don't know if I'm going completely into the wrong direction here, but I couldn't find anything on this by searching the web. Everything only talks about locking simple datatypes.
The approaches mentioned above:
struct Foo {
lock: Mutex<()>,
number: u32,
collection: Vec<u32>,
}
struct Foo {
number: Mutex<u32>,
collection: Mutex<Vec<u32>>,
}
impl Foo {
pub fn add_if_bigger(&self, v: u32) {
let collection = self.collection.lock().unwrap();
if self.is_bigger(v) {
collection.push(v);
}
}
fn is_bigger(&self) -> bool {
let collection = self.collection.lock().unwrap();
// already locked by this thread --^
// ...
}
}