Compare commits

...

8 Commits

Author SHA1 Message Date
Taiki Endo e0048be071
Migrate to Rust 2021 (#15) 2023-10-08 15:12:28 +09:00
John Nunley c5a8fab56f
v3.3.1
Signed-off-by: John Nunley <dev@notgull.net>
2023-09-25 10:19:44 -07:00
Taiki Endo e86ac7cfc9 Fix clippy::useless_vec warning in test
```
warning: useless use of `vec!`
 --> tests/smoke.rs:8:13
  |
8 |     let v = vec![2, 3, 5, 7, 11];
  |             ^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[2, 3, 5, 7, 11]`
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec
  = note: `#[warn(clippy::useless_vec)]` on by default

warning: useless use of `vec!`
  --> tests/smoke.rs:21:13
   |
21 |     let v = vec![10, 20, 30];
   |             ^^^^^^^^^^^^^^^^ help: you can use an array directly: `[10, 20, 30]`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec

warning: useless use of `vec!`
  --> tests/smoke.rs:30:13
   |
30 |     let v = vec![10, 20, 30];
   |             ^^^^^^^^^^^^^^^^ help: you can use an array directly: `[10, 20, 30]`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec
```
2023-09-10 20:52:03 +09:00
Taiki Endo d40a8747f6 Update actions/checkout action to v4 2023-09-10 18:26:07 +09:00
Taiki Endo 93d1bcf191 Minimize GITHUB_TOKEN permissions
Refs: https://github.blog/changelog/2021-04-20-github-actions-control-permissions-for-github_token
2023-08-06 16:57:26 +09:00
Taiki Endo 148b4f7701 Set CARGO_NET_GIT_FETCH_WITH_CLI=true in CI 2023-08-06 16:57:26 +09:00
John Nunley 1ef25770ab
Add smol-rs logo (#12) 2023-07-17 14:38:59 +09:00
John Nunley 6995e2e77a
Reimplement in 100% safe code (#11) 2023-06-11 09:27:59 -07:00
6 changed files with 73 additions and 72 deletions

View File

@ -1,5 +1,8 @@
name: CI
permissions:
contents: read
on:
pull_request:
push:
@ -10,6 +13,7 @@ on:
env:
CARGO_INCREMENTAL: 0
CARGO_NET_GIT_FETCH_WITH_CLI: true
CARGO_NET_RETRY: 10
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
@ -30,7 +34,7 @@ jobs:
os: [ubuntu-latest]
rust: [nightly, beta, stable]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust
run: rustup update ${{ matrix.rust }} && rustup default ${{ matrix.rust }}
- run: cargo build --all --all-features --all-targets
@ -45,9 +49,9 @@ jobs:
matrix:
# When updating this, the reminder to update the minimum supported
# Rust version in Cargo.toml.
rust: ['1.35']
rust: ['1.63']
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust
run: rustup update ${{ matrix.rust }} && rustup default ${{ matrix.rust }}
- run: cargo build
@ -55,7 +59,7 @@ jobs:
clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust
run: rustup update stable
- run: cargo clippy --all-features --all-targets
@ -63,7 +67,7 @@ jobs:
fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust
run: rustup update stable
- run: cargo fmt --all --check
@ -71,7 +75,7 @@ jobs:
miri:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Rust
run: rustup toolchain install nightly --component miri && rustup default nightly
- run: cargo miri test
@ -80,9 +84,13 @@ jobs:
RUSTFLAGS: ${{ env.RUSTFLAGS }} -Z randomize-layout
security_audit:
permissions:
checks: write
contents: read
issues: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
# https://github.com/rustsec/audit-check/issues/2
- uses: rustsec/audit-check@master
with:

View File

@ -1,5 +1,8 @@
name: Release
permissions:
contents: write
on:
push:
tags:
@ -10,7 +13,7 @@ jobs:
if: github.repository_owner == 'smol-rs'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: taiki-e/create-gh-release-action@v1
with:
changelog: CHANGELOG.md

View File

@ -1,3 +1,7 @@
# Version 3.3.1
- Reimplement using 100% safe code. (#11)
# Version 3.3.0
- Add `Parallel::collect()` and `Parallel::finish_in()` to allow for generic containers. (#9)

View File

@ -3,10 +3,10 @@ name = "easy-parallel"
# When publishing a new version:
# - Update CHANGELOG.md
# - Create "v3.x.y" git tag
version = "3.3.0"
version = "3.3.1"
authors = ["Stjepan Glavina <stjepang@gmail.com>"]
edition = "2018"
rust-version = "1.35"
edition = "2021"
rust-version = "1.63"
description = "Run closures in parallel"
license = "Apache-2.0 OR MIT"
repository = "https://github.com/smol-rs/easy-parallel"

View File

@ -57,12 +57,17 @@
//! ```
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
#![forbid(unsafe_code)]
#![doc(
html_favicon_url = "https://raw.githubusercontent.com/smol-rs/smol/master/assets/images/logo_fullsize_transparent.png"
)]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/smol-rs/smol/master/assets/images/logo_fullsize_transparent.png"
)]
use std::fmt;
use std::iter::{self, FromIterator};
use std::mem;
use std::iter;
use std::panic;
use std::process;
use std::sync::mpsc;
use std::thread;
@ -256,58 +261,50 @@ impl<'a, T> Parallel<'a, T> {
T: Send + 'a,
C: FromIterator<T>,
{
// Set up a guard that aborts on panic.
let guard = NoPanic;
// Set up a new thread scope.
thread::scope(|scope| {
// Join handles for spawned threads.
let mut handles = Vec::new();
// Join handles for spawned threads.
let mut handles = Vec::new();
// Channels to collect results from spawned threads.
let mut receivers = Vec::new();
// Channels to collect results from spawned threads.
let mut receivers = Vec::new();
for f in self.closures.into_iter() {
// Wrap into a closure that sends the result back.
let (sender, receiver) = mpsc::channel();
let f = move || sender.send(f()).unwrap();
// Spawn a thread for each closure after the first one.
for f in self.closures.into_iter() {
// Wrap into a closure that sends the result back.
let (sender, receiver) = mpsc::channel();
let f = move || sender.send(f()).unwrap();
// Erase the `'a` lifetime.
let f: Box<dyn FnOnce() + Send + 'a> = Box::new(f);
let f: Box<dyn FnOnce() + Send + 'static> = unsafe { mem::transmute(f) };
// Spawn a thread for the closure.
handles.push(thread::spawn(f));
receivers.push(receiver);
}
let mut last_err = None;
// Run the main closure on the main thread.
let res = panic::catch_unwind(panic::AssertUnwindSafe(f));
// Join threads and save the last panic if there was one.
for h in handles {
if let Err(err) = h.join() {
last_err = Some(err);
// Spawn it on the scope.
handles.push(scope.spawn(f));
receivers.push(receiver);
}
}
// Drop the guard because we may resume a panic now.
drop(guard);
let mut last_err = None;
// If a thread has panicked, resume the last collected panic.
if let Some(err) = last_err {
panic::resume_unwind(err);
}
// Run the main closure on the main thread.
let res = panic::catch_unwind(panic::AssertUnwindSafe(f));
// Collect the results from threads.
let results = receivers.into_iter().map(|r| r.recv().unwrap()).collect();
// Join threads and save the last panic if there was one.
for h in handles {
if let Err(err) = h.join() {
last_err = Some(err);
}
}
// If the main closure panicked, resume its panic.
match res {
Ok(r) => (results, r),
Err(err) => panic::resume_unwind(err),
}
// If a thread has panicked, resume the last collected panic.
if let Some(err) = last_err {
panic::resume_unwind(err);
}
// Collect the results from threads.
let results = receivers.into_iter().map(|r| r.recv().unwrap()).collect();
// If the main closure panicked, resume its panic.
match res {
Ok(r) => (results, r),
Err(err) => panic::resume_unwind(err),
}
})
}
}
@ -324,14 +321,3 @@ impl<T> Default for Parallel<'_, T> {
Self::new()
}
}
/// Aborts the process if dropped while panicking.
struct NoPanic;
impl Drop for NoPanic {
fn drop(&mut self) {
if thread::panicking() {
process::abort();
}
}
}

View File

@ -5,7 +5,7 @@ use easy_parallel::Parallel;
#[test]
fn smoke() {
let m = Mutex::new(0);
let v = vec![2, 3, 5, 7, 11];
let v = [2, 3, 5, 7, 11];
Parallel::new()
.add(|| *m.lock().unwrap() += 10)
@ -18,7 +18,7 @@ fn smoke() {
#[test]
fn squares() {
let v = vec![10, 20, 30];
let v = [10, 20, 30];
let squares = Parallel::new().each(0..v.len(), |i| v[i] * v[i]).run();
@ -27,7 +27,7 @@ fn squares() {
#[test]
fn finish() {
let v = vec![10, 20, 30];
let v = [10, 20, 30];
let (squares, len) = Parallel::new()
.each(0..v.len(), |i| v[i] * v[i])