y
02/12/2024, 9:04 AMobject FileCache {
private val contentOf: MutableMap<Path, String>
// ...
}
which is shared and has a function to read file contents, which given a Path
would serve the data from contentOf
if it's already there, or otherwise open the file, read the content to the map, then serve that. some questions about the design:
1. is there a problem with serving `String`s? should I be giving out StringReader
or something like that? (if so, why?)
2. am I correct that it's enough to lock the object (synchronized(this)
) only when mutating contentOf
(so only when initializing it with file content if it's not already in the map), and that I can do contentOf.get(...)
without locks?
3. any glaring problems with this design? it seems pretty naive. I will also note that I don't expect files to be very large here, nor do I expect the map to have a very large number of entriesSam
02/12/2024, 9:14 AMString
is the right thing to do. A Reader
just provides a way to read from the file, so caching the Reader
wouldn't help to reduce the number of reads.
2. No, you would still need to lock on all accesses. With a regular mutable map, the data structure is not in a consistent state during mutations, and you might get incorrect behavior or exceptions if you try to call get
while a write is in progress.
If you're on Java, there are some built-in solutions for problems like this, e.g. Collections.synchronizedMap
which locks the map during all accesses, and ConcurrentMap
which locks parts of the map while still allowing some concurrent access. With both you can also use methods like Map.computeIfAbsent
, which is a good way to do a "get or put" without introducing races.Joffrey
02/12/2024, 9:14 AMephemient
02/12/2024, 9:29 AMCLOVIS
02/12/2024, 1:57 PM