use super::H2Connection;
use std::sync::atomic::Ordering;
#[cfg(feature = "unstable")]
use {
crate::h2::H2Settings,
event_listener::EventListener,
std::{
future::Future,
pin::Pin,
task::{Context, Poll},
},
};
#[cfg(feature = "unstable")]
#[must_use = "futures do nothing unless awaited"]
#[derive(Debug)]
pub struct PeerSettings<'a>(
pub(super) &'a H2Connection,
pub(super) Option<EventListener>,
);
#[cfg(feature = "unstable")]
impl Future for PeerSettings<'_> {
type Output = Option<H2Settings>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let Self(connection, listener) = &mut *self;
loop {
if let Some(snapshot) = connection.peer_settings_snapshot() {
return Poll::Ready(Some(snapshot));
}
if !connection.swansong.state().is_running() {
return Poll::Ready(None);
}
let l = if let Some(l) = listener {
l
} else {
let l = listener.insert(connection.peer_settings_event.listen());
if let Some(snapshot) = connection.peer_settings_snapshot() {
return Poll::Ready(Some(snapshot));
}
if !connection.swansong.state().is_running() {
return Poll::Ready(None);
}
l
};
std::task::ready!(Pin::new(l).poll(cx));
*listener = None;
}
}
}
impl H2Connection {
#[cfg(feature = "unstable")]
pub fn peer_settings(&self) -> PeerSettings<'_> {
PeerSettings(self, None)
}
#[cfg(feature = "unstable")]
pub fn peer_settings_snapshot(&self) -> Option<H2Settings> {
self.peer_settings_received
.load(Ordering::Acquire)
.then(|| *self.current_peer_settings())
}
pub(in crate::h2) fn note_peer_settings(&self) {
self.peer_settings_received.store(true, Ordering::Release);
self.peer_settings_event.notify(usize::MAX);
}
pub(in crate::h2) fn wake_peer_settings_waiters(&self) {
self.peer_settings_event.notify(usize::MAX);
}
}