4 Commits

Author SHA1 Message Date
e12d0e8d9a Prepare for release v0.1.1 2022-09-05 20:31:51 +02:00
bors[bot]
eee5b682a5 Merge #1
1: Fix hanging when a future wakes itself r=bertptrs a=bertptrs

It's possible that either the future wakes itself or the something requests to be awoken while the future is being polled. This PR adds a bool to the waker state to track whether that happened, and will immediately unpark the executor if it did.

Also add bors for nicer merging.

Co-authored-by: Bert Peters <bert@bertptrs.nl>
2022-09-05 18:10:14 +00:00
4500f7237a Mark minimum supported rust version 2022-09-05 20:09:29 +02:00
279654ea24 Fix hanging when a future wakes itself 2022-09-02 13:57:18 +02:00
6 changed files with 84 additions and 12 deletions

View File

@@ -14,7 +14,6 @@ jobs:
strategy:
matrix:
rust:
- "1.51" # minimum stable rust version
- stable
- beta
steps:
@@ -47,6 +46,24 @@ jobs:
command: clippy
args: --all-targets -- -D warnings
# Reduced build for the Minimum Supported Rust Version. It does not include the lints as some of
# them are out-of-date and result in false positives on the codebase, e.g. mutex_atomic.
msrv:
name: MSRV
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: "1.51"
override: true
- uses: actions-rs/cargo@v1
with:
command: test
miri:
name: Miri
runs-on: ubuntu-latest

View File

@@ -6,9 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [0.1.0]
## [0.1.1] - 2022-09-05
### Fixed
- Fixed potential hanging when the waker is called while polling.
## [0.1.0] - 2022-09-01
- Initial release
[Unreleased]: https://github.com/bertptrs/beul/compare/v0.1.0...HEAD
[Unreleased]: https://github.com/bertptrs/beul/compare/v0.1.1...HEAD
[0.1.1]: https://github.com/bertptrs/beul/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/bertptrs/beul/releases/tag/v0.1.0

View File

@@ -1,11 +1,12 @@
[package]
name = "beul"
version = "0.1.0"
version = "0.1.1"
# Edition 2021 is not available in MSRV
edition = "2018"
license = "MIT OR Apache-2.0"
description = "It executes futures"
repository = "https://github.com/bertptrs/beul/"
rust-version = "1.51"
authors = [
"Bert Peters",
]

6
bors.toml Normal file
View File

@@ -0,0 +1,6 @@
status = [
'MSRV',
'tests (stable)',
'tests (beta)',
'Miri',
]

View File

@@ -26,15 +26,36 @@ use std::task::Wake;
use std::task::Waker;
#[derive(Default)]
struct CondvarWake(Condvar);
struct CondvarWake {
park: Condvar,
awoken: Mutex<bool>,
}
impl CondvarWake {
pub fn park(&self) {
let mut guard = self.awoken.lock().unwrap_or_else(PoisonError::into_inner);
// Until we are awoken, we can park on the condvar. This also handles the case where we're
// awoken while we're actually polling.
while !*guard {
guard = self
.park
.wait(guard)
.unwrap_or_else(PoisonError::into_inner);
}
*guard = false;
}
}
impl Wake for CondvarWake {
fn wake(self: Arc<Self>) {
self.0.notify_one()
self.wake_by_ref()
}
fn wake_by_ref(self: &Arc<Self>) {
self.0.notify_one()
*self.awoken.lock().unwrap_or_else(PoisonError::into_inner) = true;
self.park.notify_one();
}
}
@@ -48,14 +69,10 @@ pub fn execute<T>(f: impl Future<Output = T>) -> T {
let mut context = Context::from_waker(&waker);
let mutex = Mutex::new(());
// Cannot panic but avoids generating the unwrap code
let mut guard = mutex.lock().unwrap_or_else(PoisonError::into_inner);
loop {
match pinned.as_mut().poll(&mut context) {
Poll::Ready(value) => return value,
Poll::Pending => guard = wake.0.wait(guard).unwrap_or_else(PoisonError::into_inner),
Poll::Pending => wake.park(),
}
}
}

View File

@@ -52,3 +52,27 @@ fn test_threaded_future() {
// Future should be polled twice, once initially and once after the wake-up
assert_eq!(beul::execute(future), 2);
}
#[test]
fn test_self_waking_futures() {
struct SelfWakingFuture(bool);
impl Future for SelfWakingFuture {
type Output = ();
fn poll(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.0 {
Poll::Ready(())
} else {
// Next time we complete
self.0 = true;
// Request to be woken up
cx.waker().wake_by_ref();
Poll::Pending
}
}
}
beul::execute(SelfWakingFuture(false));
}