@@ -3,10 +3,11 @@ 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 } ;
6
+ use std:: intrinsics:: likely;
6
7
use std:: mem;
7
8
8
9
#[ derive( Default ) ]
9
- #[ cfg_attr ( parallel_compiler , repr( align( 64 ) ) ) ]
10
+ #[ repr( align( 64 ) ) ]
10
11
struct CacheAligned < T > ( T ) ;
11
12
12
13
// 32 shards is sufficient to reduce contention on an 8-core Ryzen 7 1700,
@@ -18,8 +19,9 @@ pub const SHARDS: usize = 1 << SHARD_BITS;
18
19
19
20
/// An array of cache-line aligned inner locked structures with convenience methods.
20
21
pub struct Sharded < T > {
21
- shards : [ CacheAligned < Lock < T > > ; SHARDS ] ,
22
22
single_thread : bool ,
23
+ shard : Lock < T > ,
24
+ shards : [ CacheAligned < Lock < T > > ; SHARDS ] ,
23
25
}
24
26
25
27
impl < T : Default > Default for Sharded < T > {
@@ -33,37 +35,42 @@ impl<T> Sharded<T> {
33
35
#[ inline]
34
36
pub fn new ( mut value : impl FnMut ( ) -> T ) -> Self {
35
37
Sharded {
36
- shards : [ ( ) ; SHARDS ] . map ( |( ) | CacheAligned ( Lock :: new ( value ( ) ) ) ) ,
37
38
single_thread : !active ( ) ,
39
+ shard : Lock :: new ( value ( ) ) ,
40
+ shards : [ ( ) ; SHARDS ] . map ( |( ) | CacheAligned ( Lock :: new ( value ( ) ) ) ) ,
38
41
}
39
42
}
40
43
41
44
/// The shard is selected by hashing `val` with `FxHasher`.
42
45
#[ inline]
43
46
pub fn get_shard_by_value < K : Hash + ?Sized > ( & self , val : & K ) -> & Lock < T > {
44
- if self . single_thread { & self . shards [ 0 ] . 0 } else { self . get_shard_by_hash ( make_hash ( val) ) }
47
+ if likely ( self . single_thread ) {
48
+ & self . shard
49
+ } else {
50
+ & self . shards [ get_shard_index_by_hash ( make_hash ( val) ) ] . 0
51
+ }
45
52
}
46
53
47
54
#[ inline]
48
55
pub fn get_shard_by_hash ( & self , hash : u64 ) -> & Lock < T > {
49
- if self . single_thread {
50
- & self . shards [ 0 ] . 0
56
+ if likely ( self . single_thread ) {
57
+ & self . shard
51
58
} else {
52
59
& self . shards [ get_shard_index_by_hash ( hash) ] . 0
53
60
}
54
61
}
55
62
56
63
pub fn lock_shards ( & self ) -> Vec < LockGuard < ' _ , T > > {
57
- if self . single_thread {
58
- vec ! [ self . shards [ 0 ] . 0 . lock( ) ]
64
+ if likely ( self . single_thread ) {
65
+ vec ! [ self . shard . lock( ) ]
59
66
} else {
60
67
( 0 ..SHARDS ) . map ( |i| self . shards [ i] . 0 . lock ( ) ) . collect ( )
61
68
}
62
69
}
63
70
64
71
pub fn try_lock_shards ( & self ) -> Option < Vec < LockGuard < ' _ , T > > > {
65
- if self . single_thread {
66
- Some ( vec ! [ self . shards [ 0 ] . 0 . try_lock( ) ?] )
72
+ if likely ( self . single_thread ) {
73
+ Some ( vec ! [ self . shard . try_lock( ) ?] )
67
74
} else {
68
75
( 0 ..SHARDS ) . map ( |i| self . shards [ i] . 0 . try_lock ( ) ) . collect ( )
69
76
}
0 commit comments