Another round of tidy / warning fixes
This commit is contained in:
@@ -60,7 +60,7 @@ exclude = [
|
|||||||
"obj",
|
"obj",
|
||||||
]
|
]
|
||||||
|
|
||||||
[profile.release.package.rustc-rayon-core]
|
[profile.release.package.rustc_thread_pool]
|
||||||
# The rustc fork of Rayon has deadlock detection code which intermittently
|
# The rustc fork of Rayon has deadlock detection code which intermittently
|
||||||
# causes overflows in the CI (see https://github.com/rust-lang/rust/issues/90227)
|
# causes overflows in the CI (see https://github.com/rust-lang/rust/issues/90227)
|
||||||
# so we turn overflow checks off for now.
|
# so we turn overflow checks off for now.
|
||||||
|
|||||||
@@ -22,8 +22,6 @@
|
|||||||
//! | | | `parking_lot::Mutex<T>` |
|
//! | | | `parking_lot::Mutex<T>` |
|
||||||
//! | `RwLock<T>` | `RefCell<T>` | `parking_lot::RwLock<T>` |
|
//! | `RwLock<T>` | `RefCell<T>` | `parking_lot::RwLock<T>` |
|
||||||
//! | `MTLock<T>` [^1] | `T` | `Lock<T>` |
|
//! | `MTLock<T>` [^1] | `T` | `Lock<T>` |
|
||||||
//! | | | |
|
|
||||||
//! | `ParallelIterator` | `Iterator` | `rustc_thread_pool::iter::ParallelIterator` |
|
|
||||||
//!
|
//!
|
||||||
//! [^1]: `MTLock` is similar to `Lock`, but the serial version avoids the cost
|
//! [^1]: `MTLock` is similar to `Lock`, but the serial version avoids the cost
|
||||||
//! of a `RefCell`. This is appropriate when interior mutability is not
|
//! of a `RefCell`. This is appropriate when interior mutability is not
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use crate::job::{ArcJob, StackJob};
|
|||||||
use crate::latch::{CountLatch, LatchRef};
|
use crate::latch::{CountLatch, LatchRef};
|
||||||
use crate::registry::{Registry, WorkerThread};
|
use crate::registry::{Registry, WorkerThread};
|
||||||
|
|
||||||
mod test;
|
mod tests;
|
||||||
|
|
||||||
/// Executes `op` within every thread in the current threadpool. If this is
|
/// Executes `op` within every thread in the current threadpool. If this is
|
||||||
/// called from a non-Rayon thread, it will execute in the global threadpool.
|
/// called from a non-Rayon thread, it will execute in the global threadpool.
|
||||||
@@ -103,18 +103,18 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
let n_threads = registry.num_threads();
|
let n_threads = registry.num_threads();
|
||||||
let current_thread = WorkerThread::current().as_ref();
|
let current_thread = unsafe { WorkerThread::current().as_ref() };
|
||||||
let tlv = crate::tlv::get();
|
let tlv = crate::tlv::get();
|
||||||
let latch = CountLatch::with_count(n_threads, current_thread);
|
let latch = CountLatch::with_count(n_threads, current_thread);
|
||||||
let jobs: Vec<_> =
|
let jobs: Vec<_> =
|
||||||
(0..n_threads).map(|_| StackJob::new(tlv, &f, LatchRef::new(&latch))).collect();
|
(0..n_threads).map(|_| StackJob::new(tlv, &f, LatchRef::new(&latch))).collect();
|
||||||
let job_refs = jobs.iter().map(|job| job.as_job_ref());
|
let job_refs = jobs.iter().map(|job| unsafe { job.as_job_ref() });
|
||||||
|
|
||||||
registry.inject_broadcast(job_refs);
|
registry.inject_broadcast(job_refs);
|
||||||
|
|
||||||
// Wait for all jobs to complete, then collect the results, maybe propagating a panic.
|
// Wait for all jobs to complete, then collect the results, maybe propagating a panic.
|
||||||
latch.wait(current_thread);
|
latch.wait(current_thread);
|
||||||
jobs.into_iter().map(|job| job.into_result()).collect()
|
jobs.into_iter().map(|job| unsafe { job.into_result() }).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute `op` on every thread in the pool. It will be executed on each
|
/// Execute `op` on every thread in the pool. It will be executed on each
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ fn quick_sort<T:PartialOrd+Send>(v: &mut [T]) {
|
|||||||
|
|
||||||
let mid = partition(v);
|
let mid = partition(v);
|
||||||
let (lo, _hi) = v.split_at_mut(mid);
|
let (lo, _hi) = v.split_at_mut(mid);
|
||||||
rustc_thred_pool::join(|| quick_sort(lo), || quick_sort(lo)); //~ ERROR
|
rustc_thread_pool::join(|| quick_sort(lo), || quick_sort(lo)); //~ ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
fn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {
|
fn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ fn quick_sort<T:PartialOrd+Send>(v: &mut [T]) {
|
|||||||
|
|
||||||
let mid = partition(v);
|
let mid = partition(v);
|
||||||
let (lo, _hi) = v.split_at_mut(mid);
|
let (lo, _hi) = v.split_at_mut(mid);
|
||||||
rustc_thred_pool::join(|| quick_sort(lo), || quick_sort(v)); //~ ERROR
|
rustc_thread_pool::join(|| quick_sort(lo), || quick_sort(v)); //~ ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
fn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {
|
fn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ fn quick_sort<T:PartialOrd+Send>(v: &mut [T]) {
|
|||||||
|
|
||||||
let mid = partition(v);
|
let mid = partition(v);
|
||||||
let (_lo, hi) = v.split_at_mut(mid);
|
let (_lo, hi) = v.split_at_mut(mid);
|
||||||
rustc_thred_pool::join(|| quick_sort(hi), || quick_sort(hi)); //~ ERROR
|
rustc_thread_pool::join(|| quick_sort(hi), || quick_sort(hi)); //~ ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
fn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {
|
fn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
rustc_thred_pool::join(|| Rc::new(22), || ()); //~ ERROR
|
rustc_thread_pool::join(|| Rc::new(22), || ()); //~ ERROR
|
||||||
|
|
||||||
``` */
|
``` */
|
||||||
mod left {}
|
mod left {}
|
||||||
@@ -11,7 +11,7 @@ mod left {}
|
|||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
rustc_thred_pool::join(|| (), || Rc::new(23)); //~ ERROR
|
rustc_thread_pool::join(|| (), || Rc::new(23)); //~ ERROR
|
||||||
|
|
||||||
``` */
|
``` */
|
||||||
mod right {}
|
mod right {}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
let r = Rc::new(22);
|
let r = Rc::new(22);
|
||||||
rustc_thred_pool::join(|| r.clone(), || r.clone());
|
rustc_thread_pool::join(|| r.clone(), || r.clone());
|
||||||
//~^ ERROR
|
//~^ ERROR
|
||||||
|
|
||||||
``` */
|
``` */
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
fn bad_scope<F>(f: F)
|
fn bad_scope<F>(f: F)
|
||||||
where F: FnOnce(&i32) + Send,
|
where F: FnOnce(&i32) + Send,
|
||||||
{
|
{
|
||||||
rustc_thred_pool::scope(|s| {
|
rustc_thread_pool::scope(|s| {
|
||||||
let x = 22;
|
let x = 22;
|
||||||
s.spawn(|_| f(&x)); //~ ERROR `x` does not live long enough
|
s.spawn(|_| f(&x)); //~ ERROR `x` does not live long enough
|
||||||
});
|
});
|
||||||
@@ -13,7 +13,7 @@ fn good_scope<F>(f: F)
|
|||||||
where F: FnOnce(&i32) + Send,
|
where F: FnOnce(&i32) + Send,
|
||||||
{
|
{
|
||||||
let x = 22;
|
let x = 22;
|
||||||
rustc_thred_pool::scope(|s| {
|
rustc_thread_pool::scope(|s| {
|
||||||
s.spawn(|_| f(&x));
|
s.spawn(|_| f(&x));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ impl JobRef {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) unsafe fn execute(self) {
|
pub(super) unsafe fn execute(self) {
|
||||||
(self.execute_fn)(self.pointer)
|
unsafe { (self.execute_fn)(self.pointer) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) unsafe fn as_job_ref(&self) -> JobRef {
|
pub(super) unsafe fn as_job_ref(&self) -> JobRef {
|
||||||
JobRef::new(self)
|
unsafe { JobRef::new(self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) unsafe fn run_inline(self, stolen: bool) -> R {
|
pub(super) unsafe fn run_inline(self, stolen: bool) -> R {
|
||||||
@@ -116,12 +116,16 @@ where
|
|||||||
R: Send,
|
R: Send,
|
||||||
{
|
{
|
||||||
unsafe fn execute(this: *const ()) {
|
unsafe fn execute(this: *const ()) {
|
||||||
let this = &*(this as *const Self);
|
let this = unsafe { &*(this as *const Self) };
|
||||||
tlv::set(this.tlv);
|
tlv::set(this.tlv);
|
||||||
let abort = unwind::AbortIfPanic;
|
let abort = unwind::AbortIfPanic;
|
||||||
let func = (*this.func.get()).take().unwrap();
|
let func = unsafe { (*this.func.get()).take().unwrap() };
|
||||||
(*this.result.get()) = JobResult::call(func);
|
unsafe {
|
||||||
Latch::set(&this.latch);
|
(*this.result.get()) = JobResult::call(func);
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
Latch::set(&this.latch);
|
||||||
|
}
|
||||||
mem::forget(abort);
|
mem::forget(abort);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,7 +156,7 @@ where
|
|||||||
/// lifetimes, so it is up to you to ensure that this JobRef
|
/// lifetimes, so it is up to you to ensure that this JobRef
|
||||||
/// doesn't outlive any data that it closes over.
|
/// doesn't outlive any data that it closes over.
|
||||||
pub(super) unsafe fn into_job_ref(self: Box<Self>) -> JobRef {
|
pub(super) unsafe fn into_job_ref(self: Box<Self>) -> JobRef {
|
||||||
JobRef::new(Box::into_raw(self))
|
unsafe { JobRef::new(Box::into_raw(self)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a static `JobRef` from this job.
|
/// Creates a static `JobRef` from this job.
|
||||||
@@ -169,7 +173,7 @@ where
|
|||||||
BODY: FnOnce() + Send,
|
BODY: FnOnce() + Send,
|
||||||
{
|
{
|
||||||
unsafe fn execute(this: *const ()) {
|
unsafe fn execute(this: *const ()) {
|
||||||
let this = Box::from_raw(this as *mut Self);
|
let this = unsafe { Box::from_raw(this as *mut Self) };
|
||||||
tlv::set(this.tlv);
|
tlv::set(this.tlv);
|
||||||
(this.job)();
|
(this.job)();
|
||||||
}
|
}
|
||||||
@@ -196,7 +200,7 @@ where
|
|||||||
/// lifetimes, so it is up to you to ensure that this JobRef
|
/// lifetimes, so it is up to you to ensure that this JobRef
|
||||||
/// doesn't outlive any data that it closes over.
|
/// doesn't outlive any data that it closes over.
|
||||||
pub(super) unsafe fn as_job_ref(this: &Arc<Self>) -> JobRef {
|
pub(super) unsafe fn as_job_ref(this: &Arc<Self>) -> JobRef {
|
||||||
JobRef::new(Arc::into_raw(Arc::clone(this)))
|
unsafe { JobRef::new(Arc::into_raw(Arc::clone(this))) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a static `JobRef` from this job.
|
/// Creates a static `JobRef` from this job.
|
||||||
@@ -213,7 +217,7 @@ where
|
|||||||
BODY: Fn() + Send + Sync,
|
BODY: Fn() + Send + Sync,
|
||||||
{
|
{
|
||||||
unsafe fn execute(this: *const ()) {
|
unsafe fn execute(this: *const ()) {
|
||||||
let this = Arc::from_raw(this as *mut Self);
|
let this = unsafe { Arc::from_raw(this as *mut Self) };
|
||||||
(this.job)();
|
(this.job)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -254,17 +258,17 @@ impl JobFifo {
|
|||||||
// jobs in a thread's deque may be popped from the back (LIFO) or stolen from the front
|
// jobs in a thread's deque may be popped from the back (LIFO) or stolen from the front
|
||||||
// (FIFO), but either way they will end up popping from the front of this queue.
|
// (FIFO), but either way they will end up popping from the front of this queue.
|
||||||
self.inner.push(job_ref);
|
self.inner.push(job_ref);
|
||||||
JobRef::new(self)
|
unsafe { JobRef::new(self) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Job for JobFifo {
|
impl Job for JobFifo {
|
||||||
unsafe fn execute(this: *const ()) {
|
unsafe fn execute(this: *const ()) {
|
||||||
// We "execute" a queue by executing its first job, FIFO.
|
// We "execute" a queue by executing its first job, FIFO.
|
||||||
let this = &*(this as *const Self);
|
let this = unsafe { &*(this as *const Self) };
|
||||||
loop {
|
loop {
|
||||||
match this.inner.steal() {
|
match this.inner.steal() {
|
||||||
Steal::Success(job_ref) => break job_ref.execute(),
|
Steal::Success(job_ref) => break unsafe { job_ref.execute() },
|
||||||
Steal::Empty => panic!("FIFO is empty"),
|
Steal::Empty => panic!("FIFO is empty"),
|
||||||
Steal::Retry => {}
|
Steal::Retry => {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use crate::tlv::{self, Tlv};
|
|||||||
use crate::{FnContext, unwind};
|
use crate::{FnContext, unwind};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test;
|
mod tests;
|
||||||
|
|
||||||
/// Takes two closures and *potentially* runs them in parallel. It
|
/// Takes two closures and *potentially* runs them in parallel. It
|
||||||
/// returns a pair of the results from those closures.
|
/// returns a pair of the results from those closures.
|
||||||
@@ -41,7 +41,7 @@ mod test;
|
|||||||
/// [the `par_sort` method]: ../rayon/slice/trait.ParallelSliceMut.html#method.par_sort
|
/// [the `par_sort` method]: ../rayon/slice/trait.ParallelSliceMut.html#method.par_sort
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// let mut v = vec![5, 1, 8, 22, 0, 44];
|
/// let mut v = vec![5, 1, 8, 22, 0, 44];
|
||||||
/// quick_sort(&mut v);
|
/// quick_sort(&mut v);
|
||||||
/// assert_eq!(v, vec![0, 1, 5, 8, 22, 44]);
|
/// assert_eq!(v, vec![0, 1, 5, 8, 22, 44]);
|
||||||
@@ -192,7 +192,7 @@ unsafe fn join_recover_from_panic(
|
|||||||
err: Box<dyn Any + Send>,
|
err: Box<dyn Any + Send>,
|
||||||
tlv: Tlv,
|
tlv: Tlv,
|
||||||
) -> ! {
|
) -> ! {
|
||||||
worker_thread.wait_until(job_b_latch);
|
unsafe { worker_thread.wait_until(job_b_latch) };
|
||||||
|
|
||||||
// Restore the TLV since we might have run some jobs overwriting it when waiting for job b.
|
// Restore the TLV since we might have run some jobs overwriting it when waiting for job b.
|
||||||
tlv::set(tlv);
|
tlv::set(tlv);
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ impl CoreLatch {
|
|||||||
/// latch code.
|
/// latch code.
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn set(this: *const Self) -> bool {
|
unsafe fn set(this: *const Self) -> bool {
|
||||||
let old_state = (*this).state.swap(SET, Ordering::AcqRel);
|
let old_state = unsafe { (*this).state.swap(SET, Ordering::AcqRel) };
|
||||||
old_state == SLEEPING
|
old_state == SLEEPING
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,13 +185,13 @@ impl<'r> Latch for SpinLatch<'r> {
|
|||||||
unsafe fn set(this: *const Self) {
|
unsafe fn set(this: *const Self) {
|
||||||
let cross_registry;
|
let cross_registry;
|
||||||
|
|
||||||
let registry: &Registry = if (*this).cross {
|
let registry: &Registry = if unsafe { (*this).cross } {
|
||||||
// Ensure the registry stays alive while we notify it.
|
// Ensure the registry stays alive while we notify it.
|
||||||
// Otherwise, it would be possible that we set the spin
|
// Otherwise, it would be possible that we set the spin
|
||||||
// latch and the other thread sees it and exits, causing
|
// latch and the other thread sees it and exits, causing
|
||||||
// the registry to be deallocated, all before we get a
|
// the registry to be deallocated, all before we get a
|
||||||
// chance to invoke `registry.notify_worker_latch_is_set`.
|
// chance to invoke `registry.notify_worker_latch_is_set`.
|
||||||
cross_registry = Arc::clone((*this).registry);
|
cross_registry = Arc::clone(unsafe { (*this).registry });
|
||||||
&cross_registry
|
&cross_registry
|
||||||
} else {
|
} else {
|
||||||
// If this is not a "cross-registry" spin-latch, then the
|
// If this is not a "cross-registry" spin-latch, then the
|
||||||
@@ -199,12 +199,12 @@ impl<'r> Latch for SpinLatch<'r> {
|
|||||||
// that the registry stays alive. However, that doesn't
|
// that the registry stays alive. However, that doesn't
|
||||||
// include this *particular* `Arc` handle if the waiting
|
// include this *particular* `Arc` handle if the waiting
|
||||||
// thread then exits, so we must completely dereference it.
|
// thread then exits, so we must completely dereference it.
|
||||||
(*this).registry
|
unsafe { (*this).registry }
|
||||||
};
|
};
|
||||||
let target_worker_index = (*this).target_worker_index;
|
let target_worker_index = unsafe { (*this).target_worker_index };
|
||||||
|
|
||||||
// NOTE: Once we `set`, the target may proceed and invalidate `this`!
|
// NOTE: Once we `set`, the target may proceed and invalidate `this`!
|
||||||
if CoreLatch::set(&(*this).core_latch) {
|
if unsafe { CoreLatch::set(&(*this).core_latch) } {
|
||||||
// Subtle: at this point, we can no longer read from
|
// Subtle: at this point, we can no longer read from
|
||||||
// `self`, because the thread owning this spin latch may
|
// `self`, because the thread owning this spin latch may
|
||||||
// have awoken and deallocated the latch. Therefore, we
|
// have awoken and deallocated the latch. Therefore, we
|
||||||
@@ -249,9 +249,9 @@ impl LockLatch {
|
|||||||
impl Latch for LockLatch {
|
impl Latch for LockLatch {
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn set(this: *const Self) {
|
unsafe fn set(this: *const Self) {
|
||||||
let mut guard = (*this).m.lock().unwrap();
|
let mut guard = unsafe { (*this).m.lock().unwrap() };
|
||||||
*guard = true;
|
*guard = true;
|
||||||
(*this).v.notify_all();
|
unsafe { (*this).v.notify_all() };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,7 +286,7 @@ impl OnceLatch {
|
|||||||
registry: &Registry,
|
registry: &Registry,
|
||||||
target_worker_index: usize,
|
target_worker_index: usize,
|
||||||
) {
|
) {
|
||||||
if CoreLatch::set(&(*this).core_latch) {
|
if unsafe { CoreLatch::set(&(*this).core_latch) } {
|
||||||
registry.notify_worker_latch_is_set(target_worker_index);
|
registry.notify_worker_latch_is_set(target_worker_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,17 +384,17 @@ impl CountLatch {
|
|||||||
impl Latch for CountLatch {
|
impl Latch for CountLatch {
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn set(this: *const Self) {
|
unsafe fn set(this: *const Self) {
|
||||||
if (*this).counter.fetch_sub(1, Ordering::SeqCst) == 1 {
|
if unsafe { (*this).counter.fetch_sub(1, Ordering::SeqCst) == 1 } {
|
||||||
// NOTE: Once we call `set` on the internal `latch`,
|
// NOTE: Once we call `set` on the internal `latch`,
|
||||||
// the target may proceed and invalidate `this`!
|
// the target may proceed and invalidate `this`!
|
||||||
match (*this).kind {
|
match unsafe { &(*this).kind } {
|
||||||
CountLatchKind::Stealing { ref latch, ref registry, worker_index } => {
|
CountLatchKind::Stealing { latch, registry, worker_index } => {
|
||||||
let registry = Arc::clone(registry);
|
let registry = Arc::clone(registry);
|
||||||
if CoreLatch::set(latch) {
|
if unsafe { CoreLatch::set(latch) } {
|
||||||
registry.notify_worker_latch_is_set(worker_index);
|
registry.notify_worker_latch_is_set(*worker_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CountLatchKind::Blocking { ref latch } => LockLatch::set(latch),
|
CountLatchKind::Blocking { latch } => unsafe { LockLatch::set(latch) },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -426,6 +426,6 @@ impl<L> Deref for LatchRef<'_, L> {
|
|||||||
impl<L: Latch> Latch for LatchRef<'_, L> {
|
impl<L: Latch> Latch for LatchRef<'_, L> {
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn set(this: *const Self) {
|
unsafe fn set(this: *const Self) {
|
||||||
L::set((*this).inner);
|
unsafe { L::set((*this).inner) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,7 @@
|
|||||||
//! conflicting requirements will need to be resolved before the build will
|
//! conflicting requirements will need to be resolved before the build will
|
||||||
//! succeed.
|
//! succeed.
|
||||||
|
|
||||||
|
#![cfg_attr(test, allow(unused_crate_dependencies))]
|
||||||
#![warn(rust_2018_idioms)]
|
#![warn(rust_2018_idioms)]
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
@@ -85,7 +86,7 @@ mod unwind;
|
|||||||
mod worker_local;
|
mod worker_local;
|
||||||
|
|
||||||
mod compile_fail;
|
mod compile_fail;
|
||||||
mod test;
|
mod tests;
|
||||||
|
|
||||||
pub mod tlv;
|
pub mod tlv;
|
||||||
|
|
||||||
@@ -152,14 +153,14 @@ enum ErrorKind {
|
|||||||
/// The following creates a thread pool with 22 threads.
|
/// The following creates a thread pool with 22 threads.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// let pool = rayon::ThreadPoolBuilder::new().num_threads(22).build().unwrap();
|
/// let pool = rayon::ThreadPoolBuilder::new().num_threads(22).build().unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// To instead configure the global thread pool, use [`build_global()`]:
|
/// To instead configure the global thread pool, use [`build_global()`]:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// rayon::ThreadPoolBuilder::new().num_threads(22).build_global().unwrap();
|
/// rayon::ThreadPoolBuilder::new().num_threads(22).build_global().unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
@@ -315,7 +316,7 @@ impl ThreadPoolBuilder {
|
|||||||
/// A scoped pool may be useful in combination with scoped thread-local variables.
|
/// A scoped pool may be useful in combination with scoped thread-local variables.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
///
|
///
|
||||||
/// scoped_tls::scoped_thread_local!(static POOL_DATA: Vec<i32>);
|
/// scoped_tls::scoped_thread_local!(static POOL_DATA: Vec<i32>);
|
||||||
///
|
///
|
||||||
@@ -382,7 +383,7 @@ impl<S> ThreadPoolBuilder<S> {
|
|||||||
/// A minimal spawn handler just needs to call `run()` from an independent thread.
|
/// A minimal spawn handler just needs to call `run()` from an independent thread.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// fn main() -> Result<(), rayon::ThreadPoolBuildError> {
|
/// fn main() -> Result<(), rayon::ThreadPoolBuildError> {
|
||||||
/// let pool = rayon::ThreadPoolBuilder::new()
|
/// let pool = rayon::ThreadPoolBuilder::new()
|
||||||
/// .spawn_handler(|thread| {
|
/// .spawn_handler(|thread| {
|
||||||
@@ -400,7 +401,7 @@ impl<S> ThreadPoolBuilder<S> {
|
|||||||
/// any errors from the thread builder.
|
/// any errors from the thread builder.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// fn main() -> Result<(), rayon::ThreadPoolBuildError> {
|
/// fn main() -> Result<(), rayon::ThreadPoolBuildError> {
|
||||||
/// let pool = rayon::ThreadPoolBuilder::new()
|
/// let pool = rayon::ThreadPoolBuilder::new()
|
||||||
/// .spawn_handler(|thread| {
|
/// .spawn_handler(|thread| {
|
||||||
@@ -429,7 +430,7 @@ impl<S> ThreadPoolBuilder<S> {
|
|||||||
/// [`std::thread::scope`]: https://doc.rust-lang.org/std/thread/fn.scope.html
|
/// [`std::thread::scope`]: https://doc.rust-lang.org/std/thread/fn.scope.html
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// fn main() -> Result<(), rayon::ThreadPoolBuildError> {
|
/// fn main() -> Result<(), rayon::ThreadPoolBuildError> {
|
||||||
/// std::thread::scope(|scope| {
|
/// std::thread::scope(|scope| {
|
||||||
/// let pool = rayon::ThreadPoolBuilder::new()
|
/// let pool = rayon::ThreadPoolBuilder::new()
|
||||||
|
|||||||
@@ -533,16 +533,16 @@ impl Registry {
|
|||||||
|injected| {
|
|injected| {
|
||||||
let worker_thread = WorkerThread::current();
|
let worker_thread = WorkerThread::current();
|
||||||
assert!(injected && !worker_thread.is_null());
|
assert!(injected && !worker_thread.is_null());
|
||||||
op(&*worker_thread, true)
|
op(unsafe { &*worker_thread }, true)
|
||||||
},
|
},
|
||||||
LatchRef::new(l),
|
LatchRef::new(l),
|
||||||
);
|
);
|
||||||
self.inject(job.as_job_ref());
|
self.inject(unsafe { job.as_job_ref() });
|
||||||
self.release_thread();
|
self.release_thread();
|
||||||
job.latch.wait_and_reset(); // Make sure we can use the same latch again next time.
|
job.latch.wait_and_reset(); // Make sure we can use the same latch again next time.
|
||||||
self.acquire_thread();
|
self.acquire_thread();
|
||||||
|
|
||||||
job.into_result()
|
unsafe { job.into_result() }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,13 +561,13 @@ impl Registry {
|
|||||||
|injected| {
|
|injected| {
|
||||||
let worker_thread = WorkerThread::current();
|
let worker_thread = WorkerThread::current();
|
||||||
assert!(injected && !worker_thread.is_null());
|
assert!(injected && !worker_thread.is_null());
|
||||||
op(&*worker_thread, true)
|
op(unsafe { &*worker_thread }, true)
|
||||||
},
|
},
|
||||||
latch,
|
latch,
|
||||||
);
|
);
|
||||||
self.inject(job.as_job_ref());
|
self.inject(unsafe { job.as_job_ref() });
|
||||||
current_thread.wait_until(&job.latch);
|
unsafe { current_thread.wait_until(&job.latch) };
|
||||||
job.into_result()
|
unsafe { job.into_result() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Increments the terminate counter. This increment should be
|
/// Increments the terminate counter. This increment should be
|
||||||
@@ -759,7 +759,7 @@ impl WorkerThread {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) unsafe fn push_fifo(&self, job: JobRef) {
|
pub(super) unsafe fn push_fifo(&self, job: JobRef) {
|
||||||
self.push(self.fifo.push(job));
|
unsafe { self.push(self.fifo.push(job)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -798,7 +798,7 @@ impl WorkerThread {
|
|||||||
pub(super) unsafe fn wait_until<L: AsCoreLatch + ?Sized>(&self, latch: &L) {
|
pub(super) unsafe fn wait_until<L: AsCoreLatch + ?Sized>(&self, latch: &L) {
|
||||||
let latch = latch.as_core_latch();
|
let latch = latch.as_core_latch();
|
||||||
if !latch.probe() {
|
if !latch.probe() {
|
||||||
self.wait_until_cold(latch);
|
unsafe { self.wait_until_cold(latch) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -815,7 +815,7 @@ impl WorkerThread {
|
|||||||
// Check for local work *before* we start marking ourself idle,
|
// Check for local work *before* we start marking ourself idle,
|
||||||
// especially to avoid modifying shared sleep state.
|
// especially to avoid modifying shared sleep state.
|
||||||
if let Some(job) = self.take_local_job() {
|
if let Some(job) = self.take_local_job() {
|
||||||
self.execute(job);
|
unsafe { self.execute(job) };
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -823,7 +823,7 @@ impl WorkerThread {
|
|||||||
while !latch.probe() {
|
while !latch.probe() {
|
||||||
if let Some(job) = self.find_work() {
|
if let Some(job) = self.find_work() {
|
||||||
self.registry.sleep.work_found();
|
self.registry.sleep.work_found();
|
||||||
self.execute(job);
|
unsafe { self.execute(job) };
|
||||||
// The job might have injected local work, so go back to the outer loop.
|
// The job might have injected local work, so go back to the outer loop.
|
||||||
continue 'outer;
|
continue 'outer;
|
||||||
} else {
|
} else {
|
||||||
@@ -846,13 +846,13 @@ impl WorkerThread {
|
|||||||
let index = self.index;
|
let index = self.index;
|
||||||
|
|
||||||
registry.acquire_thread();
|
registry.acquire_thread();
|
||||||
self.wait_until(®istry.thread_infos[index].terminate);
|
unsafe { self.wait_until(®istry.thread_infos[index].terminate) };
|
||||||
|
|
||||||
// Should not be any work left in our queue.
|
// Should not be any work left in our queue.
|
||||||
debug_assert!(self.take_local_job().is_none());
|
debug_assert!(self.take_local_job().is_none());
|
||||||
|
|
||||||
// Let registry know we are done
|
// Let registry know we are done
|
||||||
Latch::set(®istry.thread_infos[index].stopped);
|
unsafe { Latch::set(®istry.thread_infos[index].stopped) };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_work(&self) -> Option<JobRef> {
|
fn find_work(&self) -> Option<JobRef> {
|
||||||
@@ -886,7 +886,7 @@ impl WorkerThread {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) unsafe fn execute(&self, job: JobRef) {
|
pub(super) unsafe fn execute(&self, job: JobRef) {
|
||||||
job.execute();
|
unsafe { job.execute() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try to steal a single job and return it.
|
/// Try to steal a single job and return it.
|
||||||
@@ -932,12 +932,12 @@ impl WorkerThread {
|
|||||||
|
|
||||||
unsafe fn main_loop(thread: ThreadBuilder) {
|
unsafe fn main_loop(thread: ThreadBuilder) {
|
||||||
let worker_thread = &WorkerThread::from(thread);
|
let worker_thread = &WorkerThread::from(thread);
|
||||||
WorkerThread::set_current(worker_thread);
|
unsafe { WorkerThread::set_current(worker_thread) };
|
||||||
let registry = &*worker_thread.registry;
|
let registry = &*worker_thread.registry;
|
||||||
let index = worker_thread.index;
|
let index = worker_thread.index;
|
||||||
|
|
||||||
// let registry know we are ready to do work
|
// let registry know we are ready to do work
|
||||||
Latch::set(®istry.thread_infos[index].primed);
|
unsafe { Latch::set(®istry.thread_infos[index].primed) };
|
||||||
|
|
||||||
// Worker threads should not panic. If they do, just abort, as the
|
// Worker threads should not panic. If they do, just abort, as the
|
||||||
// internal state of the threadpool is corrupted. Note that if
|
// internal state of the threadpool is corrupted. Note that if
|
||||||
@@ -949,7 +949,7 @@ unsafe fn main_loop(thread: ThreadBuilder) {
|
|||||||
registry.catch_unwind(|| handler(index));
|
registry.catch_unwind(|| handler(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
worker_thread.wait_until_out_of_work();
|
unsafe { worker_thread.wait_until_out_of_work() };
|
||||||
|
|
||||||
// Normal termination, do not abort.
|
// Normal termination, do not abort.
|
||||||
mem::forget(abort_guard);
|
mem::forget(abort_guard);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ use crate::tlv::{self, Tlv};
|
|||||||
use crate::unwind;
|
use crate::unwind;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test;
|
mod tests;
|
||||||
|
|
||||||
/// Represents a fork-join scope which can be used to spawn any number of tasks.
|
/// Represents a fork-join scope which can be used to spawn any number of tasks.
|
||||||
/// See [`scope()`] for more information.
|
/// See [`scope()`] for more information.
|
||||||
@@ -84,7 +84,7 @@ struct ScopeBase<'scope> {
|
|||||||
/// it would be less efficient than the real implementation:
|
/// it would be less efficient than the real implementation:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// pub fn join<A,B,RA,RB>(oper_a: A, oper_b: B) -> (RA, RB)
|
/// pub fn join<A,B,RA,RB>(oper_a: A, oper_b: B) -> (RA, RB)
|
||||||
/// where A: FnOnce() -> RA + Send,
|
/// where A: FnOnce() -> RA + Send,
|
||||||
/// B: FnOnce() -> RB + Send,
|
/// B: FnOnce() -> RB + Send,
|
||||||
@@ -125,7 +125,7 @@ struct ScopeBase<'scope> {
|
|||||||
/// To see how and when tasks are joined, consider this example:
|
/// To see how and when tasks are joined, consider this example:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// // point start
|
/// // point start
|
||||||
/// rayon::scope(|s| {
|
/// rayon::scope(|s| {
|
||||||
/// s.spawn(|s| { // task s.1
|
/// s.spawn(|s| { // task s.1
|
||||||
@@ -193,7 +193,7 @@ struct ScopeBase<'scope> {
|
|||||||
/// spawned task.
|
/// spawned task.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// let ok: Vec<i32> = vec![1, 2, 3];
|
/// let ok: Vec<i32> = vec![1, 2, 3];
|
||||||
/// rayon::scope(|s| {
|
/// rayon::scope(|s| {
|
||||||
/// let bad: Vec<i32> = vec![4, 5, 6];
|
/// let bad: Vec<i32> = vec![4, 5, 6];
|
||||||
@@ -217,7 +217,7 @@ struct ScopeBase<'scope> {
|
|||||||
/// in this case including both `ok` *and* `bad`:
|
/// in this case including both `ok` *and* `bad`:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// let ok: Vec<i32> = vec![1, 2, 3];
|
/// let ok: Vec<i32> = vec![1, 2, 3];
|
||||||
/// rayon::scope(|s| {
|
/// rayon::scope(|s| {
|
||||||
/// let bad: Vec<i32> = vec![4, 5, 6];
|
/// let bad: Vec<i32> = vec![4, 5, 6];
|
||||||
@@ -238,7 +238,7 @@ struct ScopeBase<'scope> {
|
|||||||
/// is a borrow of `ok` and capture *that*:
|
/// is a borrow of `ok` and capture *that*:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// let ok: Vec<i32> = vec![1, 2, 3];
|
/// let ok: Vec<i32> = vec![1, 2, 3];
|
||||||
/// rayon::scope(|s| {
|
/// rayon::scope(|s| {
|
||||||
/// let bad: Vec<i32> = vec![4, 5, 6];
|
/// let bad: Vec<i32> = vec![4, 5, 6];
|
||||||
@@ -260,7 +260,7 @@ struct ScopeBase<'scope> {
|
|||||||
/// of individual variables:
|
/// of individual variables:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// let ok: Vec<i32> = vec![1, 2, 3];
|
/// let ok: Vec<i32> = vec![1, 2, 3];
|
||||||
/// rayon::scope(|s| {
|
/// rayon::scope(|s| {
|
||||||
/// let bad: Vec<i32> = vec![4, 5, 6];
|
/// let bad: Vec<i32> = vec![4, 5, 6];
|
||||||
@@ -312,7 +312,7 @@ where
|
|||||||
/// [`scope()`]: fn.scope.html
|
/// [`scope()`]: fn.scope.html
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// // point start
|
/// // point start
|
||||||
/// rayon::scope_fifo(|s| {
|
/// rayon::scope_fifo(|s| {
|
||||||
/// s.spawn_fifo(|s| { // task s.1
|
/// s.spawn_fifo(|s| { // task s.1
|
||||||
@@ -487,7 +487,7 @@ impl<'scope> Scope<'scope> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// let mut value_a = None;
|
/// let mut value_a = None;
|
||||||
/// let mut value_b = None;
|
/// let mut value_b = None;
|
||||||
/// let mut value_c = None;
|
/// let mut value_c = None;
|
||||||
@@ -686,7 +686,7 @@ impl<'scope> ScopeBase<'scope> {
|
|||||||
where
|
where
|
||||||
FUNC: FnOnce(),
|
FUNC: FnOnce(),
|
||||||
{
|
{
|
||||||
let _: Option<()> = Self::execute_job_closure(this, func);
|
let _: Option<()> = unsafe { Self::execute_job_closure(this, func) };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Executes `func` as a job in scope. Adjusts the "job completed"
|
/// Executes `func` as a job in scope. Adjusts the "job completed"
|
||||||
@@ -699,11 +699,11 @@ impl<'scope> ScopeBase<'scope> {
|
|||||||
let result = match unwind::halt_unwinding(func) {
|
let result = match unwind::halt_unwinding(func) {
|
||||||
Ok(r) => Some(r),
|
Ok(r) => Some(r),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
(*this).job_panicked(err);
|
unsafe { (*this).job_panicked(err) };
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Latch::set(&(*this).job_completed_latch);
|
unsafe { Latch::set(&(*this).job_completed_latch) };
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -778,6 +778,6 @@ unsafe impl<T: Sync> Sync for ScopePtr<T> {}
|
|||||||
impl<T> ScopePtr<T> {
|
impl<T> ScopePtr<T> {
|
||||||
// Helper to avoid disjoint captures of `scope_ptr.0`
|
// Helper to avoid disjoint captures of `scope_ptr.0`
|
||||||
unsafe fn as_ref(&self) -> &T {
|
unsafe fn as_ref(&self) -> &T {
|
||||||
&*self.0
|
unsafe { &*self.0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ struct SleepData {
|
|||||||
impl SleepData {
|
impl SleepData {
|
||||||
/// Checks if the conditions for a deadlock holds and if so calls the deadlock handler
|
/// Checks if the conditions for a deadlock holds and if so calls the deadlock handler
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn deadlock_check(&self, deadlock_handler: &Option<Box<DeadlockHandler>>) {
|
pub(super) fn deadlock_check(&self, deadlock_handler: &Option<Box<DeadlockHandler>>) {
|
||||||
if self.active_threads == 0 && self.blocked_threads > 0 {
|
if self.active_threads == 0 && self.blocked_threads > 0 {
|
||||||
(deadlock_handler.as_ref().unwrap())();
|
(deadlock_handler.as_ref().unwrap())();
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,7 @@ impl Sleep {
|
|||||||
/// Mark a Rayon worker thread as blocked. This triggers the deadlock handler
|
/// Mark a Rayon worker thread as blocked. This triggers the deadlock handler
|
||||||
/// if no other worker thread is active
|
/// if no other worker thread is active
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mark_blocked(&self, deadlock_handler: &Option<Box<DeadlockHandler>>) {
|
pub(super) fn mark_blocked(&self, deadlock_handler: &Option<Box<DeadlockHandler>>) {
|
||||||
let mut data = self.data.lock().unwrap();
|
let mut data = self.data.lock().unwrap();
|
||||||
debug_assert!(data.active_threads > 0);
|
debug_assert!(data.active_threads > 0);
|
||||||
debug_assert!(data.blocked_threads < data.worker_count);
|
debug_assert!(data.blocked_threads < data.worker_count);
|
||||||
@@ -115,7 +115,7 @@ impl Sleep {
|
|||||||
|
|
||||||
/// Mark a previously blocked Rayon worker thread as unblocked
|
/// Mark a previously blocked Rayon worker thread as unblocked
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mark_unblocked(&self) {
|
pub(super) fn mark_unblocked(&self) {
|
||||||
let mut data = self.data.lock().unwrap();
|
let mut data = self.data.lock().unwrap();
|
||||||
debug_assert!(data.active_threads < data.worker_count);
|
debug_assert!(data.active_threads < data.worker_count);
|
||||||
debug_assert!(data.blocked_threads > 0);
|
debug_assert!(data.blocked_threads > 0);
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ use crate::unwind;
|
|||||||
/// This code creates a Rayon task that increments a global counter.
|
/// This code creates a Rayon task that increments a global counter.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
|
/// use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
|
||||||
///
|
///
|
||||||
/// static GLOBAL_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
|
/// static GLOBAL_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||||
@@ -80,7 +80,7 @@ where
|
|||||||
// be able to panic, and hence the data won't leak but will be
|
// be able to panic, and hence the data won't leak but will be
|
||||||
// enqueued into some deque for later execution.
|
// enqueued into some deque for later execution.
|
||||||
let abort_guard = unwind::AbortIfPanic; // just in case we are wrong, and code CAN panic
|
let abort_guard = unwind::AbortIfPanic; // just in case we are wrong, and code CAN panic
|
||||||
let job_ref = spawn_job(func, registry);
|
let job_ref = unsafe { spawn_job(func, registry) };
|
||||||
registry.inject_or_push(job_ref);
|
registry.inject_or_push(job_ref);
|
||||||
mem::forget(abort_guard);
|
mem::forget(abort_guard);
|
||||||
}
|
}
|
||||||
@@ -150,16 +150,16 @@ where
|
|||||||
// be able to panic, and hence the data won't leak but will be
|
// be able to panic, and hence the data won't leak but will be
|
||||||
// enqueued into some deque for later execution.
|
// enqueued into some deque for later execution.
|
||||||
let abort_guard = unwind::AbortIfPanic; // just in case we are wrong, and code CAN panic
|
let abort_guard = unwind::AbortIfPanic; // just in case we are wrong, and code CAN panic
|
||||||
let job_ref = spawn_job(func, registry);
|
let job_ref = unsafe { spawn_job(func, registry) };
|
||||||
|
|
||||||
// If we're in the pool, use our thread's private fifo for this thread to execute
|
// If we're in the pool, use our thread's private fifo for this thread to execute
|
||||||
// in a locally-FIFO order. Otherwise, just use the pool's global injector.
|
// in a locally-FIFO order. Otherwise, just use the pool's global injector.
|
||||||
match registry.current_thread() {
|
match registry.current_thread() {
|
||||||
Some(worker) => worker.push_fifo(job_ref),
|
Some(worker) => unsafe { worker.push_fifo(job_ref) },
|
||||||
None => registry.inject(job_ref),
|
None => registry.inject(job_ref),
|
||||||
}
|
}
|
||||||
mem::forget(abort_guard);
|
mem::forget(abort_guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test;
|
mod tests;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use crate::{
|
|||||||
Scope, ScopeFifo, ThreadPoolBuildError, ThreadPoolBuilder, join, scope, scope_fifo, spawn,
|
Scope, ScopeFifo, ThreadPoolBuildError, ThreadPoolBuilder, join, scope, scope_fifo, spawn,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod test;
|
mod tests;
|
||||||
|
|
||||||
/// Represents a user created [thread-pool].
|
/// Represents a user created [thread-pool].
|
||||||
///
|
///
|
||||||
@@ -28,7 +28,7 @@ mod test;
|
|||||||
/// ## Creating a ThreadPool
|
/// ## Creating a ThreadPool
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// let pool = rayon::ThreadPoolBuilder::new().num_threads(8).build().unwrap();
|
/// let pool = rayon::ThreadPoolBuilder::new().num_threads(8).build().unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
@@ -88,10 +88,10 @@ impl ThreadPool {
|
|||||||
/// meantime. For example
|
/// meantime. For example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// rayon::ThreadPoolBuilder::new().num_threads(1).build_global().unwrap();
|
/// rayon::ThreadPoolBuilder::new().num_threads(1).build_global().unwrap();
|
||||||
/// let pool = rustc_thred_pool::ThreadPoolBuilder::default().build().unwrap();
|
/// let pool = rustc_thread_pool::ThreadPoolBuilder::default().build().unwrap();
|
||||||
/// let do_it = || {
|
/// let do_it = || {
|
||||||
/// print!("one ");
|
/// print!("one ");
|
||||||
/// pool.install(||{});
|
/// pool.install(||{});
|
||||||
@@ -123,7 +123,7 @@ impl ThreadPool {
|
|||||||
/// ## Using `install()`
|
/// ## Using `install()`
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// let pool = rayon::ThreadPoolBuilder::new().num_threads(8).build().unwrap();
|
/// let pool = rayon::ThreadPoolBuilder::new().num_threads(8).build().unwrap();
|
||||||
/// let n = pool.install(|| fib(20));
|
/// let n = pool.install(|| fib(20));
|
||||||
@@ -172,7 +172,7 @@ impl ThreadPool {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use rustc_thred_pool as rayon;
|
/// # use rustc_thread_pool as rayon;
|
||||||
/// use std::sync::atomic::{AtomicUsize, Ordering};
|
/// use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
@@ -401,7 +401,7 @@ impl ThreadPool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn wait_until_stopped(self) {
|
pub(crate) fn wait_until_stopped(self) {
|
||||||
let registry = self.registry.clone();
|
let registry = Arc::clone(&self.registry);
|
||||||
drop(self);
|
drop(self);
|
||||||
registry.wait_until_stopped();
|
registry.wait_until_stopped();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
#![allow(unused_crate_dependencies)]
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use rustc_thred_pool::ThreadPoolBuilder;
|
use rustc_thread_pool::ThreadPoolBuilder;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
|
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
use rustc_thred_pool::ThreadPoolBuilder;
|
#![allow(unused_crate_dependencies)]
|
||||||
|
|
||||||
|
use rustc_thread_pool::ThreadPoolBuilder;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
|
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
#![allow(unused_crate_dependencies)]
|
||||||
|
|
||||||
/// Test that one can emulate join with `scope`:
|
/// Test that one can emulate join with `scope`:
|
||||||
fn pseudo_join<F, G>(f: F, g: G)
|
fn pseudo_join<F, G>(f: F, g: G)
|
||||||
where
|
where
|
||||||
F: FnOnce() + Send,
|
F: FnOnce() + Send,
|
||||||
G: FnOnce() + Send,
|
G: FnOnce() + Send,
|
||||||
{
|
{
|
||||||
rustc_thred_pool::scope(|s| {
|
rustc_thread_pool::scope(|s| {
|
||||||
s.spawn(|_| g());
|
s.spawn(|_| g());
|
||||||
f();
|
f();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
#![allow(unused_crate_dependencies)]
|
||||||
|
|
||||||
use crossbeam_utils::thread;
|
use crossbeam_utils::thread;
|
||||||
use rustc_thred_pool::ThreadPoolBuilder;
|
use rustc_thread_pool::ThreadPoolBuilder;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug)]
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
struct Local(i32);
|
struct Local(i32);
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
use rustc_thred_pool::join;
|
#![allow(unused_crate_dependencies)]
|
||||||
|
|
||||||
|
use rustc_thread_pool::join;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic(expected = "should panic")]
|
#[should_panic(expected = "should panic")]
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
#![allow(unused_crate_dependencies)]
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
use std::os::unix::process::ExitStatusExt;
|
use std::os::unix::process::ExitStatusExt;
|
||||||
use std::process::{Command, ExitStatus, Stdio};
|
use std::process::{Command, ExitStatus, Stdio};
|
||||||
|
|
||||||
use rustc_thred_pool::ThreadPoolBuilder;
|
use rustc_thread_pool::ThreadPoolBuilder;
|
||||||
|
|
||||||
fn force_stack_overflow(depth: u32) {
|
fn force_stack_overflow(depth: u32) {
|
||||||
let mut buffer = [0u8; 1024 * 1024];
|
let mut buffer = [0u8; 1024 * 1024];
|
||||||
|
|||||||
Reference in New Issue
Block a user