1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#![feature(macro_metavar_expr)]

use std::fmt::Display;

use static_init::dynamic;
pub use tokio::{self, spawn as _spawn};
use tokio::{macros::support::Future, runtime::Runtime};

#[dynamic]
pub static TRT: Runtime = tokio::runtime::Builder::new_multi_thread()
  .enable_all()
  .build()
  .unwrap();

pub fn bg<F, E>(future: F)
where
  E: Display,
  F: Future<Output = Result<(), E>> + Send + 'static,
{
  TRT.spawn(async move {
    if let Err(err) = future.await {
      tracing::error!("{err}");
    }
  });
}

// pub fn spawn<F>(future: F) -> JoinHandle<F::Output> ⓘ
// where
//     F: Future + Send + 'static,
//     F::Output: Send

pub async fn spawn<E, R>(
  future: impl Future<Output = Result<R, E>> + Send + 'static,
) -> Result<R, E>
where
  E: std::error::Error + std::convert::From<tokio::task::JoinError> + Send + 'static,
  R: Send + 'static,
{
  Ok(_spawn(future).await??)
}

#[macro_export]
macro_rules! join {
  ($($i:expr),*) => {{
    let r = $crate::tokio::join!($($i),*);
    (
      $(
        ${ignore($i)}
        r.${index()}?
      ),*
    )
  }};
}