Skip to content

Commit adb58e0

Browse files
committed
Make map generic over lock type
This is necessary since there is no particular lock implementation that "makes sense" on `no_std`. This patch changes all types to be generic over any lock type that implements `lock_api::RawMutex`, and defaults to `parking_lot::RawMutex` on `std`. Note that this patch forks the struct definition for `HashMap` into one for `std` (which has a default for `L`) and one for `no_std` (which does not). This is fine since any code written _without_ the `std` feature _will_ compile with the `std` feature enabled (`indexmap` does the same; the reverse is not true). We _could_ introduce an intermediate private struct to avoid repeating the definition, but it would require writing `self.inner` all over the place, which would be sad. This seemed marginally cleaner. Also, this diff makes me want implied bounds a lot: rust-lang/rust#44491
1 parent 7b32a16 commit adb58e0

File tree

6 files changed

+203
-86
lines changed

6 files changed

+203
-86
lines changed

Cargo.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,15 @@ maintenance = { status = "experimental" }
2121

2222
[features]
2323
sanitize = ['crossbeam-epoch/sanitize']
24-
std = ["crossbeam-epoch/std", "num_cpus"]
24+
std = ["crossbeam-epoch/std", "num_cpus", "parking_lot"]
2525
default = ["std"]
2626

2727
[dependencies]
28-
parking_lot = "0.10"
28+
lock_api = "0.3.3"
29+
30+
[dependencies.parking_lot]
31+
version = "0.10"
32+
optional = true
2933

3034
[dependencies.num_cpus]
3135
version = "1.12.0"

src/iter/iter.rs

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,18 @@ use crossbeam_epoch::Guard;
66
///
77
/// See [`HashMap::iter`](crate::HashMap::iter) for details.
88
#[derive(Debug)]
9-
pub struct Iter<'g, K, V> {
10-
pub(crate) node_iter: NodeIter<'g, K, V>,
9+
pub struct Iter<'g, K, V, L>
10+
where
11+
L: lock_api::RawMutex,
12+
{
13+
pub(crate) node_iter: NodeIter<'g, K, V, L>,
1114
pub(crate) guard: &'g Guard,
1215
}
1316

14-
impl<'g, K, V> Iterator for Iter<'g, K, V> {
17+
impl<'g, K, V, L> Iterator for Iter<'g, K, V, L>
18+
where
19+
L: lock_api::RawMutex,
20+
{
1521
type Item = (&'g K, &'g V);
1622
fn next(&mut self) -> Option<Self::Item> {
1723
let node = self.node_iter.next()?;
@@ -26,11 +32,17 @@ impl<'g, K, V> Iterator for Iter<'g, K, V> {
2632
///
2733
/// See [`HashMap::keys`](crate::HashMap::keys) for details.
2834
#[derive(Debug)]
29-
pub struct Keys<'g, K, V> {
30-
pub(crate) node_iter: NodeIter<'g, K, V>,
35+
pub struct Keys<'g, K, V, L>
36+
where
37+
L: lock_api::RawMutex,
38+
{
39+
pub(crate) node_iter: NodeIter<'g, K, V, L>,
3140
}
3241

33-
impl<'g, K, V> Iterator for Keys<'g, K, V> {
42+
impl<'g, K, V, L> Iterator for Keys<'g, K, V, L>
43+
where
44+
L: lock_api::RawMutex,
45+
{
3446
type Item = &'g K;
3547
fn next(&mut self) -> Option<Self::Item> {
3648
let node = self.node_iter.next()?;
@@ -42,12 +54,18 @@ impl<'g, K, V> Iterator for Keys<'g, K, V> {
4254
///
4355
/// See [`HashMap::values`](crate::HashMap::values) for details.
4456
#[derive(Debug)]
45-
pub struct Values<'g, K, V> {
46-
pub(crate) node_iter: NodeIter<'g, K, V>,
57+
pub struct Values<'g, K, V, L>
58+
where
59+
L: lock_api::RawMutex,
60+
{
61+
pub(crate) node_iter: NodeIter<'g, K, V, L>,
4762
pub(crate) guard: &'g Guard,
4863
}
4964

50-
impl<'g, K, V> Iterator for Values<'g, K, V> {
65+
impl<'g, K, V, L> Iterator for Values<'g, K, V, L>
66+
where
67+
L: lock_api::RawMutex,
68+
{
5169
type Item = &'g V;
5270
fn next(&mut self) -> Option<Self::Item> {
5371
let node = self.node_iter.next()?;

src/iter/traverser.rs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,18 @@ use core::sync::atomic::Ordering;
99
use crossbeam_epoch::{Guard, Shared};
1010

1111
#[derive(Debug)]
12-
pub(crate) struct NodeIter<'g, K, V> {
12+
pub(crate) struct NodeIter<'g, K, V, L>
13+
where
14+
L: lock_api::RawMutex,
15+
{
1316
/// Current table; update if resized
14-
table: Option<&'g Table<K, V>>,
17+
table: Option<&'g Table<K, V, L>>,
1518

16-
stack: Option<Box<TableStack<'g, K, V>>>,
17-
spare: Option<Box<TableStack<'g, K, V>>>,
19+
stack: Option<Box<TableStack<'g, K, V, L>>>,
20+
spare: Option<Box<TableStack<'g, K, V, L>>>,
1821

1922
/// The last bin entry iterated over
20-
prev: Option<&'g Node<K, V>>,
23+
prev: Option<&'g Node<K, V, L>>,
2124

2225
/// Index of bin to use next
2326
index: usize,
@@ -34,8 +37,11 @@ pub(crate) struct NodeIter<'g, K, V> {
3437
guard: &'g Guard,
3538
}
3639

37-
impl<'g, K, V> NodeIter<'g, K, V> {
38-
pub(crate) fn new(table: Shared<'g, Table<K, V>>, guard: &'g Guard) -> Self {
40+
impl<'g, K, V, L> NodeIter<'g, K, V, L>
41+
where
42+
L: lock_api::RawMutex,
43+
{
44+
pub(crate) fn new(table: Shared<'g, Table<K, V, L>>, guard: &'g Guard) -> Self {
3945
let (table, len) = if table.is_null() {
4046
(None, 0)
4147
} else {
@@ -58,7 +64,7 @@ impl<'g, K, V> NodeIter<'g, K, V> {
5864
}
5965
}
6066

61-
fn push_state(&mut self, t: &'g Table<K, V>, i: usize, n: usize) {
67+
fn push_state(&mut self, t: &'g Table<K, V, L>, i: usize, n: usize) {
6268
let mut s = self.spare.take();
6369
if let Some(ref mut s) = s {
6470
self.spare = s.next.take();
@@ -114,8 +120,11 @@ impl<'g, K, V> NodeIter<'g, K, V> {
114120
}
115121
}
116122

117-
impl<'g, K, V> Iterator for NodeIter<'g, K, V> {
118-
type Item = &'g Node<K, V>;
123+
impl<'g, K, V, L> Iterator for NodeIter<'g, K, V, L>
124+
where
125+
L: lock_api::RawMutex,
126+
{
127+
type Item = &'g Node<K, V, L>;
119128
fn next(&mut self) -> Option<Self::Item> {
120129
let mut e = None;
121130
if let Some(prev) = self.prev {
@@ -182,19 +191,22 @@ impl<'g, K, V> Iterator for NodeIter<'g, K, V> {
182191
}
183192

184193
#[derive(Debug)]
185-
struct TableStack<'g, K, V> {
194+
struct TableStack<'g, K, V, L>
195+
where
196+
L: lock_api::RawMutex,
197+
{
186198
length: usize,
187199
index: usize,
188-
table: &'g Table<K, V>,
189-
next: Option<Box<TableStack<'g, K, V>>>,
200+
table: &'g Table<K, V, L>,
201+
next: Option<Box<TableStack<'g, K, V, L>>>,
190202
}
191203

192204
#[cfg(test)]
193205
mod tests {
194206
use super::*;
195207
use crate::raw::Table;
196208
use crossbeam_epoch::{self as epoch, Atomic, Owned};
197-
use parking_lot::Mutex;
209+
use lock_api::Mutex;
198210

199211
#[test]
200212
fn iter_new() {

0 commit comments

Comments
 (0)