I have a design question: I have a struct that has a heavy constructor (i.e. slow file read operations). However the files to read depends on the operations the client will do with the struct. Right now I read everything on the constructor, to be conservative:
What pattern should I use to make a light constructor and lazily initialize struct fields on demand? I should point out that getter methods should not take &mut self in this case. Are there problems with multi-threading in that case?
If construction requires mutation and you can't use &mut self as a receiver, then your only choice is interior mutability. There are three primary ways of doing interior mutability with std: std::cell::Cell, std::cell::RefCell and std::sync::Mutex. Cell only works for types that satisfy Copy (which would work with your example code, since both of Foo's fields are Copy). RefCell works for most any type, but it will prevent you (or anyone else using Foo) from using Arc<Foo> usefully across multiple threads. If you want to enable that use case, then you'll need to do synchronization. The simplest way to do that is to store your state in a Mutex, which provides the same kind of interior mutability that RefCell does, except it does it in a way that is thread safe. Given that you want to cache something and then probably read from it many times, you'll probably want to use std::sync::RwLock instead (which allows many readers simultaneously, but only one writer).
Wow, quite a lot of options, thanks! Any documentation pointers on that? Or example projects? I found the rust book to be somehow obscure on the topic.
If you find it confusing, please note down you confusion for @steveklabnik, who can then act on it. You would really help a lot. (Or even: once you understood the subject, rewrite parts)
Precisely that section. I think it is too small. @BurntSushi answer is already better than the whole section (for my specific problem at least). Maybe the section requires the same refactor has been done for error handling, with basics, std types involved and some case study. That's only my opinion, of course.
@mbrt I'm not aware of anything specific targeting your use case. For now, I'd recommend trying to understand to interior mutability andSend/Sync, and then attacking your problem. I'm short on time, so the best I can do is fire some links at you:
Thanks for sharing. I don't think my problem is very uncommon, as it is only an application of interior mutability. Don't you think it's better to explain better in the docs why someone would ever choose to use it and what are the interactions with Send/Sync and all the stuff you mentioned?
I am in this situation and want to cache a value, whilst still being thread-safe. I feel like a RwLock is overkill, because after the initial write, the data no longer needs interior mutability, and getting a read-lock has overhead. Does anyone know of any crates that do a single write then read-only?