Skip to content

Instantly share code, notes, and snippets.

@WhiteGrouse
Last active September 21, 2020 17:44
Show Gist options
  • Select an option

  • Save WhiteGrouse/9e6c93bba0e0934e34cef39ed70c20de to your computer and use it in GitHub Desktop.

Select an option

Save WhiteGrouse/9e6c93bba0e0934e34cef39ed70c20de to your computer and use it in GitHub Desktop.
切断通知付き、仮想コネクション
use async_std::prelude::FutureExt;
use async_std::net::SocketAddr;
use async_std::sync::{channel, Sender, Receiver};
use async_std::task;
const QUEUE_SIZE: usize = 128;
pub struct Communicator<T> {
tx_packet: Sender<T>,
rx_packet: Receiver<T>,
tx_disconnect: Sender<()>,
rx_disconnect: Receiver<()>,
}
pub struct DisconnectedError;
enum Event<T> {
Disconnect,
Sent,
Received(T),
}
impl<T> Communicator<T> {
pub fn pair() -> (Communicator<T>, Communicator<T>) {
let (tx_packet_a, rx_packet_b) = channel(QUEUE_SIZE);
let (tx_packet_b, rx_packet_a) = channel(QUEUE_SIZE);
let (tx_disconnect_a, rx_disconnect_b) = channel(1);
let (tx_disconnect_b, rx_disconnect_a) = channel(1);
let communicator_a = Communicator {
tx_packet: tx_packet_a,
rx_packet: rx_packet_a,
tx_disconnect: tx_disconnect_a,
rx_disconnect: rx_disconnect_a,
};
let communicator_b = Communicator {
tx_packet: tx_packet_b,
rx_packet: rx_packet_b,
tx_disconnect: tx_disconnect_b,
rx_disconnect: rx_disconnect_b,
};
(communicator_a, communicator_b)
}
pub fn send(&self, packet: T) -> Result<(), DisconnectedError> {
task::block_on(async {
match self.send_packet(packet).race(self.recv_disconnect()).await {
Event::<T>::Sent => Ok(()),
_ => Err(DisconnectedError),
}
})
}
pub fn recv(&self) -> Result<T, DisconnectedError> {
task::block_on(async {
match self.recv_packet().race(self.recv_disconnect()).await {
Event::Received(packet) => Ok(packet),
_ => Err(DisconnectedError),
}
})
}
pub fn disconnect(self) {
task::block_on(self.tx_disconnect.send(()));
}
async fn send_packet(&self, packet: T) -> Event<T> {
self.tx_packet.send(packet).await;
Event::<T>::Sent
}
async fn recv_packet(&self) -> Event<T> {
match self.rx_packet.recv().await {
Ok(packet) => Event::Received(packet),
Err(_) => Event::Disconnect,
}
}
async fn recv_disconnect(&self) -> Event<T> {
let _ = self.rx_disconnect.recv().await;
Event::Disconnect
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment