char/avril
(wip) why'd you have to go and make things so complicaaaaated?
git clone https://git.t4t.associates/char/avril
f4a0f5b
main
1use std:: cell:: RefCell ; 2use std:: collections::{ BTreeMap , HashMap , VecDeque }; 3use std:: convert:: Infallible ; 4use std:: rc:: Rc ; 5use std:: sync::{ Arc , Mutex , Weak }; 6 7use avril_core::{ Op , message, v8}; 8use tokio:: sync:: Notify ; 9 10type Id =u64 ; 11 12const MAX_ID : u64 =9_007_199_254_740_991 ; 13 14fn u64_arg < ' s , ' i >( 15scope : & mut v8:: PinScope < ' s , ' i >, 16value : v8:: Local < ' s , v8:: Value >, 17) ->Option < u64 > { 18match avril_core:: serde_v8:: from_v8 ::< u64 >( scope, value) { 19Ok ( id) =>Some ( id), 20Err ( error) =>{ 21let message = v8:: String :: new ( scope, & error. to_string ()) ?; 22 scope. throw_exception ( v8:: Exception :: type_error ( scope, message)); 23None 24} 25} 26} 27 28fn port_id < ' s , ' i >( 29scope : & mut v8:: PinScope < ' s , ' i >, 30value : v8:: Local < ' s , v8:: Value >, 31) ->Option < Id > { 32u64_arg ( scope, value) 33} 34 35struct Packet { 36message : message:: Message , 37_transfers : Vec < Arc < Endpoint >>, 38} 39 40# [ derive ( Default )] 41struct State { 42queue : VecDeque < Packet >, 43epoch : u64 , 44closed : bool , 45} 46 47pub struct Endpoint { 48id : Id , 49broker : Weak < Broker >, 50peer : Mutex < Weak < Endpoint >>, 51state : Mutex < State >, 52notify : Notify , 53} 54 55impl Endpoint { 56pub fn close ( & self ) { 57let mut state =self . state . lock (). unwrap (); 58 state. closed =true ; 59 state. queue . clear (); 60drop ( state); 61self . notify . notify_waiters (); 62if let Some ( peer) =self . peer . lock (). unwrap (). upgrade () { 63 peer. notify . notify_waiters (); 64} 65} 66 67pub fn id ( & self ) ->Id { 68self . id 69} 70 71pub async fn drained ( & self ) { 72loop { 73let notified =self . notify . notified (); 74 tokio:: pin!( notified); 75 notified. as_mut (). enable (); 76if self . state . lock (). unwrap (). queue . is_empty () { 77return ; 78} 79 notified. await ; 80} 81} 82 83async fn wait ( & self , epoch : u64 ) ->bool { 84loop { 85let notified =self . notify . notified (); 86 tokio:: pin!( notified); 87 notified. as_mut (). enable (); 88let peer_closed =self 89. peer 90. lock () 91. unwrap () 92. upgrade () 93. is_none_or ( |peer| peer. state . lock (). unwrap (). closed ); 94{ 95let state =self . state . lock (). unwrap (); 96if state. closed || state. epoch != epoch{ 97return false ; 98} 99if !state. queue . is_empty () { 100return true ; 101} 102if peer_closed{ 103return false ; 104} 105} 106 notified. await ; 107} 108} 109} 110 111impl Drop for Endpoint { 112fn drop ( & mut self ) { 113if let Some ( broker) =self . broker . upgrade () 114 &&let Ok ( mut registry) = broker. 0 . lock () 115{ 116 registry. ports . remove ( & self . id ); 117} 118if let Some ( peer) =self . peer . get_mut (). unwrap (). upgrade () { 119 peer. notify . notify_waiters (); 120} 121} 122} 123 124# [ derive ( Default )] 125struct Registry { 126next : Id , 127ports : HashMap < Id , Weak < Endpoint >>, 128broadcasts : HashMap < Vec < u16 >, BTreeMap < Id , Weak < Endpoint >>>, 129} 130 131# [ derive ( Default )] 132pub struct Broker ( Mutex < Registry >); 133 134impl Broker { 135pub fn pair ( self : & Arc < Self >) -> std:: io:: Result <( Arc < Endpoint >, Arc < Endpoint >)> { 136let mut registry =self . 0 . lock (). unwrap (); 137let id = registry. next ; 138if id >MAX_ID -1 { 139return Err ( std:: io:: Error :: other ( "MessagePort ID space exhausted" )); 140} 141 registry. next = id +2 ; 142let first =Arc :: new ( Endpoint { 143 id, 144broker : Arc :: downgrade ( self ), 145peer : Mutex :: default (), 146state : Mutex :: default (), 147notify : Notify :: new (), 148}); 149let second =Arc :: new ( Endpoint { 150id : id +1 , 151broker : Arc :: downgrade ( self ), 152peer : Mutex :: default (), 153state : Mutex :: default (), 154notify : Notify :: new (), 155}); 156* first. peer . lock (). unwrap () =Arc :: downgrade ( & second); 157* second. peer . lock (). unwrap () =Arc :: downgrade ( & first); 158 registry. ports . insert ( id, Arc :: downgrade ( & first)); 159 registry. ports . insert ( id +1 , Arc :: downgrade ( & second)); 160Ok (( first, second)) 161} 162 163pub fn endpoint ( & self , id : Id ) ->Option < Arc < Endpoint >> { 164self . 0 165. lock () 166. unwrap () 167. ports 168. get ( & id) 169. and_then ( Weak :: upgrade) 170} 171} 172 173struct Subscription { 174id : Id , 175name : Vec < u16 >, 176sender : Arc < Endpoint >, 177broker : Arc < Broker >, 178} 179 180impl Drop for Subscription { 181fn drop ( & mut self ) { 182self . sender . close (); 183let Ok ( mut registry) =self . broker . 0 . lock () else { 184return ; 185}; 186if let Some ( group) = registry. broadcasts . get_mut ( & self . name ) { 187 group. remove ( & self . id ); 188if group. is_empty () { 189 registry. broadcasts . remove ( & self . name ); 190} 191} 192} 193} 194 195struct Ports { 196broker : Arc < Broker >, 197owned : RefCell < HashMap < Id , Arc < Endpoint >>>, 198moving : RefCell < Vec < Arc < Endpoint >>>, 199broadcasts : RefCell < HashMap < Id , Subscription >>, 200} 201 202impl Ports { 203fn resolve ( & self , id : Id ) ->Option < Arc < Endpoint >> { 204if let Some ( endpoint) =self . owned . borrow (). get ( & id). cloned () { 205return Some ( endpoint); 206} 207self . broker . endpoint ( id) 208} 209} 210 211impl Drop for Ports { 212fn drop ( & mut self ) { 213for ( _, endpoint) in self . owned . get_mut (). drain () { 214 endpoint. close (); 215} 216} 217} 218 219pub fn ops ( broker : Arc < Broker >) ->Vec < Op > { 220let ports =Rc :: new ( Ports { 221broker : broker. clone (), 222owned : RefCell :: default (), 223moving : RefCell :: default (), 224broadcasts : RefCell :: default (), 225}); 226vec! [ 227Op :: raw ( "op_broadcast_open" , { 228let ports = ports. clone (); 229move |scope, args|{ 230let value = v8:: Local ::< v8:: String >:: try_from ( args. get ( 0 )). ok () ?; 231let mut name =vec! [ 0 ; value. length ()]; 232 value. write_v2 ( scope, 0 , & mut name, v8:: WriteFlags :: empty ()); 233let ( sender, receiver) =match ports. broker . pair () { 234Ok ( pair) => pair, 235Err ( error) =>{ 236let message = v8:: String :: new ( scope, & error. to_string ()) ?; 237 scope. throw_exception ( v8:: Exception :: error ( scope, message)); 238return None ; 239} 240}; 241let id = receiver. id ; 242 ports. owned . borrow_mut (). insert ( id, receiver. clone ()); 243 ports 244. broker 245. 0 246. lock () 247. unwrap () 248. broadcasts 249. entry ( name. clone ()) 250. or_default () 251. insert ( id, Arc :: downgrade ( & receiver)); 252 ports. broadcasts . borrow_mut (). insert ( 253 id, 254Subscription { 255 id, 256 name, 257 sender, 258broker : ports. broker . clone (), 259}, 260); 261Some ( v8:: Number :: new ( scope, idas f64 ). into ()) 262} 263}), 264Op :: new ( "op_broadcast_close" , { 265let ports = ports. clone (); 266move |id : Id |{ 267 ports. broadcasts . borrow_mut (). remove ( & id); 268Ok ::< _ , Infallible >(()) 269} 270}), 271Op :: raw ( "op_broadcast_send" , { 272let ports = ports. clone (); 273move |scope, args|{ 274let id =port_id ( scope, args. get ( 0 )) ?; 275let name = ports. broadcasts . borrow (). get ( & id) ?. name . clone (); 276let transfer = v8:: Array :: new ( scope, 0 ); 277let callbacks =[ 278 v8:: Local ::< v8:: Function >:: try_from ( args. get ( 2 )). ok () ?, 279 v8:: Local ::< v8:: Function >:: try_from ( args. get ( 3 )). ok () ?, 280 v8:: Local ::< v8:: Function >:: try_from ( args. get ( 4 )). ok () ?, 281 v8:: Local ::< v8:: Function >:: try_from ( args. get ( 5 )). ok () ?, 282 v8:: Local ::< v8:: Function >:: try_from ( args. get ( 6 )). ok () ?, 283]; 284let message = message:: serialize ( scope, args. get ( 1 ), transfer, callbacks) ?; 285let recipients: Vec < _ > = ports 286. broker 287. 0 288. lock () 289. unwrap () 290. broadcasts 291. get ( & name) 292. into_iter () 293. flat_map ( |group| group. iter ()) 294. filter ( |( recipient, _) |** recipient != id) 295. filter_map ( |( _, endpoint) | endpoint. upgrade ()) 296. collect (); 297for endpointin recipients{ 298let mut state = endpoint. state . lock (). unwrap (); 299if !state. closed { 300 state. queue . push_back ( Packet { 301message : message 302. try_clone () 303. expect ( "Broadcast messages have no transfers" ), 304_transfers : Vec :: new (), 305}); 306} 307drop ( state); 308 endpoint. notify . notify_waiters (); 309} 310Some ( v8:: undefined ( scope). into ()) 311} 312}), 313Op :: new ( "op_port_pair" , { 314let ports = ports. clone (); 315move |(): () |{ 316let ( a, b) = ports. broker . pair () ?; 317 ports 318. owned 319. borrow_mut () 320. extend ([( a. id , a. clone ()), ( b. id , b. clone ())]); 321Ok ::< _ , std:: io:: Error >(( a. id , b. id )) 322} 323}), 324Op :: new ( "op_port_adopt" , { 325let ports = ports. clone (); 326move |id : Id |{ 327let endpoint = ports 328. resolve ( id) 329. ok_or_else ( || std:: io:: Error :: other ( "MessagePort endpoint is closed" )) ?; 330 ports. owned . borrow_mut (). insert ( id, endpoint. clone ()); 331 ports. moving . borrow_mut (). retain ( |port| port. id != id); 332Ok ::< _ , std:: io:: Error >( endpoint. state . lock (). unwrap (). epoch ) 333} 334}), 335Op :: new ( "op_port_move" , { 336let ports = ports. clone (); 337move |id : Id |{ 338let endpoint = ports 339. owned 340. borrow_mut () 341. remove ( & id) 342. ok_or_else ( || std:: io:: Error :: other ( "Transferred port is not owned" )) ?; 343 endpoint. state . lock (). unwrap (). epoch +=1 ; 344 endpoint. notify . notify_waiters (); 345 ports. moving . borrow_mut (). push ( endpoint); 346Ok ::< _ , std:: io:: Error >(()) 347} 348}), 349Op :: new ( "op_port_close" , { 350let ports = ports. clone (); 351move |id : Id |{ 352if let Some ( endpoint) = ports. owned . borrow_mut (). remove ( & id) { 353 endpoint. close (); 354} 355Ok ::< _ , Infallible >(()) 356} 357}), 358Op :: new ( "op_port_peer" , { 359let ports = ports. clone (); 360move |id : Id |{ 361Ok ::< _ , Infallible >( ports. resolve ( id). and_then ( |endpoint|{ 362 endpoint. peer . lock (). unwrap (). upgrade (). map ( |peer| peer. id ) 363})) 364} 365}), 366Op :: asynchronous_unreferenced ( "op_port_wait" , { 367let ports = ports. clone (); 368move |( id, epoch): ( Id , u64 ) |{ 369let endpoint = ports. resolve ( id); 370async move { 371Ok ::< _ , Infallible >( match endpoint{ 372Some ( endpoint) => endpoint. wait ( epoch). await , 373None =>false , 374}) 375} 376} 377}), 378Op :: asynchronous ( "op_port_wait_ref" , { 379let ports = ports. clone (); 380move |( id, epoch): ( Id , u64 ) |{ 381let endpoint = ports. resolve ( id); 382async move { 383Ok ::< _ , Infallible >( match endpoint{ 384Some ( endpoint) => endpoint. wait ( epoch). await , 385None =>false , 386}) 387} 388} 389}), 390Op :: raw ( "op_port_send" , { 391let ports = ports. clone (); 392move |scope, args|{ 393let id_value = args. get ( 0 ); 394let id =if id_value. is_null () { 395None 396} else { 397Some ( port_id ( scope, id_value) ?) 398}; 399let value = args. get ( 1 ); 400let transfer = v8:: Local ::< v8:: Array >:: try_from ( args. get ( 2 )). ok () ?; 401let callbacks =[ 402 v8:: Local ::< v8:: Function >:: try_from ( args. get ( 3 )). ok () ?, 403 v8:: Local ::< v8:: Function >:: try_from ( args. get ( 4 )). ok () ?, 404 v8:: Local ::< v8:: Function >:: try_from ( args. get ( 5 )). ok () ?, 405 v8:: Local ::< v8:: Function >:: try_from ( args. get ( 6 )). ok () ?, 406 v8:: Local ::< v8:: Function >:: try_from ( args. get ( 7 )). ok () ?, 407]; 408let serialized = message:: serialize ( scope, value, transfer, callbacks); 409let transfers = std:: mem:: take ( & mut * ports. moving . borrow_mut ()); 410let packet =Packet { 411message : serialized?, 412_transfers : transfers, 413}; 414let endpoint = id. and_then ( |id| ports. resolve ( id)); 415if let Some ( endpoint) = endpoint 416 && !endpoint. state . lock (). unwrap (). closed 417 &&let Some ( peer) = endpoint. peer . lock (). unwrap (). upgrade () 418{ 419let mut state = peer. state . lock (). unwrap (); 420if !state. closed { 421 state. queue . push_back ( packet); 422} 423drop ( state); 424 peer. notify . notify_waiters (); 425} 426Some ( v8:: undefined ( scope). into ()) 427} 428}), 429Op :: raw ( "op_port_take" , { 430let ports = ports. clone (); 431move |scope, args|{ 432let id =port_id ( scope, args. get ( 0 )) ?; 433let epoch =u64_arg ( scope, args. get ( 1 )) ?; 434let host = v8:: Local ::< v8:: Function >:: try_from ( args. get ( 2 )). ok () ?; 435let error = v8:: Local ::< v8:: Function >:: try_from ( args. get ( 3 )). ok () ?; 436let Some ( endpoint) = ports. resolve ( id) else { 437return Some ( v8:: null ( scope). into ()); 438}; 439let mut state = endpoint. state . lock (). unwrap (); 440if state. epoch != epoch || state. closed { 441return Some ( v8:: null ( scope). into ()); 442} 443let packet = state. queue . pop_front (); 444drop ( state); 445 endpoint. notify . notify_waiters (); 446match packet{ 447Some ( packet) => message:: deserialize ( scope, packet. message , host, error), 448None =>Some ( v8:: null ( scope). into ()), 449} 450} 451}), 452] 453}