HashMap
のラップをデフォルト値で実装しました。安全かどうかを知りたいと思います。HashMapの安全なラップをデフォルト値で書き込む方法
get
が呼び出されると、内部マップのサイズが変更され、以前の値参照(get
で取得)が無効なアドレスを指している可能性があります。私は、「コンピュータサイエンスのすべての問題は別のレベルの間接指向で解決できる」という考え方(Butler Lampson)を使ってこの問題を解決しようとしました。このトリックがこのコードを安全にするかどうかを知りたいと思います。
use std::cell::UnsafeCell;
use std::collections::HashMap;
use std::hash::Hash;
pub struct DefaultHashMap<I: Hash + Eq, T: Clone> {
default: T,
map: UnsafeCell<HashMap<I, Box<T>>>,
}
impl<I: Hash + Eq, T: Clone> DefaultHashMap<I, T> {
pub fn new(default: T) -> Self {
DefaultHashMap {
default: default,
map: UnsafeCell::new(HashMap::new()),
}
}
pub fn get_mut(&mut self, v: I) -> &mut T {
let m = unsafe { &mut *self.map.get() };
m.entry(v).or_insert_with(|| Box::new(self.default.clone()))
}
pub fn get(&self, v: I) -> &T {
let m = unsafe { &mut *self.map.get() };
m.entry(v).or_insert_with(|| Box::new(self.default.clone()))
}
}
#[test]
fn test() {
let mut m = DefaultHashMap::new(10usize);
*m.get_mut(4) = 40;
let a = m.get(4);
for i in 1..1024 {
m.get(i);
}
assert_eq!(a, m.get(4));
assert_eq!(40, *m.get(4));
}