Skip to content

Commit f41fa13

Browse files
authored
make tuple::hca::HighContentionAllocator be Send (#214)
make tuple::hca::HighContentionAllocator be Send - thread rng is not `Send`; instead, seed a `SmallRng` from it, which is `Send` - use of allocation mutex was causing non-`Send`ability despite being dropped before any `.await` boundaries; wrapped in blocks. - update related test to use `.boxed()` instead of `.boxed_local()`
1 parent 85474f5 commit f41fa13

File tree

3 files changed

+32
-22
lines changed

3 files changed

+32
-22
lines changed

foundationdb/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ foundationdb-gen = { version = "0.5.1", path = "../foundationdb-gen", default-fe
4545
foundationdb-sys = { version = "0.5.1", path = "../foundationdb-sys", default-features = false }
4646
futures = "0.3.1"
4747
memchr = "2.2.1"
48-
rand = "0.7.2"
48+
rand = { version = "0.7.2", features = ["default", "small_rng"] }
4949
static_assertions = "1.1.0"
5050
uuid = { version = "0.8.1", optional = true }
5151
num-bigint = { version = "0.3.0", optional = true }

foundationdb/src/tuple/hca.rs

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use std::fmt;
2828
use std::sync::{Mutex, PoisonError};
2929

3030
use futures::future;
31-
use rand::Rng;
31+
use rand::{self, rngs::SmallRng, Error as RandError, Rng, SeedableRng};
3232

3333
use crate::options::{ConflictRangeType, MutationType, TransactionOption};
3434
use crate::tuple::{PackError, Subspace};
@@ -41,6 +41,7 @@ pub enum HcaError {
4141
PackError(PackError),
4242
InvalidDirectoryLayerMetadata,
4343
PoisonError,
44+
RandError(RandError),
4445
}
4546

4647
impl fmt::Debug for HcaError {
@@ -52,6 +53,7 @@ impl fmt::Debug for HcaError {
5253
write!(f, "invalid directory layer metadata")
5354
}
5455
HcaError::PoisonError => write!(f, "mutex poisoned"),
56+
HcaError::RandError(err) => err.fmt(f),
5557
}
5658
}
5759
}
@@ -71,6 +73,11 @@ impl<T> From<PoisonError<T>> for HcaError {
7173
Self::PoisonError
7274
}
7375
}
76+
impl From<RandError> for HcaError {
77+
fn from(err: RandError) -> Self {
78+
Self::RandError(err)
79+
}
80+
}
7481

7582
impl TransactError for HcaError {
7683
fn try_into_fdb_error(self) -> Result<FdbError, Self> {
@@ -114,7 +121,7 @@ impl HighContentionAllocator {
114121
reverse: true,
115122
..RangeOption::default()
116123
};
117-
let mut rng = rand::thread_rng();
124+
let mut rng = SmallRng::from_rng(&mut rand::thread_rng())?;
118125

119126
loop {
120127
let kvs = trx.get_range(&counters_range, 1, true).await?;
@@ -130,17 +137,18 @@ impl HighContentionAllocator {
130137
let window = loop {
131138
let counters_start = self.counters.subspace(&start);
132139

133-
let mutex_guard = self.allocation_mutex.lock()?;
134-
if window_advanced {
135-
trx.clear_range(self.counters.bytes(), counters_start.bytes());
136-
trx.set_option(TransactionOption::NextWriteNoWriteConflictRange)?;
137-
trx.clear_range(self.recent.bytes(), self.recent.subspace(&start).bytes());
138-
}
139-
140-
// Increment the allocation count for the current window
141-
trx.atomic_op(counters_start.bytes(), ONE_BYTES, MutationType::Add);
142-
let count_future = trx.get(counters_start.bytes(), true);
143-
drop(mutex_guard);
140+
let count_future = {
141+
let _mutex_guard = self.allocation_mutex.lock()?;
142+
if window_advanced {
143+
trx.clear_range(self.counters.bytes(), counters_start.bytes());
144+
trx.set_option(TransactionOption::NextWriteNoWriteConflictRange)?;
145+
trx.clear_range(self.recent.bytes(), self.recent.subspace(&start).bytes());
146+
};
147+
148+
// Increment the allocation count for the current window
149+
trx.atomic_op(counters_start.bytes(), ONE_BYTES, MutationType::Add);
150+
trx.get(counters_start.bytes(), true)
151+
};
144152

145153
let count_value = count_future.await?;
146154
let count = if let Some(count_value) = count_value {
@@ -171,12 +179,14 @@ impl HighContentionAllocator {
171179
let candidate: i64 = rng.gen_range(start, start + window);
172180
let recent_candidate = self.recent.subspace(&candidate);
173181

174-
let mutex_guard = self.allocation_mutex.lock()?;
175-
let latest_counter = trx.get_range(&counters_range, 1, true);
176-
let candidate_value = trx.get(recent_candidate.bytes(), false);
177-
trx.set_option(TransactionOption::NextWriteNoWriteConflictRange)?;
178-
trx.set(recent_candidate.bytes(), &[]);
179-
drop(mutex_guard);
182+
let (latest_counter, candidate_value) = {
183+
let _mutex_guard = self.allocation_mutex.lock()?;
184+
let latest_counter = trx.get_range(&counters_range, 1, true);
185+
let candidate_value = trx.get(recent_candidate.bytes(), false);
186+
trx.set_option(TransactionOption::NextWriteNoWriteConflictRange)?;
187+
trx.set(recent_candidate.bytes(), &[]);
188+
(latest_counter, candidate_value)
189+
};
180190

181191
let (latest_counter, candidate_value) =
182192
future::try_join(latest_counter, candidate_value).await?;

foundationdb/tests/hca.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ async fn test_hca_concurrent_allocations_async() -> FdbResult<()> {
6969
let hca = HighContentionAllocator::new(Subspace::from_bytes(KEY));
7070

7171
let all_ints: Vec<i64> = future::try_join_all((0..N).map(|_| {
72-
db.transact_boxed_local(
72+
db.transact_boxed(
7373
&hca,
74-
move |tx, hca| hca.allocate(tx).boxed_local(),
74+
move |tx, hca| hca.allocate(tx).boxed(),
7575
TransactOption::default(),
7676
)
7777
}))

0 commit comments

Comments
 (0)