1- use std:: { collections:: HashMap , sync:: Arc } ;
1+ use std:: { collections:: HashMap , marker :: PhantomData , sync:: Arc } ;
22
33use futures:: future:: join_all;
44use tokio:: sync:: { broadcast, mpsc, Mutex } ;
@@ -141,7 +141,6 @@ impl InChannel {
141141 } ,
142142 }
143143 }
144-
145144 /// Close the channel and drop the messages inside.
146145 fn close ( & mut self ) {
147146 match self {
@@ -152,6 +151,100 @@ impl InChannel {
152151 }
153152}
154153
154+ /// # Typed Input Channels
155+ /// A hash-table mapping `NodeId` to `InChannel`. This provides type-safe channel communication
156+ /// between nodes.
157+ #[ derive( Default ) ]
158+ pub struct TypedInChannels < T : Send + Sync + ' static > (
159+ pub ( crate ) HashMap < NodeId , Arc < Mutex < InChannel > > > ,
160+ // maker for type T
161+ pub ( crate ) PhantomData < T > ,
162+ ) ;
163+
164+ impl < T : Send + Sync + ' static > TypedInChannels < T > {
165+ /// Perform a blocking receive on the incoming channel from `NodeId`.
166+ pub fn blocking_recv_from ( & mut self , id : & NodeId ) -> Result < Option < Arc < T > > , RecvErr > {
167+ match self . get ( id) {
168+ Some ( channel) => {
169+ let content: Content = channel. blocking_lock ( ) . blocking_recv ( ) ?;
170+ Ok ( content. into_inner ( ) )
171+ }
172+ None => Err ( RecvErr :: NoSuchChannel ) ,
173+ }
174+ }
175+
176+ /// Perform a asynchronous receive on the incoming channel from `NodeId`.
177+ pub async fn recv_from ( & mut self , id : & NodeId ) -> Result < Option < Arc < T > > , RecvErr > {
178+ match self . get ( id) {
179+ Some ( channel) => {
180+ let content: Content = channel. lock ( ) . await . recv ( ) . await ?;
181+ Ok ( content. into_inner ( ) )
182+ }
183+ None => Err ( RecvErr :: NoSuchChannel ) ,
184+ }
185+ }
186+
187+ /// Calls `blocking_recv` for all the [`InChannel`]s, and applies transformation `f` to
188+ /// the return values of the call.
189+ pub fn blocking_map < F , U > ( & mut self , mut f : F ) -> Vec < U >
190+ where
191+ F : FnMut ( Result < Option < Arc < T > > , RecvErr > ) -> U ,
192+ {
193+ self . keys ( )
194+ . into_iter ( )
195+ . map ( |id| f ( self . blocking_recv_from ( & id) ) )
196+ . collect ( )
197+ }
198+
199+ /// Calls `recv` for all the [`InChannel`]s, and applies transformation `f` to
200+ /// the return values of the call asynchronously.
201+ pub async fn map < F , U > ( & mut self , mut f : F ) -> Vec < U >
202+ where
203+ F : FnMut ( Result < Option < Arc < T > > , RecvErr > ) -> U ,
204+ {
205+ let futures = self . 0 . iter_mut ( ) . map ( |( _, c) | async {
206+ let content: Content = c. lock ( ) . await . recv ( ) . await ?;
207+ Ok ( content. into_inner ( ) )
208+ } ) ;
209+ join_all ( futures) . await . into_iter ( ) . map ( |x| f ( x) ) . collect ( )
210+ }
211+
212+ /// Close the channel by the given `NodeId` asynchronously, and remove the channel in this map.
213+ pub async fn close_async ( & mut self , id : & NodeId ) {
214+ if let Some ( c) = self . get ( id) {
215+ c. lock ( ) . await . close ( ) ;
216+ self . 0 . remove ( id) ;
217+ }
218+ }
219+
220+ /// Close the channel by the given `NodeId`, and remove the channel in this map.
221+ pub fn close ( & mut self , id : & NodeId ) {
222+ if let Some ( c) = self . get ( id) {
223+ c. blocking_lock ( ) . close ( ) ;
224+ self . 0 . remove ( id) ;
225+ }
226+ }
227+
228+ pub ( crate ) fn insert ( & mut self , node_id : NodeId , channel : Arc < Mutex < InChannel > > ) {
229+ self . 0 . insert ( node_id, channel) ;
230+ }
231+
232+ pub ( crate ) fn close_all ( & mut self ) {
233+ self . 0 . values_mut ( ) . for_each ( |c| c. blocking_lock ( ) . close ( ) ) ;
234+ }
235+
236+ fn get ( & self , id : & NodeId ) -> Option < Arc < Mutex < InChannel > > > {
237+ match self . 0 . get ( id) {
238+ Some ( c) => Some ( c. clone ( ) ) ,
239+ None => None ,
240+ }
241+ }
242+
243+ fn keys ( & self ) -> Vec < NodeId > {
244+ self . 0 . keys ( ) . map ( |x| * x) . collect ( )
245+ }
246+ }
247+
155248/// # Input Channel Error Types
156249/// - NoSuchChannel: try to get a channel with an invalid `NodeId`.
157250/// - Closed: the channel to receive messages from is closed and empty already.
0 commit comments