Skip to content

Commit 7d6227f

Browse files
committed
add get_or_insert and Send
1 parent 31708ec commit 7d6227f

File tree

6 files changed

+257
-17
lines changed

6 files changed

+257
-17
lines changed

Diff for: examples/bench_lru.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,5 @@ fn do_bench(num: usize) {
8181
}
8282

8383
fn main() {
84-
do_bench(1e4 as usize);
84+
do_bench(1e6 as usize);
8585
}

Diff for: src/cache/arc.rs

+70-15
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,48 @@ impl<K: Hash + Eq, V, S: BuildHasher> ArcCache<K, V, S> {
441441
}
442442
}
443443

444+
445+
pub fn get_or_insert<F>(&mut self, k: K, f: F) -> &V
446+
where
447+
F: FnOnce() -> V, {
448+
&*self.get_or_insert_mut(k, f)
449+
}
450+
451+
pub fn get_or_insert_mut<F>(&mut self, k: K, f: F) -> &mut V
452+
where
453+
F: FnOnce() -> V, {
454+
455+
if let Some((key, val)) = self.main_lru.remove(&k) {
456+
self.main_lfu.insert(key, val);
457+
return self.main_lfu.get_mut_key_value(&k).map(|(_, v)| v).unwrap();
458+
}
459+
460+
if let Some((key, val)) = self.ghost_lfu.remove(&k) {
461+
self.main_lfu.full_increase();
462+
self.main_lru.full_decrease();
463+
self.main_lfu.insert(key, val);
464+
return self.main_lfu.get_mut_key_value(&k).map(|(_, v)| v).unwrap();
465+
}
466+
467+
if let Some((key, val)) = self.ghost_lru.remove(&k) {
468+
self.main_lru.full_increase();
469+
self.main_lfu.full_decrease();
470+
self.main_lru.insert(key, val);
471+
return self.main_lru.get_mut_key_value(&k).map(|(_, v)| v).unwrap();
472+
}
473+
474+
if self.main_lfu.contains_key(&k) {
475+
return self.main_lfu.get_mut_key_value(&k).map(|(_, v)| v).unwrap();
476+
}
477+
478+
if self.main_lru.is_full() {
479+
let (pk, pv) = self.main_lru.pop_last().unwrap();
480+
self.ghost_lru.insert(pk, pv);
481+
}
482+
self.get_or_insert_mut(k, f)
483+
}
484+
485+
444486
/// 移除元素
445487
///
446488
/// ```
@@ -490,6 +532,17 @@ impl<K: Hash + Eq, V, S: BuildHasher> ArcCache<K, V, S> {
490532
}
491533
}
492534

535+
536+
impl<K: Hash + Eq, V: Default, S: BuildHasher> ArcCache<K, V, S> {
537+
pub fn get_or_insert_default(&mut self, k: K) -> &V {
538+
&*self.get_or_insert_mut(k, || V::default())
539+
}
540+
541+
pub fn get_or_insert_default_mut(&mut self, k: K) -> &mut V {
542+
self.get_or_insert_mut(k, || V::default())
543+
}
544+
}
545+
493546
impl<K: Clone + Hash + Eq, V: Clone, S: Clone + BuildHasher> Clone for ArcCache<K, V, S> {
494547
fn clone(&self) -> Self {
495548
ArcCache {
@@ -739,6 +792,9 @@ where
739792
}
740793
}
741794

795+
unsafe impl<K: Send, V: Send, S: Send> Send for ArcCache<K, V, S> {}
796+
unsafe impl<K: Sync, V: Sync, S: Sync> Sync for ArcCache<K, V, S> {}
797+
742798
#[cfg(test)]
743799
mod tests {
744800
use std::collections::hash_map::RandomState;
@@ -1111,19 +1167,18 @@ mod tests {
11111167
assert_eq!(a[&3], "three");
11121168
}
11131169

1114-
// #[test]
1115-
// fn test_drain() {
1116-
// let mut a = ArcCache::new(3);
1117-
// a.insert(1, 1);
1118-
// a.insert(2, 2);
1119-
// a.insert(3, 3);
1120-
1121-
// assert_eq!(a.len(), 3);
1122-
// {
1123-
// let mut drain = a.drain();
1124-
// assert_eq!(drain.next().unwrap(), (1, 1));
1125-
// assert_eq!(drain.next().unwrap(), (2, 2));
1126-
// }
1127-
// assert_eq!(a.len(), 0);
1128-
// }
1170+
1171+
#[test]
1172+
fn test_send() {
1173+
use std::thread;
1174+
1175+
let mut cache = ArcCache::new(4);
1176+
cache.insert(1, "a");
1177+
1178+
let handle = thread::spawn(move || {
1179+
assert_eq!(cache.get(&1), Some(&"a"));
1180+
});
1181+
1182+
assert!(handle.join().is_ok());
1183+
}
11291184
}

Diff for: src/cache/lfu.rs

+59
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,37 @@ impl<K: Hash + Eq, V, S: BuildHasher> LfuCache<K, V, S> {
706706
}
707707
}
708708

709+
710+
pub fn get_or_insert<F>(&mut self, k: K, f: F) -> &V
711+
where
712+
F: FnOnce() -> V, {
713+
&*self.get_or_insert_mut(k, f)
714+
}
715+
716+
717+
pub fn get_or_insert_mut<F>(&mut self, k: K, f: F) -> &mut V
718+
where
719+
F: FnOnce() -> V, {
720+
if let Some(l) = self.map.get(KeyWrapper::from_ref(&k)) {
721+
let node = l.as_ptr();
722+
self.detach(node);
723+
self.attach(node);
724+
unsafe { &mut *(*node).val.as_mut_ptr() }
725+
} else {
726+
let v = f();
727+
728+
let (_, node) = self.replace_or_create_node(k, v);
729+
let node_ptr: *mut LfuEntry<K, V> = node.as_ptr();
730+
731+
self.attach(node_ptr);
732+
733+
let keyref = unsafe { (*node_ptr).key.as_ptr() };
734+
self.map.insert(KeyRef { k: keyref }, node);
735+
unsafe { &mut *(*node_ptr).val.as_mut_ptr() }
736+
}
737+
}
738+
739+
709740
/// 移除元素
710741
///
711742
/// ```
@@ -813,6 +844,17 @@ impl<K: Hash + Eq, V, S: BuildHasher> LfuCache<K, V, S> {
813844
}
814845
}
815846

847+
848+
impl<K: Hash + Eq, V: Default, S: BuildHasher> LfuCache<K, V, S> {
849+
pub fn get_or_insert_default(&mut self, k: K) -> &V {
850+
&*self.get_or_insert_mut(k, || V::default())
851+
}
852+
853+
pub fn get_or_insert_default_mut(&mut self, k: K) -> &mut V {
854+
self.get_or_insert_mut(k, || V::default())
855+
}
856+
}
857+
816858
impl<K: Clone + Hash + Eq, V: Clone, S: Clone + BuildHasher> Clone for LfuCache<K, V, S> {
817859
fn clone(&self) -> Self {
818860
let mut new_lru = LfuCache::with_hasher(self.cap, self.map.hasher().clone());
@@ -1204,6 +1246,9 @@ where
12041246
}
12051247
}
12061248

1249+
unsafe impl<K: Send, V: Send, S: Send> Send for LfuCache<K, V, S> {}
1250+
unsafe impl<K: Sync, V: Sync, S: Sync> Sync for LfuCache<K, V, S> {}
1251+
12071252
#[cfg(test)]
12081253
mod tests {
12091254
use std::collections::hash_map::RandomState;
@@ -1591,4 +1636,18 @@ mod tests {
15911636
}
15921637
assert_eq!(a.len(), 0);
15931638
}
1639+
1640+
#[test]
1641+
fn test_send() {
1642+
use std::thread;
1643+
1644+
let mut cache = LfuCache::new(4);
1645+
cache.insert(1, "a");
1646+
1647+
let handle = thread::spawn(move || {
1648+
assert_eq!(cache.get(&1), Some(&"a"));
1649+
});
1650+
1651+
assert!(handle.join().is_ok());
1652+
}
15941653
}

Diff for: src/cache/lru.rs

+64
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ impl<K, V, S> LruCache<K, V, S> {
142142
self.map.len()
143143
}
144144

145+
pub fn is_full(&self) -> bool {
146+
self.map.len() == self.cap
147+
}
148+
145149
pub fn is_empty(&self) -> bool {
146150
self.map.len() == 0
147151
}
@@ -537,6 +541,36 @@ impl<K: Hash + Eq, V, S: BuildHasher> LruCache<K, V, S> {
537541
}
538542
}
539543

544+
545+
pub fn get_or_insert<F>(&mut self, k: K, f: F) -> &V
546+
where
547+
F: FnOnce() -> V, {
548+
&*self.get_or_insert_mut(k, f)
549+
}
550+
551+
552+
pub fn get_or_insert_mut<F>(&mut self, k: K, f: F) -> &mut V
553+
where
554+
F: FnOnce() -> V, {
555+
if let Some(l) = self.map.get(KeyWrapper::from_ref(&k)) {
556+
let node = l.as_ptr();
557+
self.detach(node);
558+
self.attach(node);
559+
unsafe { &mut *(*node).val.as_mut_ptr() }
560+
} else {
561+
let v = f();
562+
563+
let (_, node) = self.replace_or_create_node(k, v);
564+
let node_ptr: *mut LruEntry<K, V> = node.as_ptr();
565+
566+
self.attach(node_ptr);
567+
568+
let keyref = unsafe { (*node_ptr).key.as_ptr() };
569+
self.map.insert(KeyRef { k: keyref }, node);
570+
unsafe { &mut *(*node_ptr).val.as_mut_ptr() }
571+
}
572+
}
573+
540574
/// 移除元素
541575
///
542576
/// ```
@@ -623,6 +657,17 @@ impl<K: Hash + Eq, V, S: BuildHasher> LruCache<K, V, S> {
623657
}
624658
}
625659

660+
661+
impl<K: Hash + Eq, V: Default, S: BuildHasher> LruCache<K, V, S> {
662+
pub fn get_or_insert_default(&mut self, k: K) -> &V {
663+
&*self.get_or_insert_mut(k, || V::default())
664+
}
665+
666+
pub fn get_or_insert_default_mut(&mut self, k: K) -> &mut V {
667+
self.get_or_insert_mut(k, || V::default())
668+
}
669+
}
670+
626671
impl<K: Clone + Hash + Eq, V: Clone, S: Clone + BuildHasher> Clone for LruCache<K, V, S> {
627672
fn clone(&self) -> Self {
628673
let mut new_lru = LruCache::with_hasher(self.cap, self.map.hasher().clone());
@@ -928,6 +973,10 @@ where
928973
}
929974
}
930975

976+
unsafe impl<K: Send, V: Send, S: Send> Send for LruCache<K, V, S> {}
977+
unsafe impl<K: Sync, V: Sync, S: Sync> Sync for LruCache<K, V, S> {}
978+
979+
931980
#[cfg(test)]
932981
mod tests {
933982
use std::collections::hash_map::RandomState;
@@ -1306,4 +1355,19 @@ mod tests {
13061355
}
13071356
assert_eq!(a.len(), 0);
13081357
}
1358+
1359+
1360+
#[test]
1361+
fn test_send() {
1362+
use std::thread;
1363+
1364+
let mut cache = LruCache::new(4);
1365+
cache.insert(1, "a");
1366+
1367+
let handle = thread::spawn(move || {
1368+
assert_eq!(cache.get(&1), Some(&"a"));
1369+
});
1370+
1371+
assert!(handle.join().is_ok());
1372+
}
13091373
}

Diff for: src/cache/lruk.rs

+61
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,35 @@ impl<K: Hash + Eq, V, S: BuildHasher> LruKCache<K, V, S> {
578578
}
579579
}
580580

581+
pub fn get_or_insert<F>(&mut self, k: K, f: F) -> &V
582+
where
583+
F: FnOnce() -> V, {
584+
&*self.get_or_insert_mut(k, f)
585+
}
586+
587+
588+
pub fn get_or_insert_mut<F>(&mut self, k: K, f: F) -> &mut V
589+
where
590+
F: FnOnce() -> V, {
591+
if let Some(l) = self.map.get(KeyWrapper::from_ref(&k)) {
592+
let node = l.as_ptr();
593+
self.detach(node);
594+
self.attach(node);
595+
unsafe { &mut *(*node).val.as_mut_ptr() }
596+
} else {
597+
let v = f();
598+
599+
let (_, node) = self.replace_or_create_node(k, v);
600+
let node_ptr: *mut LruKEntry<K, V> = node.as_ptr();
601+
602+
self.attach(node_ptr);
603+
604+
let keyref = unsafe { (*node_ptr).key.as_ptr() };
605+
self.map.insert(KeyRef { k: keyref }, node);
606+
unsafe { &mut *(*node_ptr).val.as_mut_ptr() }
607+
}
608+
}
609+
581610
/// 移除元素
582611
///
583612
/// ```
@@ -672,6 +701,17 @@ impl<K: Hash + Eq, V, S: BuildHasher> LruKCache<K, V, S> {
672701
}
673702
}
674703

704+
705+
impl<K: Hash + Eq, V: Default, S: BuildHasher> LruKCache<K, V, S> {
706+
pub fn get_or_insert_default(&mut self, k: K) -> &V {
707+
&*self.get_or_insert_mut(k, || V::default())
708+
}
709+
710+
pub fn get_or_insert_default_mut(&mut self, k: K) -> &mut V {
711+
self.get_or_insert_mut(k, || V::default())
712+
}
713+
}
714+
675715
impl<K: Clone + Hash + Eq, V: Clone, S: Clone + BuildHasher> Clone for LruKCache<K, V, S> {
676716
fn clone(&self) -> Self {
677717

@@ -998,6 +1038,12 @@ where
9981038
}
9991039
}
10001040

1041+
1042+
1043+
unsafe impl<K: Send, V: Send, S: Send> Send for LruKCache<K, V, S> {}
1044+
unsafe impl<K: Sync, V: Sync, S: Sync> Sync for LruKCache<K, V, S> {}
1045+
1046+
10011047
#[cfg(test)]
10021048
mod tests {
10031049
use std::collections::hash_map::RandomState;
@@ -1376,4 +1422,19 @@ mod tests {
13761422
}
13771423
assert_eq!(a.len(), 0);
13781424
}
1425+
1426+
1427+
#[test]
1428+
fn test_send() {
1429+
use std::thread;
1430+
1431+
let mut cache = LruKCache::new(4);
1432+
cache.insert(1, "a");
1433+
1434+
let handle = thread::spawn(move || {
1435+
assert_eq!(cache.get(&1), Some(&"a"));
1436+
});
1437+
1438+
assert!(handle.join().is_ok());
1439+
}
13791440
}

Diff for: src/cache/slab.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,8 @@ impl<T: Default> Extend<T> for Slab<T> {
698698
}
699699
}
700700

701-
701+
unsafe impl<T: Send + Default> Send for Slab<T> {}
702+
unsafe impl<T: Sync + Default> Sync for Slab<T> {}
702703

703704
#[cfg(test)]
704705
mod tests {

0 commit comments

Comments
 (0)