I'm currently implementing a multi client Key-Value Store (like redis or memcached) and it allows the clients to gain exclusive access to the store.
Now I have the problem that when getting values from the shared store, it can either be protected by a RwLockWriteGoard (when exclusive access is active) or a RwLockReadGuard when not.
I did not find a ways of saving the store in a variable to perform operations later on it in a way that doesn't care about whether it's protected by a read or write guard.
Here is the simplified solution I use at the moment.
// Assume Store is like this
let store = Arc::new(RwLock::new(HashMap::new()));
// --snip--
let mut exclusive_access: Option<RwLockWriteGuard<HashMap<String, String>>> = None;
while !is_finished {
// --snip--
let response = match parse_command(&command) {
Command::Get(key) => {
let read_result = match exclusive_access {
Some(exclusive_store) => match exclusive_store.get(&key) {
Some(x) => Some(x.clone()),
None => None,
},
None => match store.read().unwrap().get(&key) {
Some(x) => Some(x.clone()),
None => None,
},
};
// simplified
read_result
}
// --snip--
};
if gain_exclusive_access {
exclusive_access = Some(store.write().unwrap());
} else {
exclusive_access = None;
}
}
If possible, I'd like to write the Command::Get(key) arm as something like this:
let store = match exclusive_access {
Some(store) => store,
None => store.read().unwrap()
};
store.get(&key)
But this doesn't work, because the two arms of that match return different Types (RwLockWriteGuard and RwLockReadGuard).
Is there a way around this, which I'm just too blind to see?
Use enum as tagged union.