(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
op: impl FnOnce(&mut S) -> p2::StreamResult<T>,
)
| 259 | S: SharedHandleReady, |
| 260 | { |
| 261 | fn poll<T>( |
| 262 | mut self: Pin<&mut Self>, |
| 263 | cx: &mut Context<'_>, |
| 264 | op: impl FnOnce(&mut S) -> p2::StreamResult<T>, |
| 265 | ) -> Poll<Option<io::Result<T>>> { |
| 266 | // If we don't currently have the lock on this handle, initiate the |
| 267 | // lock acquisition. |
| 268 | if let StdioHandle::Ready(lock) = &*self { |
| 269 | self.set(StdioHandle::Locking(Box::new(lock.clone().lock_owned()))); |
| 270 | } |
| 271 | |
| 272 | // If we're in the process of locking this handle, wait for that to |
| 273 | // finish. |
| 274 | if let Some(lock) = self.as_mut().as_locking() { |
| 275 | let guard = ready!(lock.poll(cx)); |
| 276 | self.set(StdioHandle::Locked(guard)); |
| 277 | } |
| 278 | |
| 279 | let mut guard = match self.as_mut().take_guard() { |
| 280 | Some(guard) => guard, |
| 281 | // If the guard can't be acquired that means that this stream is |
| 282 | // closed, so return that we're ready without filling in data. |
| 283 | None => return Poll::Ready(None), |
| 284 | }; |
| 285 | |
| 286 | // Wait for our locked stream to be ready, resetting to the "locked" |
| 287 | // state if it's not quite ready yet. |
| 288 | match guard.poll_ready(cx) { |
| 289 | Poll::Ready(()) => {} |
| 290 | |
| 291 | // If the read isn't ready yet then restore our "locked" state |
| 292 | // since we haven't finished, then return pending. |
| 293 | Poll::Pending => { |
| 294 | self.set(StdioHandle::Locked(guard)); |
| 295 | return Poll::Pending; |
| 296 | } |
| 297 | } |
| 298 | |
| 299 | // Perform the I/O and delegate on the result. |
| 300 | match op(&mut guard) { |
| 301 | // The I/O succeeded so relinquish the lock on this stream by |
| 302 | // transitioning back to the "Ready" state. |
| 303 | Ok(result) => { |
| 304 | self.set(StdioHandle::Ready(OwnedMutexGuard::mutex(&guard).clone())); |
| 305 | Poll::Ready(Some(Ok(result))) |
| 306 | } |
| 307 | |
| 308 | // The stream is closed, and `take_guard` above already set the |
| 309 | // closed state, so return nothing indicating the closure. |
| 310 | Err(p2::StreamError::Closed) => Poll::Ready(None), |
| 311 | |
| 312 | // The stream failed so propagate the error. Errors should only |
| 313 | // come from the underlying I/O object and thus should cast |
| 314 | // successfully. Additionally `take_guard` replaced our state |
| 315 | // with "closed" above which is the desired state at this point. |
| 316 | Err(p2::StreamError::LastOperationFailed(e)) => { |
| 317 | Poll::Ready(Some(Err(e.downcast().unwrap()))) |
| 318 | } |
no test coverage detected