Skip to content

Commit 9c24c32

Browse files
committed
refactor: better tests
1 parent aa5fb88 commit 9c24c32

File tree

18 files changed

+505
-933
lines changed

18 files changed

+505
-933
lines changed

README.md

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ use futures_executor::block_on;
2424

2525
fn main() {
2626
block_on(async {
27-
let (wg, handle) = MonoWaitGroup::new();
27+
let (wg, token) = MonoWaitGroup::new();
2828

2929
thread::spawn(move || {
3030
println!("Worker started");
3131
// Long-running task...
3232
thread::sleep(Duration::from_secs(1));
3333
println!("Worker finished");
34-
// Handle is dropped here, signaling completion
35-
handle.done();
34+
// Token is dropped here, signaling completion
35+
token.release();
3636
});
3737

3838
// Wait for the task to complete
@@ -54,16 +54,16 @@ use futures_executor::block_on;
5454

5555
fn main() {
5656
block_on(async {
57-
let (wg, base_handle) = WaitGroup::new();
57+
let (wg, factory) = WaitGroup::new();
5858

59-
for (i, handle) in repeat_n(base_handle, 8).enumerate() {
59+
for (i, token) in repeat_n(factory.into_token(), 8).enumerate() {
6060
thread::spawn(move || {
6161
println!("Task {i} started");
6262
// Long-running task...
6363
thread::sleep(Duration::from_secs(1));
6464
println!("Task {i} finished");
65-
// Handle is dropped here, signaling completion
66-
handle.done();
65+
// Token is dropped here, signaling completion
66+
token.release();
6767
});
6868
}
6969

@@ -86,18 +86,20 @@ use tokio::time::sleep;
8686

8787
#[tokio::main]
8888
async fn main() {
89-
let (wg, base_handle) = WaitGroup::new();
89+
let (wg, factory) = WaitGroup::new();
9090

91-
for (i, handle) in repeat_n(base_handle, 8).enumerate() {
92-
let task = async move {
93-
println!("Task {i} started");
94-
// Long-running task...
95-
sleep(Duration::from_secs(1)).await;
96-
println!("Task {i} finished");
91+
factory.scope(|token| {
92+
for (i, token) in repeat_n(token, 8).enumerate() {
93+
let task = async move {
94+
println!("Task {i} started");
95+
// Long-running task...
96+
sleep(Duration::from_secs(1)).await;
97+
println!("Task {i} finished");
98+
}
99+
.release_on_ready(token);
100+
tokio::spawn(task);
97101
}
98-
.with_worker_handle(handle);
99-
tokio::spawn(task);
100-
}
102+
});
101103

102104
// Wait for the task to complete
103105
wg.await;

src/ext.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ use core::{
66
use derive_more::Into;
77
use pin_project_lite::pin_project;
88

9-
use crate::{GroupToken, MonoGroupToken};
9+
use crate::{GroupToken, MonoGroupToken, group::GroupTokenFactory};
1010

1111
pub trait GroupTokenExt<T>: Sized {
12+
#[inline]
1213
fn release_on_drop(self, token: T) -> GroupTokenReleaseOnDrop<Self, T> {
1314
GroupTokenReleaseOnDrop { inner: self, token }
1415
}
1516

17+
#[inline]
1618
fn release_on_ready(self, token: T) -> GroupTokenReleaseOnReady<Self, T> {
1719
GroupTokenReleaseOnReady {
1820
inner: self,
@@ -23,6 +25,7 @@ pub trait GroupTokenExt<T>: Sized {
2325

2426
trait GroupTokenType {}
2527

28+
impl GroupTokenType for GroupTokenFactory {}
2629
impl GroupTokenType for GroupToken {}
2730
impl GroupTokenType for MonoGroupToken {}
2831

@@ -47,20 +50,24 @@ pin_project! {
4750
}
4851

4952
impl<F, T> GroupTokenReleaseOnDrop<F, T> {
53+
#[inline]
5054
pub fn inner_pin(self: Pin<&mut Self>) -> Pin<&mut F> {
5155
self.project().inner
5256
}
5357

58+
#[inline]
5459
pub fn group_token(&self) -> &T {
5560
&self.token
5661
}
5762
}
5863

5964
impl<F, T> GroupTokenReleaseOnReady<F, T> {
65+
#[inline]
6066
pub fn inner_pin(self: Pin<&mut Self>) -> Pin<&mut F> {
6167
self.project().inner
6268
}
6369

70+
#[inline]
6471
pub fn group_token(&self) -> Option<&T> {
6572
self.token.as_ref()
6673
}
@@ -69,6 +76,7 @@ impl<F, T> GroupTokenReleaseOnReady<F, T> {
6976
impl<F: Future, T> Future for GroupTokenReleaseOnDrop<F, T> {
7077
type Output = F::Output;
7178

79+
#[inline]
7280
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
7381
self.inner_pin().poll(cx)
7482
}
@@ -77,6 +85,7 @@ impl<F: Future, T> Future for GroupTokenReleaseOnDrop<F, T> {
7785
impl<F: Future, T> Future for GroupTokenReleaseOnReady<F, T> {
7886
type Output = F::Output;
7987

88+
#[inline]
8089
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
8190
let this = self.project();
8291
let res = this.inner.poll(cx);

src/group.rs

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use core::{
33
task::{Context, Poll},
44
};
55

6-
use derive_more::Debug;
6+
use derive_more::{Debug, Into};
77

88
use crate::{
99
layout::SharedLayout,
@@ -77,34 +77,42 @@ pub struct WaitGroup(#[debug("done: {}", _0.is_done())] WaitGroupWrapper<TwinRef
7777
pub struct MonoWaitGroup(#[debug("done: {}", _0.is_done())] WaitGroupWrapper<TwinRef<MonoLayout>>);
7878

7979
/// Clonable group token.
80-
#[allow(unused)]
8180
#[must_use]
8281
#[derive(Clone, Debug)]
83-
pub struct GroupToken(#[debug("done: {}", _0.is_done())] ClonableTwinRef<SharedLayout>);
82+
pub struct GroupToken(
83+
#[allow(unused)]
84+
#[debug("done: {}", _0.is_done())]
85+
ClonableTwinRef<SharedLayout>,
86+
);
8487

8588
/// Non-clonable group token.
8689
#[must_use]
8790
#[derive(Debug)]
8891
pub struct MonoGroupToken(#[debug("done: {}", _0.is_done())] TwinRef<MonoLayout>);
8992

93+
/// Factory of `GroupToken`.
94+
#[must_use]
95+
#[derive(Debug, Into)]
96+
pub struct GroupTokenFactory(GroupToken);
97+
9098
impl WaitGroup {
91-
/// Creates a new `WaitGroup` and a clonable `GroupToken`.
92-
///
93-
/// The `WaitGroup` is used to await the completion of tasks. The
94-
/// `GroupToken` is used to signal task completion.
99+
/// Creates a new `WaitGroup` and a `GroupTokenFactory`.
95100
///
96101
/// # Examples
97102
///
98103
/// ```
99104
/// use compact_waitgroup::WaitGroup;
100105
///
101-
/// let (wg, token) = WaitGroup::new();
102-
/// // ... distribute token ...
106+
/// let (wg, factory) = WaitGroup::new();
107+
/// // ... distribute token with factory ...
103108
/// ```
104-
pub fn new() -> (Self, GroupToken) {
109+
pub fn new() -> (Self, GroupTokenFactory) {
105110
let inner = SharedLayout::new();
106111
let (wg, token) = TwinRef::new_clonable(inner);
107-
(Self(WaitGroupWrapper::new(wg)), GroupToken(token))
112+
(
113+
Self(WaitGroupWrapper::new(wg)),
114+
GroupTokenFactory(GroupToken(token)),
115+
)
108116
}
109117

110118
/// Checks if the `WaitGroup` has completed.
@@ -186,6 +194,26 @@ impl Future for MonoWaitGroup {
186194
}
187195
}
188196

197+
impl GroupTokenFactory {
198+
/// Consumes the inner token.
199+
///
200+
/// This is equivalent to dropping the factory.
201+
#[inline]
202+
pub fn release(self) {
203+
drop(self);
204+
}
205+
206+
#[inline]
207+
pub fn into_token(self) -> GroupToken {
208+
self.0
209+
}
210+
211+
#[inline]
212+
pub fn scope<T, F: FnOnce(GroupToken) -> T>(self, func: F) -> T {
213+
func(self.into_token())
214+
}
215+
}
216+
189217
impl GroupToken {
190218
/// Consumes the token.
191219
///
@@ -204,6 +232,16 @@ impl MonoGroupToken {
204232
pub fn release(self) {
205233
drop(self);
206234
}
235+
236+
#[inline]
237+
pub fn into_token(self) -> Self {
238+
self
239+
}
240+
241+
#[inline]
242+
pub fn scope<T, F: FnOnce(MonoGroupToken) -> T>(self, func: F) -> T {
243+
func(self.into_token())
244+
}
207245
}
208246

209247
impl Drop for MonoGroupToken {

src/lib.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,18 @@
2727
//! ```rust
2828
//! # use compact_waitgroup::WaitGroup;
2929
//! # futures_executor::block_on(async {
30-
//! let (wg, token) = WaitGroup::new();
31-
//! let token_cloned = token.clone();
32-
//! assert!(!wg.is_done());
33-
//! std::thread::spawn(move || {
34-
//! // Long-running task
35-
//! token_cloned.release();
36-
//! });
37-
//! std::thread::spawn(move || {
38-
//! // Another long-running task
39-
//! token.release();
30+
//! let (wg, factory) = WaitGroup::new();
31+
//! factory.scope(|token| {
32+
//! let token_cloned = token.clone();
33+
//! assert!(!wg.is_done());
34+
//! std::thread::spawn(move || {
35+
//! // Long-running task
36+
//! token_cloned.release();
37+
//! });
38+
//! std::thread::spawn(move || {
39+
//! // Another long-running task
40+
//! token.release();
41+
//! });
4042
//! });
4143
//! // Wait for all tasks to complete
4244
//! wg.await;

0 commit comments

Comments
 (0)