Index: Cargo.toml ================================================================== --- Cargo.toml +++ Cargo.toml @@ -1,8 +1,8 @@ [package] name = "swctx" -version = "0.1.0" +version = "0.1.1" edition = "2021" license = "0BSD" categories = [ "concurrency", "asynchronous" ] keywords = [ "channel", "threads", "sync", "message-passing" ] repository = "https://repos.qrnch.tech/pub/swctx" Index: src/lib.rs ================================================================== --- src/lib.rs +++ src/lib.rs @@ -69,10 +69,36 @@ struct Inner { state: State, waker: Option } + +impl Inner { + fn try_get(&mut self) -> Result, Error> { + match self.state { + State::Inactive | State::Waiting => Ok(None), + State::Data(_) => { + let old = std::mem::replace(&mut self.state, State::Finalized); + let State::Data(data) = old else { + panic!("Unable to extract data"); + }; + Ok(Some(data)) + } + State::Err(_) => { + let old = std::mem::replace(&mut self.state, State::Finalized); + let State::Err(err) = old else { + panic!("Unable to extract error"); + }; + Err(err) + } + _ => { + panic!("Unexpected state"); + } + } + } +} + struct Shared { inner: Mutex>, signal: Condvar } Index: src/wctx.rs ================================================================== --- src/wctx.rs +++ src/wctx.rs @@ -41,14 +41,30 @@ panic!("Unexpected state"); } } } } + + /// Non-blocking attempt to get the get the stored value. + /// + /// Returns `Ok(Some(T))` if a value has been stored. Returns `Ok(None)` if + /// no value has been stored. + /// + /// # Panic + /// This function will panic if called again after it has resolved to either + /// data or error. + pub fn try_get(&self) -> Result, Error> { + let mut inner = self.0.inner.lock(); + inner.try_get() + } /// Return a `Future` that will wait for either data to be set or an error to /// occur. /// + /// # Cancel safety + /// This method is cancel safe. + /// /// # Panic /// This function will panic if called again after it has resolved to either /// data or error. pub fn wait_async(&self) -> WaitFuture { WaitFuture(Arc::clone(&self.0)) @@ -61,34 +77,17 @@ impl Future for WaitFuture { type Output = Result>; fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll { let mut inner = self.0.inner.lock(); - match inner.state { - State::Inactive | State::Waiting => { + match inner.try_get() { + Ok(Some(v)) => Poll::Ready(Ok(v)), + Ok(None) => { inner.waker = Some(ctx.waker().clone()); Poll::Pending } - State::Data(_) => { - let State::Data(data) = - std::mem::replace(&mut inner.state, State::Finalized) - else { - panic!("Unexpected state; not State::Data()"); - }; - Poll::Ready(Ok(data)) - } - State::Err(_) => { - let State::Err(err) = - std::mem::replace(&mut inner.state, State::Finalized) - else { - panic!("Unexpected state; not State::Err()"); - }; - Poll::Ready(Err(err)) - } - State::Finalized => { - panic!("Unexpected state"); - } + Err(e) => Poll::Ready(Err(e)) } } } // vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 : Index: www/changelog.md ================================================================== --- www/changelog.md +++ www/changelog.md @@ -6,10 +6,17 @@ ### Changed ### Removed + +## [0.1.1] - 2023-08-08 + +### Added + +- Add a `try_get()` as a non-blocking alternative to `wait()`. + ## [0.1.0] - 2023-07-30 - First release.