Last active
September 21, 2020 17:44
-
-
Save WhiteGrouse/9e6c93bba0e0934e34cef39ed70c20de to your computer and use it in GitHub Desktop.
切断通知付き、仮想コネクション
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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