Suspend the current fiber, storing the reason in `ConcurrentState::suspend_reason` to indicate the conditions under which it should be resumed. See the `SuspendReason` documentation for details.
(&mut self, reason: SuspendReason)
| 1949 | /// |
| 1950 | /// See the `SuspendReason` documentation for details. |
| 1951 | fn suspend(&mut self, reason: SuspendReason) -> Result<()> { |
| 1952 | log::trace!("suspend fiber: {reason:?}"); |
| 1953 | |
| 1954 | // If we're yielding or waiting on behalf of a guest thread, we'll need to |
| 1955 | // pop the call context which manages resource borrows before suspending |
| 1956 | // and then push it again once we've resumed. |
| 1957 | let task = match &reason { |
| 1958 | SuspendReason::Yielding { thread, .. } |
| 1959 | | SuspendReason::Waiting { thread, .. } |
| 1960 | | SuspendReason::ExplicitlySuspending { thread, .. } => Some(thread.task), |
| 1961 | SuspendReason::NeedWork => None, |
| 1962 | }; |
| 1963 | |
| 1964 | let old_guest_thread = if task.is_some() { |
| 1965 | self.concurrent_state_mut().current_thread |
| 1966 | } else { |
| 1967 | CurrentThread::None |
| 1968 | }; |
| 1969 | |
| 1970 | // We should not have reached here unless either there's no current |
| 1971 | // task, or the current task is permitted to block. In addition, we |
| 1972 | // special-case `thread.switch-to` and waiting for a subtask to go from |
| 1973 | // `starting` to `started`, both of which we consider non-blocking |
| 1974 | // operations despite requiring a suspend. |
| 1975 | debug_assert!( |
| 1976 | matches!( |
| 1977 | reason, |
| 1978 | SuspendReason::ExplicitlySuspending { |
| 1979 | skip_may_block_check: true, |
| 1980 | .. |
| 1981 | } | SuspendReason::Waiting { |
| 1982 | skip_may_block_check: true, |
| 1983 | .. |
| 1984 | } | SuspendReason::Yielding { |
| 1985 | skip_may_block_check: true, |
| 1986 | .. |
| 1987 | } |
| 1988 | ) || old_guest_thread |
| 1989 | .guest() |
| 1990 | .map(|thread| self.concurrent_state_mut().may_block(thread.task)) |
| 1991 | .transpose()? |
| 1992 | .unwrap_or(true) |
| 1993 | ); |
| 1994 | |
| 1995 | let suspend_reason = &mut self.concurrent_state_mut().suspend_reason; |
| 1996 | assert!(suspend_reason.is_none()); |
| 1997 | *suspend_reason = Some(reason); |
| 1998 | |
| 1999 | self.with_blocking(|_, cx| cx.suspend(StoreFiberYield::ReleaseStore))?; |
| 2000 | |
| 2001 | if task.is_some() { |
| 2002 | self.set_thread(old_guest_thread)?; |
| 2003 | } |
| 2004 | |
| 2005 | Ok(()) |
| 2006 | } |
| 2007 | |
| 2008 | fn wait_for_event(&mut self, waitable: Waitable) -> Result<()> { |
no test coverage detected