@@ -3,7 +3,6 @@ use crate::node::*;
3
3
use crate :: raw:: * ;
4
4
use crossbeam_epoch:: { self as epoch, Atomic , Guard , Owned , Shared } ;
5
5
use std:: borrow:: Borrow ;
6
- use std:: collections:: hash_map:: RandomState ;
7
6
use std:: fmt:: { self , Debug , Formatter } ;
8
7
use std:: hash:: { BuildHasher , Hash , Hasher } ;
9
8
use std:: iter:: FromIterator ;
@@ -12,18 +11,14 @@ use std::sync::{
12
11
Once ,
13
12
} ;
14
13
15
- macro_rules! isize_bits {
16
- ( ) => {
17
- std:: mem:: size_of:: <isize >( ) * 8
18
- } ;
19
- }
14
+ const ISIZE_BITS : usize = core:: mem:: size_of :: < isize > ( ) * 8 ;
20
15
21
16
/// The largest possible table capacity. This value must be
22
17
/// exactly 1<<30 to stay within Java array allocation and indexing
23
18
/// bounds for power of two table sizes, and is further required
24
19
/// because the top two bits of 32bit hash fields are used for
25
20
/// control purposes.
26
- const MAXIMUM_CAPACITY : usize = 1 << 30 ; // TODO: use isize_bits!()
21
+ const MAXIMUM_CAPACITY : usize = 1 << 30 ; // TODO: use ISIZE_BITS
27
22
28
23
/// The default initial table capacity. Must be a power of 2
29
24
/// (i.e., at least 1) and at most `MAXIMUM_CAPACITY`.
@@ -38,15 +33,15 @@ const MIN_TRANSFER_STRIDE: isize = 16;
38
33
39
34
/// The number of bits used for generation stamp in `size_ctl`.
40
35
/// Must be at least 6 for 32bit arrays.
41
- const RESIZE_STAMP_BITS : usize = isize_bits ! ( ) / 2 ;
36
+ const RESIZE_STAMP_BITS : usize = ISIZE_BITS / 2 ;
42
37
43
38
/// The maximum number of threads that can help resize.
44
39
/// Must fit in `32 - RESIZE_STAMP_BITS` bits for 32 bit architectures
45
40
/// and `64 - RESIZE_STAMP_BITS` bits for 64 bit architectures
46
- const MAX_RESIZERS : isize = ( 1 << ( isize_bits ! ( ) - RESIZE_STAMP_BITS ) ) - 1 ;
41
+ const MAX_RESIZERS : isize = ( 1 << ( ISIZE_BITS - RESIZE_STAMP_BITS ) ) - 1 ;
47
42
48
43
/// The bit shift for recording size stamp in `size_ctl`.
49
- const RESIZE_STAMP_SHIFT : usize = isize_bits ! ( ) - RESIZE_STAMP_BITS ;
44
+ const RESIZE_STAMP_SHIFT : usize = ISIZE_BITS - RESIZE_STAMP_BITS ;
50
45
51
46
static NCPU_INITIALIZER : Once = Once :: new ( ) ;
52
47
static NCPU : AtomicUsize = AtomicUsize :: new ( 0 ) ;
@@ -61,7 +56,7 @@ macro_rules! load_factor {
61
56
/// A concurrent hash table.
62
57
///
63
58
/// See the [crate-level documentation](index.html) for details.
64
- pub struct HashMap < K , V , S = RandomState > {
59
+ pub struct HashMap < K , V , S = crate :: DefaultHashBuilder > {
65
60
/// The array of bins. Lazily initialized upon first insertion.
66
61
/// Size is always a power of two. Accessed directly by iterators.
67
62
table : Atomic < Table < K , V > > ,
@@ -85,30 +80,32 @@ pub struct HashMap<K, V, S = RandomState> {
85
80
build_hasher : S ,
86
81
}
87
82
88
- impl < K , V > Default for HashMap < K , V , RandomState >
83
+ impl < K , V , S > Default for HashMap < K , V , S >
89
84
where
90
85
K : Sync + Send + Clone + Hash + Eq ,
91
86
V : Sync + Send ,
87
+ S : BuildHasher + Default ,
92
88
{
93
89
fn default ( ) -> Self {
94
90
Self :: new ( )
95
91
}
96
92
}
97
93
98
- impl < K , V > HashMap < K , V , RandomState >
94
+ impl < K , V , S > HashMap < K , V , S >
99
95
where
100
96
K : Sync + Send + Clone + Hash + Eq ,
101
97
V : Sync + Send ,
98
+ S : BuildHasher + Default ,
102
99
{
103
100
/// Creates a new, empty map with the default initial table size (16).
104
101
pub fn new ( ) -> Self {
105
- Self :: with_hasher ( RandomState :: new ( ) )
102
+ Self :: with_hasher ( S :: default ( ) )
106
103
}
107
104
108
105
/// Creates a new, empty map with an initial table size accommodating the specified number of
109
106
/// elements without the need to dynamically resize.
110
107
pub fn with_capacity ( n : usize ) -> Self {
111
- Self :: with_capacity_and_hasher ( RandomState :: new ( ) , n)
108
+ Self :: with_capacity_and_hasher ( S :: default ( ) , n)
112
109
}
113
110
}
114
111
@@ -172,16 +169,16 @@ where
172
169
h. finish ( )
173
170
}
174
171
172
+ #[ inline]
175
173
/// Tests if `key` is a key in this table.
176
174
///
177
175
/// The key may be any borrowed form of the map's key type, but `Hash` and `Eq` on the borrowed
178
176
/// form must match those for the key type.
179
- pub fn contains_key < Q > ( & self , key : & Q ) -> bool
177
+ pub fn contains_key < Q > ( & self , key : & Q , guard : & Guard ) -> bool
180
178
where
181
179
K : Borrow < Q > ,
182
180
Q : ?Sized + Hash + Eq ,
183
181
{
184
- let guard = crossbeam_epoch:: pin ( ) ;
185
182
self . get ( key, & guard) . is_some ( )
186
183
}
187
184
@@ -261,19 +258,19 @@ where
261
258
unsafe { v. as_ref ( ) }
262
259
}
263
260
261
+ #[ inline]
264
262
/// Obtains the value to which `key` is mapped and passes it through the closure `then`.
265
263
///
266
264
/// Returns `None` if this map contains no mapping for `key`.
267
265
///
268
266
/// The key may be any borrowed form of the map's key type, but `Hash` and `Eq` on the borrowed
269
267
/// form must match those for the key type.
270
- pub fn get_and < Q , R , F > ( & self , key : & Q , then : F ) -> Option < R >
268
+ pub fn get_and < Q , R , F > ( & self , key : & Q , then : F , guard : & Guard ) -> Option < R >
271
269
where
272
270
K : Borrow < Q > ,
273
271
Q : ?Sized + Hash + Eq ,
274
272
F : FnOnce ( & V ) -> R ,
275
273
{
276
- let guard = & crossbeam_epoch:: pin ( ) ;
277
274
self . get ( key, guard) . map ( then)
278
275
}
279
276
@@ -536,7 +533,7 @@ where
536
533
}
537
534
}
538
535
539
- fn put_all < ' g , I : Iterator < Item = ( K , V ) > > ( & self , iter : I , guard : & ' g Guard ) {
536
+ fn put_all < I : Iterator < Item = ( K , V ) > > ( & self , iter : I , guard : & Guard ) {
540
537
for ( key, value) in iter {
541
538
self . put ( key, value, false , guard) ;
542
539
}
@@ -1164,7 +1161,7 @@ where
1164
1161
}
1165
1162
1166
1163
/// Tries to presize table to accommodate the given number of elements.
1167
- fn try_presize < ' g > ( & self , size : usize , guard : & ' g Guard ) {
1164
+ fn try_presize ( & self , size : usize , guard : & Guard ) {
1168
1165
let requested_capacity = if size >= MAXIMUM_CAPACITY / 2 {
1169
1166
MAXIMUM_CAPACITY
1170
1167
} else {
@@ -1275,11 +1272,9 @@ where
1275
1272
#[ inline]
1276
1273
/// Tries to reserve capacity for at least additional more elements.
1277
1274
/// The collection may reserve more space to avoid frequent reallocations.
1278
- pub fn reserve ( & self , additional : usize ) {
1275
+ pub fn reserve ( & self , additional : usize , guard : & Guard ) {
1279
1276
let absolute = self . len ( ) + additional;
1280
-
1281
- let guard = epoch:: pin ( ) ;
1282
- self . try_presize ( absolute, & guard) ;
1277
+ self . try_presize ( absolute, guard) ;
1283
1278
}
1284
1279
1285
1280
/// Removes the key (and its corresponding value) from this map.
@@ -1472,16 +1467,15 @@ where
1472
1467
/// If `f` returns `false` for a given key/value pair, but the value for that pair is concurrently
1473
1468
/// modified before the removal takes place, the entry will not be removed.
1474
1469
/// If you want the removal to happen even in the case of concurrent modification, use [`HashMap::retain_force`].
1475
- pub fn retain < F > ( & self , mut f : F )
1470
+ pub fn retain < F > ( & self , mut f : F , guard : & Guard )
1476
1471
where
1477
1472
F : FnMut ( & K , & V ) -> bool ,
1478
1473
{
1479
- let guard = epoch:: pin ( ) ;
1480
1474
// removed selected keys
1481
1475
for ( k, v) in self . iter ( & guard) {
1482
1476
if !f ( k, v) {
1483
1477
let old_value: Shared < ' _ , V > = Shared :: from ( v as * const V ) ;
1484
- self . replace_node ( k, None , Some ( old_value) , & guard) ;
1478
+ self . replace_node ( k, None , Some ( old_value) , guard) ;
1485
1479
}
1486
1480
}
1487
1481
}
@@ -1492,15 +1486,14 @@ where
1492
1486
///
1493
1487
/// This method always deletes any key/value pair that `f` returns `false` for,
1494
1488
/// even if if the value is updated concurrently. If you do not want that behavior, use [`HashMap::retain`].
1495
- pub fn retain_force < F > ( & self , mut f : F )
1489
+ pub fn retain_force < F > ( & self , mut f : F , guard : & Guard )
1496
1490
where
1497
1491
F : FnMut ( & K , & V ) -> bool ,
1498
1492
{
1499
- let guard = epoch:: pin ( ) ;
1500
1493
// removed selected keys
1501
1494
for ( k, v) in self . iter ( & guard) {
1502
1495
if !f ( k, v) {
1503
- self . replace_node ( k, None , None , & guard) ;
1496
+ self . replace_node ( k, None , None , guard) ;
1504
1497
}
1505
1498
}
1506
1499
}
@@ -1544,7 +1537,7 @@ where
1544
1537
#[ inline]
1545
1538
#[ cfg( test) ]
1546
1539
/// Returns the capacity of the map.
1547
- fn capacity < ' g > ( & self , guard : & ' g Guard ) -> usize {
1540
+ fn capacity ( & self , guard : & Guard ) -> usize {
1548
1541
let table = self . table . load ( Ordering :: Relaxed , & guard) ;
1549
1542
1550
1543
if table. is_null ( ) {
@@ -1644,9 +1637,9 @@ where
1644
1637
( iter. size_hint ( ) . 0 + 1 ) / 2
1645
1638
} ;
1646
1639
1647
- self . reserve ( reserve ) ;
1640
+ let guard = epoch :: pin ( ) ;
1648
1641
1649
- let guard = crossbeam_epoch :: pin ( ) ;
1642
+ self . reserve ( reserve , & guard) ;
1650
1643
( * self ) . put_all ( iter. into_iter ( ) , & guard) ;
1651
1644
}
1652
1645
}
@@ -1663,10 +1656,11 @@ where
1663
1656
}
1664
1657
}
1665
1658
1666
- impl < K , V > FromIterator < ( K , V ) > for HashMap < K , V , RandomState >
1659
+ impl < K , V , S > FromIterator < ( K , V ) > for HashMap < K , V , S >
1667
1660
where
1668
1661
K : Sync + Send + Clone + Hash + Eq ,
1669
1662
V : Sync + Send ,
1663
+ S : BuildHasher + Default ,
1670
1664
{
1671
1665
fn from_iter < T : IntoIterator < Item = ( K , V ) > > ( iter : T ) -> Self {
1672
1666
let mut iter = iter. into_iter ( ) ;
@@ -1688,21 +1682,23 @@ where
1688
1682
}
1689
1683
}
1690
1684
1691
- impl < ' a , K , V > FromIterator < ( & ' a K , & ' a V ) > for HashMap < K , V , RandomState >
1685
+ impl < ' a , K , V , S > FromIterator < ( & ' a K , & ' a V ) > for HashMap < K , V , S >
1692
1686
where
1693
1687
K : Sync + Send + Copy + Hash + Eq ,
1694
1688
V : Sync + Send + Copy ,
1689
+ S : BuildHasher + Default ,
1695
1690
{
1696
1691
#[ inline]
1697
1692
fn from_iter < T : IntoIterator < Item = ( & ' a K , & ' a V ) > > ( iter : T ) -> Self {
1698
1693
Self :: from_iter ( iter. into_iter ( ) . map ( |( & k, & v) | ( k, v) ) )
1699
1694
}
1700
1695
}
1701
1696
1702
- impl < ' a , K , V > FromIterator < & ' a ( K , V ) > for HashMap < K , V , RandomState >
1697
+ impl < ' a , K , V , S > FromIterator < & ' a ( K , V ) > for HashMap < K , V , S >
1703
1698
where
1704
1699
K : Sync + Send + Copy + Hash + Eq ,
1705
1700
V : Sync + Send + Copy ,
1701
+ S : BuildHasher + Default ,
1706
1702
{
1707
1703
#[ inline]
1708
1704
fn from_iter < T : IntoIterator < Item = & ' a ( K , V ) > > ( iter : T ) -> Self {
@@ -1733,7 +1729,6 @@ where
1733
1729
/// Returns the number of physical CPUs in the machine (_O(1)_).
1734
1730
fn num_cpus ( ) -> usize {
1735
1731
NCPU_INITIALIZER . call_once ( || NCPU . store ( num_cpus:: get_physical ( ) , Ordering :: Relaxed ) ) ;
1736
-
1737
1732
NCPU . load ( Ordering :: Relaxed )
1738
1733
}
1739
1734
@@ -1764,6 +1759,7 @@ fn capacity() {
1764
1759
// The table has been resized once (and it's capacity doubled),
1765
1760
// since we inserted more elements than it can hold
1766
1761
}
1762
+
1767
1763
#[ cfg( test) ]
1768
1764
mod tests {
1769
1765
use super :: * ;
@@ -1774,7 +1770,7 @@ mod tests {
1774
1770
1775
1771
map. insert ( 42 , 0 , & guard) ;
1776
1772
1777
- map. reserve ( 32 ) ;
1773
+ map. reserve ( 32 , & guard ) ;
1778
1774
1779
1775
let capacity = map. capacity ( & guard) ;
1780
1776
assert ! ( capacity >= 16 + 32 ) ;
@@ -1785,7 +1781,7 @@ mod tests {
1785
1781
let map = HashMap :: < usize , usize > :: new ( ) ;
1786
1782
let guard = epoch:: pin ( ) ;
1787
1783
1788
- map. reserve ( 32 ) ;
1784
+ map. reserve ( 32 , & guard ) ;
1789
1785
1790
1786
let capacity = map. capacity ( & guard) ;
1791
1787
assert ! ( capacity >= 32 ) ;
0 commit comments