|
1 |
| -use std::any::type_name; |
2 | 1 | use std::cell::RefCell;
|
3 |
| -use std::fmt::{Debug, Display}; |
4 | 2 | use std::future::Future;
|
5 | 3 | use std::marker::PhantomData;
|
6 | 4 | use std::pin::Pin;
|
7 |
| -use std::sync::{Arc, Mutex}; |
| 5 | +use std::sync::Arc; |
8 | 6 | use std::task::{Context, Poll, Wake, Waker};
|
9 | 7 | use std::thread::{self, ThreadId};
|
10 | 8 |
|
11 |
| -use crate::builtin::{Callable, RustCallable, Signal, Variant}; |
12 |
| -use crate::classes::object::ConnectFlags; |
| 9 | +use crate::builtin::{Callable, Variant}; |
13 | 10 | use crate::classes::Os;
|
14 |
| -use crate::meta::{FromGodot, ToGodot}; |
15 |
| -use crate::obj::EngineEnum; |
| 11 | +use crate::meta::ToGodot; |
| 12 | + |
| 13 | +// ---------------------------------------------------------------------------------------------------------------------------------------------- |
| 14 | +// Public interface |
16 | 15 |
|
17 | 16 | pub fn godot_task(future: impl Future<Output = ()> + 'static) -> TaskHandle {
|
18 | 17 | let os = Os::singleton();
|
@@ -44,6 +43,9 @@ pub fn godot_task(future: impl Future<Output = ()> + 'static) -> TaskHandle {
|
44 | 43 | task_handle
|
45 | 44 | }
|
46 | 45 |
|
| 46 | +// ---------------------------------------------------------------------------------------------------------------------------------------------- |
| 47 | +// Async Runtime |
| 48 | + |
47 | 49 | thread_local! { pub(crate) static ASYNC_RUNTIME: RefCell<AsyncRuntime> = RefCell::new(AsyncRuntime::new()); }
|
48 | 50 |
|
49 | 51 | #[derive(Default)]
|
@@ -244,7 +246,7 @@ impl GodotWaker {
|
244 | 246 |
|
245 | 247 | impl Wake for GodotWaker {
|
246 | 248 | fn wake(self: std::sync::Arc<Self>) {
|
247 |
| - let callable = Callable::from_fn("GodotWaker::wake", move |_args| { |
| 249 | + let callable = Callable::from_local_fn("GodotWaker::wake", move |_args| { |
248 | 250 | let current_thread = thread::current().id();
|
249 | 251 |
|
250 | 252 | if self.thread_id != current_thread {
|
@@ -293,294 +295,3 @@ impl Wake for GodotWaker {
|
293 | 295 | callable.to_variant().call("call_deferred", &[]);
|
294 | 296 | }
|
295 | 297 | }
|
296 |
| - |
297 |
| -pub struct SignalFuture<R: FromSignalArgs> { |
298 |
| - state: Arc<Mutex<(Option<R>, Option<Waker>)>>, |
299 |
| - callable: Callable, |
300 |
| - signal: Signal, |
301 |
| -} |
302 |
| - |
303 |
| -impl<R: FromSignalArgs> SignalFuture<R> { |
304 |
| - fn new(signal: Signal) -> Self { |
305 |
| - let state = Arc::new(Mutex::new((None, Option::<Waker>::None))); |
306 |
| - let callback_state = state.clone(); |
307 |
| - |
308 |
| - // the callable currently requires that the return value is Sync + Send |
309 |
| - let callable = Callable::from_fn("async_task", move |args: &[&Variant]| { |
310 |
| - let mut lock = callback_state.lock().unwrap(); |
311 |
| - let waker = lock.1.take(); |
312 |
| - |
313 |
| - lock.0.replace(R::from_args(args)); |
314 |
| - drop(lock); |
315 |
| - |
316 |
| - if let Some(waker) = waker { |
317 |
| - waker.wake(); |
318 |
| - } |
319 |
| - |
320 |
| - Ok(Variant::nil()) |
321 |
| - }); |
322 |
| - |
323 |
| - signal.connect(callable.clone(), ConnectFlags::ONE_SHOT.ord() as i64); |
324 |
| - |
325 |
| - Self { |
326 |
| - state, |
327 |
| - callable, |
328 |
| - signal, |
329 |
| - } |
330 |
| - } |
331 |
| -} |
332 |
| - |
333 |
| -impl<R: FromSignalArgs> Future for SignalFuture<R> { |
334 |
| - type Output = R; |
335 |
| - |
336 |
| - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
337 |
| - let mut lock = self.state.lock().unwrap(); |
338 |
| - |
339 |
| - if let Some(result) = lock.0.take() { |
340 |
| - return Poll::Ready(result); |
341 |
| - } |
342 |
| - |
343 |
| - lock.1.replace(cx.waker().clone()); |
344 |
| - |
345 |
| - Poll::Pending |
346 |
| - } |
347 |
| -} |
348 |
| - |
349 |
| -impl<R: FromSignalArgs> Drop for SignalFuture<R> { |
350 |
| - fn drop(&mut self) { |
351 |
| - if !self.callable.is_valid() { |
352 |
| - return; |
353 |
| - } |
354 |
| - |
355 |
| - if self.signal.object().is_none() { |
356 |
| - return; |
357 |
| - } |
358 |
| - |
359 |
| - if self.signal.is_connected(self.callable.clone()) { |
360 |
| - self.signal.disconnect(self.callable.clone()); |
361 |
| - } |
362 |
| - } |
363 |
| -} |
364 |
| - |
365 |
| -struct GuaranteedSignalFutureWaker<R> { |
366 |
| - state: Arc<Mutex<(GuaranteedSignalFutureState<R>, Option<Waker>)>>, |
367 |
| -} |
368 |
| - |
369 |
| -impl<R> Clone for GuaranteedSignalFutureWaker<R> { |
370 |
| - fn clone(&self) -> Self { |
371 |
| - Self { |
372 |
| - state: self.state.clone(), |
373 |
| - } |
374 |
| - } |
375 |
| -} |
376 |
| - |
377 |
| -impl<R> GuaranteedSignalFutureWaker<R> { |
378 |
| - fn new(state: Arc<Mutex<(GuaranteedSignalFutureState<R>, Option<Waker>)>>) -> Self { |
379 |
| - Self { state } |
380 |
| - } |
381 |
| -} |
382 |
| - |
383 |
| -impl<R> std::hash::Hash for GuaranteedSignalFutureWaker<R> { |
384 |
| - fn hash<H: std::hash::Hasher>(&self, state: &mut H) { |
385 |
| - state.write_usize(Arc::as_ptr(&self.state) as usize); |
386 |
| - } |
387 |
| -} |
388 |
| - |
389 |
| -impl<R> PartialEq for GuaranteedSignalFutureWaker<R> { |
390 |
| - fn eq(&self, other: &Self) -> bool { |
391 |
| - Arc::ptr_eq(&self.state, &other.state) |
392 |
| - } |
393 |
| -} |
394 |
| - |
395 |
| -impl<R: FromSignalArgs> RustCallable for GuaranteedSignalFutureWaker<R> { |
396 |
| - fn invoke(&mut self, args: &[&Variant]) -> Result<Variant, ()> { |
397 |
| - let mut lock = self.state.lock().unwrap(); |
398 |
| - let waker = lock.1.take(); |
399 |
| - |
400 |
| - lock.0 = GuaranteedSignalFutureState::Ready(R::from_args(args)); |
401 |
| - drop(lock); |
402 |
| - |
403 |
| - if let Some(waker) = waker { |
404 |
| - waker.wake(); |
405 |
| - } |
406 |
| - |
407 |
| - Ok(Variant::nil()) |
408 |
| - } |
409 |
| -} |
410 |
| - |
411 |
| -impl<R> Display for GuaranteedSignalFutureWaker<R> { |
412 |
| - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
413 |
| - write!(f, "SafeCallable::<{}>", type_name::<R>()) |
414 |
| - } |
415 |
| -} |
416 |
| - |
417 |
| -impl<R> Drop for GuaranteedSignalFutureWaker<R> { |
418 |
| - fn drop(&mut self) { |
419 |
| - let mut lock = self.state.lock().unwrap(); |
420 |
| - |
421 |
| - if !matches!(lock.0, GuaranteedSignalFutureState::Pending) { |
422 |
| - return; |
423 |
| - } |
424 |
| - |
425 |
| - lock.0 = GuaranteedSignalFutureState::Dead; |
426 |
| - |
427 |
| - if let Some(ref waker) = lock.1 { |
428 |
| - waker.wake_by_ref(); |
429 |
| - } |
430 |
| - } |
431 |
| -} |
432 |
| - |
433 |
| -#[derive(Default)] |
434 |
| -enum GuaranteedSignalFutureState<T> { |
435 |
| - #[default] |
436 |
| - Pending, |
437 |
| - Ready(T), |
438 |
| - Dead, |
439 |
| - Dropped, |
440 |
| -} |
441 |
| - |
442 |
| -impl<T> GuaranteedSignalFutureState<T> { |
443 |
| - fn take(&mut self) -> Self { |
444 |
| - let new_value = match self { |
445 |
| - Self::Pending => Self::Pending, |
446 |
| - Self::Ready(_) | Self::Dead => Self::Dead, |
447 |
| - Self::Dropped => Self::Dropped, |
448 |
| - }; |
449 |
| - |
450 |
| - std::mem::replace(self, new_value) |
451 |
| - } |
452 |
| -} |
453 |
| - |
454 |
| -pub struct GuaranteedSignalFuture<R: FromSignalArgs> { |
455 |
| - state: Arc<Mutex<(GuaranteedSignalFutureState<R>, Option<Waker>)>>, |
456 |
| - callable: GuaranteedSignalFutureWaker<R>, |
457 |
| - signal: Signal, |
458 |
| -} |
459 |
| - |
460 |
| -impl<R: FromSignalArgs + Debug> GuaranteedSignalFuture<R> { |
461 |
| - fn new(signal: Signal) -> Self { |
462 |
| - let state = Arc::new(Mutex::new(( |
463 |
| - GuaranteedSignalFutureState::Pending, |
464 |
| - Option::<Waker>::None, |
465 |
| - ))); |
466 |
| - |
467 |
| - // the callable currently requires that the return value is Sync + Send |
468 |
| - let callable = GuaranteedSignalFutureWaker::new(state.clone()); |
469 |
| - |
470 |
| - signal.connect( |
471 |
| - Callable::from_custom(callable.clone()), |
472 |
| - ConnectFlags::ONE_SHOT.ord() as i64, |
473 |
| - ); |
474 |
| - |
475 |
| - Self { |
476 |
| - state, |
477 |
| - callable, |
478 |
| - signal, |
479 |
| - } |
480 |
| - } |
481 |
| -} |
482 |
| - |
483 |
| -impl<R: FromSignalArgs> Future for GuaranteedSignalFuture<R> { |
484 |
| - type Output = Option<R>; |
485 |
| - |
486 |
| - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
487 |
| - let mut lock = self.state.lock().unwrap(); |
488 |
| - |
489 |
| - lock.1.replace(cx.waker().clone()); |
490 |
| - |
491 |
| - let value = lock.0.take(); |
492 |
| - |
493 |
| - match value { |
494 |
| - GuaranteedSignalFutureState::Pending => Poll::Pending, |
495 |
| - GuaranteedSignalFutureState::Dropped => unreachable!(), |
496 |
| - GuaranteedSignalFutureState::Dead => Poll::Ready(None), |
497 |
| - GuaranteedSignalFutureState::Ready(value) => Poll::Ready(Some(value)), |
498 |
| - } |
499 |
| - } |
500 |
| -} |
501 |
| - |
502 |
| -impl<R: FromSignalArgs> Drop for GuaranteedSignalFuture<R> { |
503 |
| - fn drop(&mut self) { |
504 |
| - if self.signal.object().is_none() { |
505 |
| - return; |
506 |
| - } |
507 |
| - |
508 |
| - self.state.lock().unwrap().0 = GuaranteedSignalFutureState::Dropped; |
509 |
| - |
510 |
| - let gd_callable = Callable::from_custom(self.callable.clone()); |
511 |
| - |
512 |
| - if self.signal.is_connected(gd_callable.clone()) { |
513 |
| - self.signal.disconnect(gd_callable); |
514 |
| - } |
515 |
| - } |
516 |
| -} |
517 |
| - |
518 |
| -pub trait FromSignalArgs: Sync + Send + 'static { |
519 |
| - fn from_args(args: &[&Variant]) -> Self; |
520 |
| -} |
521 |
| - |
522 |
| -impl<R: FromGodot + Sync + Send + 'static> FromSignalArgs for R { |
523 |
| - fn from_args(args: &[&Variant]) -> Self { |
524 |
| - args.first() |
525 |
| - .map(|arg| (*arg).to_owned()) |
526 |
| - .unwrap_or_default() |
527 |
| - .to() |
528 |
| - } |
529 |
| -} |
530 |
| - |
531 |
| -// more of these should be generated via macro to support more than two signal arguments |
532 |
| -impl<R1: FromGodot + Sync + Send + 'static, R2: FromGodot + Sync + Send + 'static> FromSignalArgs |
533 |
| - for (R1, R2) |
534 |
| -{ |
535 |
| - fn from_args(args: &[&Variant]) -> Self { |
536 |
| - (args[0].to(), args[0].to()) |
537 |
| - } |
538 |
| -} |
539 |
| - |
540 |
| -// Signal should implement IntoFuture for convenience. Keeping ToSignalFuture around might still be desirable, though. It allows to reuse i |
541 |
| -// the same signal instance multiple times. |
542 |
| -pub trait ToSignalFuture<R: FromSignalArgs> { |
543 |
| - fn to_future(&self) -> SignalFuture<R>; |
544 |
| -} |
545 |
| - |
546 |
| -impl<R: FromSignalArgs> ToSignalFuture<R> for Signal { |
547 |
| - fn to_future(&self) -> SignalFuture<R> { |
548 |
| - SignalFuture::new(self.clone()) |
549 |
| - } |
550 |
| -} |
551 |
| - |
552 |
| -pub trait ToGuaranteedSignalFuture<R: FromSignalArgs + Debug> { |
553 |
| - fn to_guaranteed_future(&self) -> GuaranteedSignalFuture<R>; |
554 |
| -} |
555 |
| - |
556 |
| -impl<R: FromSignalArgs + Debug> ToGuaranteedSignalFuture<R> for Signal { |
557 |
| - fn to_guaranteed_future(&self) -> GuaranteedSignalFuture<R> { |
558 |
| - GuaranteedSignalFuture::new(self.clone()) |
559 |
| - } |
560 |
| -} |
561 |
| - |
562 |
| -#[cfg(test)] |
563 |
| -mod tests { |
564 |
| - use std::{ |
565 |
| - hash::{DefaultHasher, Hash, Hasher}, |
566 |
| - sync::Arc, |
567 |
| - }; |
568 |
| - |
569 |
| - use super::GuaranteedSignalFutureWaker; |
570 |
| - |
571 |
| - #[test] |
572 |
| - fn guaranteed_future_waker_cloned_hash() { |
573 |
| - let waker_a = GuaranteedSignalFutureWaker::<u8>::new(Arc::default()); |
574 |
| - let waker_b = waker_a.clone(); |
575 |
| - |
576 |
| - let mut hasher = DefaultHasher::new(); |
577 |
| - waker_a.hash(&mut hasher); |
578 |
| - let hash_a = hasher.finish(); |
579 |
| - |
580 |
| - let mut hasher = DefaultHasher::new(); |
581 |
| - waker_b.hash(&mut hasher); |
582 |
| - let hash_b = hasher.finish(); |
583 |
| - |
584 |
| - assert_eq!(hash_a, hash_b); |
585 |
| - } |
586 |
| -} |
0 commit comments