Skip to content

Commit 4c3ba70

Browse files
committed
Auto merge of #229 - cole-miller:try-insert-no-grow, r=Amanieu
Add `try_insert_no_grow` method on `RawTable` This is my attempt to answer the need described in #224 by adding a method on `RawTable`: ```rust impl<T> RawTable<T, Global> { pub fn try_insert_no_grow(&mut self, hash: u64, value: T) -> Result<Bucket<T>, T>; } ``` This method follows the logic of `RawTable::insert`, but if the table would need to grow to accomodate the new element it "signals" by returning `Err(value)` instead of performing the reallocation and insertion. Marked as draft for now because - I'm not sure whether there's a better way to achieve this (advice welcome) - some tests are probably needed - there's an unused warning (despite the `pub`) that I haven't figured out how to get rid of
2 parents f9b3183 + 92677e0 commit 4c3ba70

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
## Added
11+
- Added safe `try_insert_no_grow` method to `RawTable`. (#229)
12+
1013
## Changed
1114
- The minimum Rust version has been bumped to 1.49.0. (#230)
1215

src/raw/mod.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,31 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
10131013
}
10141014
}
10151015

1016+
/// Attempts to insert a new element without growing the table and return its raw bucket.
1017+
///
1018+
/// Returns an `Err` containing the given element if inserting it would require growing the
1019+
/// table.
1020+
///
1021+
/// This does not check if the given element already exists in the table.
1022+
#[cfg(feature = "raw")]
1023+
#[cfg_attr(feature = "inline-more", inline)]
1024+
pub fn try_insert_no_grow(&mut self, hash: u64, value: T) -> Result<Bucket<T>, T> {
1025+
unsafe {
1026+
let index = self.find_insert_slot(hash);
1027+
let old_ctrl = *self.ctrl(index);
1028+
if unlikely(self.growth_left == 0 && special_is_empty(old_ctrl)) {
1029+
Err(value)
1030+
} else {
1031+
let bucket = self.bucket(index);
1032+
self.growth_left -= special_is_empty(old_ctrl) as usize;
1033+
self.set_ctrl(index, h2(hash));
1034+
bucket.write(value);
1035+
self.items += 1;
1036+
Ok(bucket)
1037+
}
1038+
}
1039+
}
1040+
10161041
/// Inserts a new element into the table, and returns a mutable reference to it.
10171042
///
10181043
/// This does not check if the given element already exists in the table.

0 commit comments

Comments
 (0)