Skip to content

Commit 678ffbb

Browse files
bors[bot]ralfbiedertcuviper
committed
668: Reusing LockLatch to reduce allocation r=cuviper a=ralfbiedert This addresses the first half of rayon-rs#666. I kept the `LockLatch` and added a `reset()` method because that had overall fewer lines of code. If you want I can still change it to a separate `ReusableLockLatch` type. Co-authored-by: Ralf Biedert <rb@xr.io> Co-authored-by: Josh Stone <cuviper@gmail.com>
2 parents 45a1c33 + 9619a16 commit 678ffbb

File tree

4 files changed

+48
-17
lines changed

4 files changed

+48
-17
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ target
33
*~
44
TAGS
55
*.bk
6+
.idea

rayon-core/src/join/mod.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,12 @@ where
120120
worker: worker_thread.index()
121121
});
122122

123+
let latch = SpinLatch::new();
124+
123125
// Create virtual wrapper for task b; this all has to be
124126
// done here so that the stack frame can keep it all live
125127
// long enough.
126-
let job_b = StackJob::new(
127-
|migrated| oper_b(FnContext::new(migrated)),
128-
SpinLatch::new(),
129-
);
128+
let job_b = StackJob::new(|migrated| oper_b(FnContext::new(migrated)), latch);
130129
let job_b_ref = job_b.as_job_ref();
131130
worker_thread.push(job_b_ref);
132131

rayon-core/src/latch.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,15 @@ impl LockLatch {
8686
}
8787
}
8888

89+
/// Block until latch is set, then resets this lock latch so it can be reused again.
90+
pub(super) fn wait_and_reset(&self) {
91+
let mut guard = self.m.lock().unwrap();
92+
while !*guard {
93+
guard = self.v.wait(guard).unwrap();
94+
}
95+
*guard = false;
96+
}
97+
8998
/// Block until latch is set.
9099
pub(super) fn wait(&self) {
91100
let mut guard = self.m.lock().unwrap();
@@ -186,3 +195,21 @@ impl<'a, L: Latch> Latch for TickleLatch<'a, L> {
186195
self.sleep.tickle(usize::MAX);
187196
}
188197
}
198+
199+
impl<'a, L> LatchProbe for &'a L
200+
where
201+
L: LatchProbe,
202+
{
203+
fn probe(&self) -> bool {
204+
L::probe(self)
205+
}
206+
}
207+
208+
impl<'a, L> Latch for &'a L
209+
where
210+
L: Latch,
211+
{
212+
fn set(&self) {
213+
L::set(self);
214+
}
215+
}

rayon-core/src/registry.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -486,19 +486,23 @@ impl Registry {
486486
OP: FnOnce(&WorkerThread, bool) -> R + Send,
487487
R: Send,
488488
{
489-
// This thread isn't a member of *any* thread pool, so just block.
490-
debug_assert!(WorkerThread::current().is_null());
491-
let job = StackJob::new(
492-
|injected| {
493-
let worker_thread = WorkerThread::current();
494-
assert!(injected && !worker_thread.is_null());
495-
op(&*worker_thread, true)
496-
},
497-
LockLatch::new(),
498-
);
499-
self.inject(&[job.as_job_ref()]);
500-
job.latch.wait();
501-
job.into_result()
489+
thread_local!(static LOCK_LATCH: LockLatch = LockLatch::new());
490+
491+
LOCK_LATCH.with(|l| {
492+
// This thread isn't a member of *any* thread pool, so just block.
493+
debug_assert!(WorkerThread::current().is_null());
494+
let job = StackJob::new(
495+
|injected| {
496+
let worker_thread = WorkerThread::current();
497+
assert!(injected && !worker_thread.is_null());
498+
op(&*worker_thread, true)
499+
},
500+
l,
501+
);
502+
self.inject(&[job.as_job_ref()]);
503+
job.latch.wait_and_reset(); // Make sure we can use the same latch again next time.
504+
job.into_result()
505+
})
502506
}
503507

504508
#[cold]

0 commit comments

Comments
 (0)