Skip to content

Commit

Permalink
Merge pull request #73 from NobodyXu/feat/try_acquire
Browse files Browse the repository at this point in the history
feature: Impl `Client::{supports_try_acquire, try_acquire}`
  • Loading branch information
weihanglo authored Apr 7, 2024
2 parents 0d10b47 + 81195a4 commit 507eb38
Show file tree
Hide file tree
Showing 9 changed files with 404 additions and 102 deletions.
36 changes: 36 additions & 0 deletions .github/actions/compile-make/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Compile make
description: compile-make
inputs:
version:
description: make version
required: true
workaround:
description: enable workaround for _alloc bug
required: false
default: "false"

runs:
using: composite
steps:
- name: Cache make compiled
if: ${{ !startsWith(runner.os, 'windows') }}
id: cache-maka
uses: actions/cache@v4
with:
path: /usr/local/bin/make-${{ inputs.version }}
key: v1-${{ runner.os }}-make-${{ inputs.version }}

- name: Make GNU Make from source
if: ${{ !startsWith(runner.os, 'windows') && steps.cache-make.outputs.cache-hit != 'true' }}
env:
VERSION: ${{ inputs.version }}
WORKAROUND: ${{ inputs.workaround }}
shell: bash
run: |
curl "https://ftp.gnu.org/gnu/make/make-${VERSION}.tar.gz" | tar xz
pushd "make-${VERSION}"
./configure
[[ "$WORKAROUND" = "true" ]] && sed -i 's/#if !defined __alloca \&\& !defined __GNU_LIBRARY__/#if !defined __alloca \&\& defined __GNU_LIBRARY__/g; s/#ifndef __GNU_LIBRARY__/#ifdef __GNU_LIBRARY__/g' "./glob/glob.c"
make -j 4
popd
cp -p "make-${VERSION}/make" "/usr/local/bin/make-${VERSION}"
75 changes: 29 additions & 46 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,54 +13,37 @@ jobs:
rust: [stable, beta, nightly]
os: [ubuntu-latest, macos-14, windows-latest]
steps:
- uses: actions/checkout@master
- name: Install Rust (rustup)
run: |
rustup toolchain install ${{ matrix.rust }} --no-self-update --profile minimal
rustup default ${{ matrix.rust }}
shell: bash

- uses: Swatinem/rust-cache@v2
- uses: actions/checkout@master
- name: Install Rust (rustup)
run: |
rustup toolchain install ${{ matrix.rust }} --no-self-update --profile minimal
rustup default ${{ matrix.rust }}
shell: bash

- run: cargo test --locked
- uses: Swatinem/rust-cache@v2

- name: Cache make compiled
if: ${{ !startsWith(matrix.os, 'windows') }}
id: cache-make
uses: actions/cache@v4
with:
path: /usr/local/bin/make
key: ${{ runner.os }}-make-4.4.1
- run: cargo test --locked

# Compile it from source (temporarily)
- name: Make GNU Make from source
if: ${{ !startsWith(matrix.os, 'windows') && steps.cache-make.outputs.cache-hit != 'true' }}
env:
VERSION: "4.4.1"
shell: bash
run: |
curl "https://ftp.gnu.org/gnu/make/make-${VERSION}.tar.gz" | tar xz
pushd "make-${VERSION}"
./configure
make -j 4
popd
cp -p "make-${VERSION}/make" /usr/local/bin
- name: Compile make 4.4.1
uses: ./.github/actions/compile-make
with:
version: 4.4.1

- name: Test against GNU Make from source
if: ${{ !startsWith(matrix.os, 'windows') }}
shell: bash
run: cargo test --locked
env:
MAKE: /usr/local/bin/make
- name: Test against GNU Make 4.4.1
if: ${{ !startsWith(matrix.os, 'windows') }}
shell: bash
run: cargo test --locked
env:
MAKE: /usr/local/bin/make-4.4.1

rustfmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Install Rust
run: rustup update stable && rustup default stable && rustup component add rustfmt
- run: cargo fmt -- --check
- uses: actions/checkout@master
- name: Install Rust
run: rustup update stable && rustup default stable && rustup component add rustfmt
- run: cargo fmt -- --check

publish_docs:
name: Publish Documentation
Expand All @@ -86,12 +69,12 @@ jobs:
matrix:
os: [ubuntu-latest, macos-14, windows-latest]
steps:
- uses: actions/checkout@master
- name: Install Rust (rustup)
run: rustup toolchain install nightly --no-self-update --profile minimal
shell: bash
- uses: actions/checkout@master
- name: Install Rust (rustup)
run: rustup toolchain install nightly --no-self-update --profile minimal
shell: bash

- uses: taiki-e/install-action@cargo-hack
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@cargo-hack
- uses: Swatinem/rust-cache@v2

- run: cargo hack check --lib --rust-version --ignore-private --locked
- run: cargo hack check --lib --rust-version --ignore-private --locked
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
target/
**/*.rs.bk
Cargo.lock
23 changes: 21 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ edition = "2021"
rust-version = "1.63"

[target.'cfg(unix)'.dependencies]
libc = "0.2.72"
libc = "0.2.87"

[target.'cfg(unix)'.dev-dependencies]
nix = { version = "0.28.0", features = ["fs"] }

[dev-dependencies]
tempfile = "3.10.1"
Expand Down
142 changes: 96 additions & 46 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,32 @@ impl Client {
})
}

/// Acquires a token from this jobserver client in a non-blocking way.
///
/// # Return value
///
/// On successful acquisition of a token an instance of [`Acquired`] is
/// returned. This structure, when dropped, will release the token back to
/// the jobserver. It's recommended to avoid leaking this value.
///
/// # Errors
///
/// If an I/O error happens while acquiring a token then this function will
/// return immediately with the error. If an error is returned then a token
/// was not acquired.
///
/// If non-blocking acquire is not supported, the return error will have its `kind()`
/// set to [`io::ErrorKind::Unsupported`].
pub fn try_acquire(&self) -> io::Result<Option<Acquired>> {
let ret = self.inner.try_acquire()?;

Ok(ret.map(|data| Acquired {
client: self.inner.clone(),
data,
disabled: false,
}))
}

/// Returns amount of tokens in the read-side pipe.
///
/// # Return value
Expand Down Expand Up @@ -607,52 +633,76 @@ fn find_jobserver_auth(var: &str) -> Option<&str> {
.and_then(|s| s.split(' ').next())
}

#[test]
fn no_helper_deadlock() {
let x = crate::Client::new(32).unwrap();
let _y = x.clone();
std::mem::drop(x.into_helper_thread(|_| {}).unwrap());
}
#[cfg(test)]
mod test {
use super::*;

pub(super) fn run_named_fifo_try_acquire_tests(client: &Client) {
assert!(client.try_acquire().unwrap().is_none());
client.release_raw().unwrap();

#[test]
fn test_find_jobserver_auth() {
let cases = [
("", None),
("-j2", None),
("-j2 --jobserver-auth=3,4", Some("3,4")),
("--jobserver-auth=3,4 -j2", Some("3,4")),
("--jobserver-auth=3,4", Some("3,4")),
("--jobserver-auth=fifo:/myfifo", Some("fifo:/myfifo")),
("--jobserver-auth=", Some("")),
("--jobserver-auth", None),
("--jobserver-fds=3,4", Some("3,4")),
("--jobserver-fds=fifo:/myfifo", Some("fifo:/myfifo")),
("--jobserver-fds=", Some("")),
("--jobserver-fds", None),
(
"--jobserver-auth=auth-a --jobserver-auth=auth-b",
Some("auth-b"),
),
(
"--jobserver-auth=auth-b --jobserver-auth=auth-a",
Some("auth-a"),
),
("--jobserver-fds=fds-a --jobserver-fds=fds-b", Some("fds-b")),
("--jobserver-fds=fds-b --jobserver-fds=fds-a", Some("fds-a")),
(
"--jobserver-auth=auth-a --jobserver-fds=fds-a --jobserver-auth=auth-b",
Some("auth-b"),
),
(
"--jobserver-fds=fds-a --jobserver-auth=auth-a --jobserver-fds=fds-b",
Some("auth-a"),
),
];
for (var, expected) in cases {
let actual = find_jobserver_auth(var);
assert_eq!(
actual, expected,
"expect {expected:?}, got {actual:?}, input `{var:?}`"
);
let acquired = client.try_acquire().unwrap().unwrap();
assert!(client.try_acquire().unwrap().is_none());

drop(acquired);
client.try_acquire().unwrap().unwrap();
}

#[cfg(not(unix))]
#[test]
fn test_try_acquire() {
let client = Client::new(0).unwrap();

run_named_fifo_try_acquire_tests(&client);
}

#[test]
fn no_helper_deadlock() {
let x = crate::Client::new(32).unwrap();
let _y = x.clone();
std::mem::drop(x.into_helper_thread(|_| {}).unwrap());
}

#[test]
fn test_find_jobserver_auth() {
let cases = [
("", None),
("-j2", None),
("-j2 --jobserver-auth=3,4", Some("3,4")),
("--jobserver-auth=3,4 -j2", Some("3,4")),
("--jobserver-auth=3,4", Some("3,4")),
("--jobserver-auth=fifo:/myfifo", Some("fifo:/myfifo")),
("--jobserver-auth=", Some("")),
("--jobserver-auth", None),
("--jobserver-fds=3,4", Some("3,4")),
("--jobserver-fds=fifo:/myfifo", Some("fifo:/myfifo")),
("--jobserver-fds=", Some("")),
("--jobserver-fds", None),
(
"--jobserver-auth=auth-a --jobserver-auth=auth-b",
Some("auth-b"),
),
(
"--jobserver-auth=auth-b --jobserver-auth=auth-a",
Some("auth-a"),
),
("--jobserver-fds=fds-a --jobserver-fds=fds-b", Some("fds-b")),
("--jobserver-fds=fds-b --jobserver-fds=fds-a", Some("fds-a")),
(
"--jobserver-auth=auth-a --jobserver-fds=fds-a --jobserver-auth=auth-b",
Some("auth-b"),
),
(
"--jobserver-fds=fds-a --jobserver-auth=auth-a --jobserver-fds=fds-b",
Some("auth-a"),
),
];
for (var, expected) in cases {
let actual = find_jobserver_auth(var);
assert_eq!(
actual, expected,
"expect {expected:?}, got {actual:?}, input `{var:?}`"
);
}
}
}
Loading

0 comments on commit 507eb38

Please sign in to comment.