1
1
use crate :: fx:: { FxHashMap , FxHasher } ;
2
- use crate :: sync:: { Lock , LockGuard } ;
2
+ use crate :: sync:: { active , Lock , LockGuard } ;
3
3
use std:: borrow:: Borrow ;
4
4
use std:: collections:: hash_map:: RawEntryMut ;
5
5
use std:: hash:: { Hash , Hasher } ;
@@ -23,6 +23,7 @@ pub const SHARDS: usize = 1 << SHARD_BITS;
23
23
/// An array of cache-line aligned inner locked structures with convenience methods.
24
24
pub struct Sharded < T > {
25
25
shards : [ CacheAligned < Lock < T > > ; SHARDS ] ,
26
+ single_thread : bool ,
26
27
}
27
28
28
29
impl < T : Default > Default for Sharded < T > {
@@ -35,31 +36,41 @@ impl<T: Default> Default for Sharded<T> {
35
36
impl < T > Sharded < T > {
36
37
#[ inline]
37
38
pub fn new ( mut value : impl FnMut ( ) -> T ) -> Self {
38
- Sharded { shards : [ ( ) ; SHARDS ] . map ( |( ) | CacheAligned ( Lock :: new ( value ( ) ) ) ) }
39
+ Sharded {
40
+ shards : [ ( ) ; SHARDS ] . map ( |( ) | CacheAligned ( Lock :: new ( value ( ) ) ) ) ,
41
+ single_thread : !active ( ) ,
42
+ }
39
43
}
40
44
41
45
/// The shard is selected by hashing `val` with `FxHasher`.
42
46
#[ inline]
43
47
pub fn get_shard_by_value < K : Hash + ?Sized > ( & self , val : & K ) -> & Lock < T > {
44
- if SHARDS == 1 { & self . shards [ 0 ] . 0 } else { self . get_shard_by_hash ( make_hash ( val) ) }
48
+ if self . single_thread { & self . shards [ 0 ] . 0 } else { self . get_shard_by_hash ( make_hash ( val) ) }
45
49
}
46
50
47
51
#[ inline]
48
52
pub fn get_shard_by_hash ( & self , hash : u64 ) -> & Lock < T > {
49
- & self . shards [ get_shard_index_by_hash ( hash) ] . 0
50
- }
51
-
52
- #[ inline]
53
- pub fn get_shard_by_index ( & self , i : usize ) -> & Lock < T > {
54
- & self . shards [ i] . 0
53
+ if self . single_thread {
54
+ & self . shards [ 0 ] . 0
55
+ } else {
56
+ & self . shards [ get_shard_index_by_hash ( hash) ] . 0
57
+ }
55
58
}
56
59
57
60
pub fn lock_shards ( & self ) -> Vec < LockGuard < ' _ , T > > {
58
- ( 0 ..SHARDS ) . map ( |i| self . shards [ i] . 0 . lock ( ) ) . collect ( )
61
+ if self . single_thread {
62
+ vec ! [ self . shards[ 0 ] . 0 . lock( ) ]
63
+ } else {
64
+ ( 0 ..SHARDS ) . map ( |i| self . shards [ i] . 0 . lock ( ) ) . collect ( )
65
+ }
59
66
}
60
67
61
68
pub fn try_lock_shards ( & self ) -> Option < Vec < LockGuard < ' _ , T > > > {
62
- ( 0 ..SHARDS ) . map ( |i| self . shards [ i] . 0 . try_lock ( ) ) . collect ( )
69
+ if self . single_thread {
70
+ Some ( vec ! [ self . shards[ 0 ] . 0 . try_lock( ) ?] )
71
+ } else {
72
+ ( 0 ..SHARDS ) . map ( |i| self . shards [ i] . 0 . try_lock ( ) ) . collect ( )
73
+ }
63
74
}
64
75
}
65
76
@@ -141,7 +152,7 @@ pub fn make_hash<K: Hash + ?Sized>(val: &K) -> u64 {
141
152
/// consistently for each `Sharded` instance.
142
153
#[ inline]
143
154
#[ allow( clippy:: modulo_one) ]
144
- pub fn get_shard_index_by_hash ( hash : u64 ) -> usize {
155
+ fn get_shard_index_by_hash ( hash : u64 ) -> usize {
145
156
let hash_len = mem:: size_of :: < usize > ( ) ;
146
157
// Ignore the top 7 bits as hashbrown uses these and get the next SHARD_BITS highest bits.
147
158
// hashbrown also uses the lowest bits, so we can't use those
0 commit comments