Skip to content

Commit 507eb38

Browse files
authored
Merge pull request #73 from NobodyXu/feat/try_acquire
feature: Impl `Client::{supports_try_acquire, try_acquire}`
2 parents 0d10b47 + 81195a4 commit 507eb38

File tree

9 files changed

+404
-102
lines changed

9 files changed

+404
-102
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Compile make
2+
description: compile-make
3+
inputs:
4+
version:
5+
description: make version
6+
required: true
7+
workaround:
8+
description: enable workaround for _alloc bug
9+
required: false
10+
default: "false"
11+
12+
runs:
13+
using: composite
14+
steps:
15+
- name: Cache make compiled
16+
if: ${{ !startsWith(runner.os, 'windows') }}
17+
id: cache-maka
18+
uses: actions/cache@v4
19+
with:
20+
path: /usr/local/bin/make-${{ inputs.version }}
21+
key: v1-${{ runner.os }}-make-${{ inputs.version }}
22+
23+
- name: Make GNU Make from source
24+
if: ${{ !startsWith(runner.os, 'windows') && steps.cache-make.outputs.cache-hit != 'true' }}
25+
env:
26+
VERSION: ${{ inputs.version }}
27+
WORKAROUND: ${{ inputs.workaround }}
28+
shell: bash
29+
run: |
30+
curl "https://ftp.gnu.org/gnu/make/make-${VERSION}.tar.gz" | tar xz
31+
pushd "make-${VERSION}"
32+
./configure
33+
[[ "$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"
34+
make -j 4
35+
popd
36+
cp -p "make-${VERSION}/make" "/usr/local/bin/make-${VERSION}"

.github/workflows/main.yml

Lines changed: 29 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -13,54 +13,37 @@ jobs:
1313
rust: [stable, beta, nightly]
1414
os: [ubuntu-latest, macos-14, windows-latest]
1515
steps:
16-
- uses: actions/checkout@master
17-
- name: Install Rust (rustup)
18-
run: |
19-
rustup toolchain install ${{ matrix.rust }} --no-self-update --profile minimal
20-
rustup default ${{ matrix.rust }}
21-
shell: bash
22-
23-
- uses: Swatinem/rust-cache@v2
16+
- uses: actions/checkout@master
17+
- name: Install Rust (rustup)
18+
run: |
19+
rustup toolchain install ${{ matrix.rust }} --no-self-update --profile minimal
20+
rustup default ${{ matrix.rust }}
21+
shell: bash
2422

25-
- run: cargo test --locked
23+
- uses: Swatinem/rust-cache@v2
2624

27-
- name: Cache make compiled
28-
if: ${{ !startsWith(matrix.os, 'windows') }}
29-
id: cache-make
30-
uses: actions/cache@v4
31-
with:
32-
path: /usr/local/bin/make
33-
key: ${{ runner.os }}-make-4.4.1
25+
- run: cargo test --locked
3426

35-
# Compile it from source (temporarily)
36-
- name: Make GNU Make from source
37-
if: ${{ !startsWith(matrix.os, 'windows') && steps.cache-make.outputs.cache-hit != 'true' }}
38-
env:
39-
VERSION: "4.4.1"
40-
shell: bash
41-
run: |
42-
curl "https://ftp.gnu.org/gnu/make/make-${VERSION}.tar.gz" | tar xz
43-
pushd "make-${VERSION}"
44-
./configure
45-
make -j 4
46-
popd
47-
cp -p "make-${VERSION}/make" /usr/local/bin
27+
- name: Compile make 4.4.1
28+
uses: ./.github/actions/compile-make
29+
with:
30+
version: 4.4.1
4831

49-
- name: Test against GNU Make from source
50-
if: ${{ !startsWith(matrix.os, 'windows') }}
51-
shell: bash
52-
run: cargo test --locked
53-
env:
54-
MAKE: /usr/local/bin/make
32+
- name: Test against GNU Make 4.4.1
33+
if: ${{ !startsWith(matrix.os, 'windows') }}
34+
shell: bash
35+
run: cargo test --locked
36+
env:
37+
MAKE: /usr/local/bin/make-4.4.1
5538

5639
rustfmt:
5740
name: Rustfmt
5841
runs-on: ubuntu-latest
5942
steps:
60-
- uses: actions/checkout@master
61-
- name: Install Rust
62-
run: rustup update stable && rustup default stable && rustup component add rustfmt
63-
- run: cargo fmt -- --check
43+
- uses: actions/checkout@master
44+
- name: Install Rust
45+
run: rustup update stable && rustup default stable && rustup component add rustfmt
46+
- run: cargo fmt -- --check
6447

6548
publish_docs:
6649
name: Publish Documentation
@@ -86,12 +69,12 @@ jobs:
8669
matrix:
8770
os: [ubuntu-latest, macos-14, windows-latest]
8871
steps:
89-
- uses: actions/checkout@master
90-
- name: Install Rust (rustup)
91-
run: rustup toolchain install nightly --no-self-update --profile minimal
92-
shell: bash
72+
- uses: actions/checkout@master
73+
- name: Install Rust (rustup)
74+
run: rustup toolchain install nightly --no-self-update --profile minimal
75+
shell: bash
9376

94-
- uses: taiki-e/install-action@cargo-hack
95-
- uses: Swatinem/rust-cache@v2
77+
- uses: taiki-e/install-action@cargo-hack
78+
- uses: Swatinem/rust-cache@v2
9679

97-
- run: cargo hack check --lib --rust-version --ignore-private --locked
80+
- run: cargo hack check --lib --rust-version --ignore-private --locked

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
target/
22
**/*.rs.bk
3-
Cargo.lock

Cargo.lock

Lines changed: 21 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ edition = "2021"
1313
rust-version = "1.63"
1414

1515
[target.'cfg(unix)'.dependencies]
16-
libc = "0.2.72"
16+
libc = "0.2.87"
17+
18+
[target.'cfg(unix)'.dev-dependencies]
19+
nix = { version = "0.28.0", features = ["fs"] }
1720

1821
[dev-dependencies]
1922
tempfile = "3.10.1"

src/lib.rs

Lines changed: 96 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,32 @@ impl Client {
324324
})
325325
}
326326

327+
/// Acquires a token from this jobserver client in a non-blocking way.
328+
///
329+
/// # Return value
330+
///
331+
/// On successful acquisition of a token an instance of [`Acquired`] is
332+
/// returned. This structure, when dropped, will release the token back to
333+
/// the jobserver. It's recommended to avoid leaking this value.
334+
///
335+
/// # Errors
336+
///
337+
/// If an I/O error happens while acquiring a token then this function will
338+
/// return immediately with the error. If an error is returned then a token
339+
/// was not acquired.
340+
///
341+
/// If non-blocking acquire is not supported, the return error will have its `kind()`
342+
/// set to [`io::ErrorKind::Unsupported`].
343+
pub fn try_acquire(&self) -> io::Result<Option<Acquired>> {
344+
let ret = self.inner.try_acquire()?;
345+
346+
Ok(ret.map(|data| Acquired {
347+
client: self.inner.clone(),
348+
data,
349+
disabled: false,
350+
}))
351+
}
352+
327353
/// Returns amount of tokens in the read-side pipe.
328354
///
329355
/// # Return value
@@ -607,52 +633,76 @@ fn find_jobserver_auth(var: &str) -> Option<&str> {
607633
.and_then(|s| s.split(' ').next())
608634
}
609635

610-
#[test]
611-
fn no_helper_deadlock() {
612-
let x = crate::Client::new(32).unwrap();
613-
let _y = x.clone();
614-
std::mem::drop(x.into_helper_thread(|_| {}).unwrap());
615-
}
636+
#[cfg(test)]
637+
mod test {
638+
use super::*;
639+
640+
pub(super) fn run_named_fifo_try_acquire_tests(client: &Client) {
641+
assert!(client.try_acquire().unwrap().is_none());
642+
client.release_raw().unwrap();
616643

617-
#[test]
618-
fn test_find_jobserver_auth() {
619-
let cases = [
620-
("", None),
621-
("-j2", None),
622-
("-j2 --jobserver-auth=3,4", Some("3,4")),
623-
("--jobserver-auth=3,4 -j2", Some("3,4")),
624-
("--jobserver-auth=3,4", Some("3,4")),
625-
("--jobserver-auth=fifo:/myfifo", Some("fifo:/myfifo")),
626-
("--jobserver-auth=", Some("")),
627-
("--jobserver-auth", None),
628-
("--jobserver-fds=3,4", Some("3,4")),
629-
("--jobserver-fds=fifo:/myfifo", Some("fifo:/myfifo")),
630-
("--jobserver-fds=", Some("")),
631-
("--jobserver-fds", None),
632-
(
633-
"--jobserver-auth=auth-a --jobserver-auth=auth-b",
634-
Some("auth-b"),
635-
),
636-
(
637-
"--jobserver-auth=auth-b --jobserver-auth=auth-a",
638-
Some("auth-a"),
639-
),
640-
("--jobserver-fds=fds-a --jobserver-fds=fds-b", Some("fds-b")),
641-
("--jobserver-fds=fds-b --jobserver-fds=fds-a", Some("fds-a")),
642-
(
643-
"--jobserver-auth=auth-a --jobserver-fds=fds-a --jobserver-auth=auth-b",
644-
Some("auth-b"),
645-
),
646-
(
647-
"--jobserver-fds=fds-a --jobserver-auth=auth-a --jobserver-fds=fds-b",
648-
Some("auth-a"),
649-
),
650-
];
651-
for (var, expected) in cases {
652-
let actual = find_jobserver_auth(var);
653-
assert_eq!(
654-
actual, expected,
655-
"expect {expected:?}, got {actual:?}, input `{var:?}`"
656-
);
644+
let acquired = client.try_acquire().unwrap().unwrap();
645+
assert!(client.try_acquire().unwrap().is_none());
646+
647+
drop(acquired);
648+
client.try_acquire().unwrap().unwrap();
649+
}
650+
651+
#[cfg(not(unix))]
652+
#[test]
653+
fn test_try_acquire() {
654+
let client = Client::new(0).unwrap();
655+
656+
run_named_fifo_try_acquire_tests(&client);
657+
}
658+
659+
#[test]
660+
fn no_helper_deadlock() {
661+
let x = crate::Client::new(32).unwrap();
662+
let _y = x.clone();
663+
std::mem::drop(x.into_helper_thread(|_| {}).unwrap());
664+
}
665+
666+
#[test]
667+
fn test_find_jobserver_auth() {
668+
let cases = [
669+
("", None),
670+
("-j2", None),
671+
("-j2 --jobserver-auth=3,4", Some("3,4")),
672+
("--jobserver-auth=3,4 -j2", Some("3,4")),
673+
("--jobserver-auth=3,4", Some("3,4")),
674+
("--jobserver-auth=fifo:/myfifo", Some("fifo:/myfifo")),
675+
("--jobserver-auth=", Some("")),
676+
("--jobserver-auth", None),
677+
("--jobserver-fds=3,4", Some("3,4")),
678+
("--jobserver-fds=fifo:/myfifo", Some("fifo:/myfifo")),
679+
("--jobserver-fds=", Some("")),
680+
("--jobserver-fds", None),
681+
(
682+
"--jobserver-auth=auth-a --jobserver-auth=auth-b",
683+
Some("auth-b"),
684+
),
685+
(
686+
"--jobserver-auth=auth-b --jobserver-auth=auth-a",
687+
Some("auth-a"),
688+
),
689+
("--jobserver-fds=fds-a --jobserver-fds=fds-b", Some("fds-b")),
690+
("--jobserver-fds=fds-b --jobserver-fds=fds-a", Some("fds-a")),
691+
(
692+
"--jobserver-auth=auth-a --jobserver-fds=fds-a --jobserver-auth=auth-b",
693+
Some("auth-b"),
694+
),
695+
(
696+
"--jobserver-fds=fds-a --jobserver-auth=auth-a --jobserver-fds=fds-b",
697+
Some("auth-a"),
698+
),
699+
];
700+
for (var, expected) in cases {
701+
let actual = find_jobserver_auth(var);
702+
assert_eq!(
703+
actual, expected,
704+
"expect {expected:?}, got {actual:?}, input `{var:?}`"
705+
);
706+
}
657707
}
658708
}

0 commit comments

Comments
 (0)