summaryrefslogtreecommitdiff
path: root/runtime/tokio_util.rs
blob: d723006bda673b4dd7eaf11d015cf51b1532cdf5 (plain)
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
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.

use deno_core::task::MaskFutureAsSend;

pub fn create_basic_runtime() -> tokio::runtime::Runtime {
  tokio::runtime::Builder::new_current_thread()
    .enable_io()
    .enable_time()
    // This limits the number of threads for blocking operations (like for
    // synchronous fs ops) or CPU bound tasks like when we run dprint in
    // parallel for deno fmt.
    // The default value is 512, which is an unhelpfully large thread pool. We
    // don't ever want to have more than a couple dozen threads.
    .max_blocking_threads(32)
    .build()
    .unwrap()
}

#[inline(always)]
pub fn create_and_run_current_thread<F, R>(future: F) -> R
where
  F: std::future::Future<Output = R> + 'static,
  R: Send + 'static,
{
  let rt = create_basic_runtime();

  // Since this is the main future, we want to box it in debug mode because it tends to be fairly
  // large and the compiler won't optimize repeated copies. We also make this runtime factory
  // function #[inline(always)] to avoid holding the unboxed, unused future on the stack.

  #[cfg(debug_assertions)]
  // SAFETY: this this is guaranteed to be running on a current-thread executor
  let future = Box::pin(unsafe { MaskFutureAsSend::new(future) });

  #[cfg(not(debug_assertions))]
  // SAFETY: this this is guaranteed to be running on a current-thread executor
  let future = unsafe { MaskFutureAsSend::new(future) };

  let join_handle = rt.spawn(future);
  rt.block_on(join_handle).unwrap().into_inner()
}