11//! Access the [`World`]s resources from async futures.
2+ use std:: { any:: Any , sync:: Arc } ;
3+
24use moongraph:: { Edges , Function , GraphError , Node , Resource , TypeKey , TypeMap } ;
35
6+ use crate :: { world:: LazyOp , World } ;
7+
48pub ( crate ) struct Request {
59 pub ( crate ) reads : Vec < TypeKey > ,
610 pub ( crate ) writes : Vec < TypeKey > ,
@@ -45,6 +49,7 @@ pub struct Facade {
4549 // Unbounded. Sending a request from the facade will not yield the future.
4650 // In other words, it will not cause the async to stop at an await point.
4751 pub ( crate ) request_tx : async_channel:: Sender < Request > ,
52+ pub ( crate ) lazy_tx : async_channel:: Sender < LazyOp > ,
4853}
4954
5055impl Facade {
@@ -71,7 +76,7 @@ impl Facade {
7176 writes,
7277 moves,
7378 prepare : |resources : & mut TypeMap | {
74- log:: trace !(
79+ log:: debug !(
7580 "request got resources - constructing {}" ,
7681 std:: any:: type_name:: <D >( )
7782 ) ;
@@ -87,14 +92,41 @@ impl Facade {
8792 let box_d: Box < D > = rez. downcast ( ) . unwrap ( ) ;
8893 let d = * box_d;
8994 let t = f ( d) ;
90- log:: trace !( "request for {} done" , std:: any:: type_name:: <D >( ) ) ;
95+ log:: debug !( "request for {} done" , std:: any:: type_name:: <D >( ) ) ;
9196 Ok ( t)
9297 }
9398
9499 /// Return the total number of facades.
95100 pub fn count ( & self ) -> usize {
96101 self . request_tx . sender_count ( )
97102 }
103+
104+ pub async fn visit_world_mut < T > (
105+ & mut self ,
106+ f : impl FnOnce ( & mut World ) -> T + Send + Sync + ' static ,
107+ ) -> Result < T , GraphError >
108+ where
109+ T : Any + Send + Sync ,
110+ {
111+ let ( tx, rx) = async_channel:: bounded ( 1 ) ;
112+ // UNWRAP: safe because this channel is unbounded
113+ self . lazy_tx
114+ . try_send ( LazyOp {
115+ op : Box :: new ( |world| {
116+ let t = f ( world) ;
117+ let any_t = Arc :: new ( t) ;
118+ Ok ( any_t)
119+ } ) ,
120+ tx,
121+ } )
122+ . unwrap ( ) ;
123+ let any_t: Arc < _ > = rx. recv ( ) . await . map_err ( GraphError :: other) ?;
124+ // UNWRAP: safe because we know we will only receive the type we expect, as we packed it
125+ // in the closure above.
126+ let arc_t: Arc < T > = any_t. downcast ( ) . unwrap ( ) ;
127+ // UNWRAP: safe because we know nothing has cloned this arc
128+ Ok ( Arc :: try_unwrap ( arc_t) . unwrap_or_else ( |_| unreachable ! ( "something cloned the arc" ) ) )
129+ }
98130}
99131
100132/// A fulfillment schedule of requests for world resources,
@@ -142,6 +174,10 @@ impl<'a> FacadeSchedule<'a> {
142174 self . batches . len ( )
143175 }
144176
177+ pub fn is_empty ( & self ) -> bool {
178+ self . len ( ) == 0
179+ }
180+
145181 /// Attempt to unify resources, returning `true` if resources are unified, `false` if not.
146182 pub fn unify ( & mut self ) -> bool {
147183 self . batches . unify ( )
0 commit comments