summaryrefslogtreecommitdiffstats
path: root/tokio/src/runtime/handle.rs
blob: 93644840568c629de19506be7f99fff8bba84f1f (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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#[cfg(feature = "rt-core")]
use crate::runtime::basic_scheduler;
#[cfg(feature = "rt-full")]
use crate::runtime::thread_pool;
use crate::runtime::{blocking, io, time};
#[cfg(feature = "rt-core")]
use crate::task::JoinHandle;

#[cfg(feature = "rt-core")]
use std::future::Future;

/// Handle to the runtime
#[derive(Debug, Clone)]
pub struct Handle {
    pub(super) kind: Kind,

    /// Handles to the I/O drivers
    pub(super) io_handles: Vec<io::Handle>,

    /// Handles to the time drivers
    pub(super) time_handles: Vec<time::Handle>,

    pub(super) clock: time::Clock,

    /// Blocking pool spawner
    pub(super) blocking_spawner: blocking::Spawner,
}

#[derive(Debug, Clone)]
pub(super) enum Kind {
    Shell,
    #[cfg(feature = "rt-core")]
    Basic(basic_scheduler::Spawner),
    #[cfg(feature = "rt-full")]
    ThreadPool(thread_pool::Spawner),
}

impl Handle {
    /// Spawn a future onto the Tokio runtime.
    ///
    /// This spawns the given future onto the runtime's executor, usually a
    /// thread pool. The thread pool is then responsible for polling the future
    /// until it completes.
    ///
    /// See [module level][mod] documentation for more details.
    ///
    /// [mod]: index.html
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::runtime::Runtime;
    ///
    /// # fn dox() {
    /// // Create the runtime
    /// let rt = Runtime::new().unwrap();
    /// let handle = rt.handle();
    ///
    /// // Spawn a future onto the runtime
    /// handle.spawn(async {
    ///     println!("now running on a worker thread");
    /// });
    /// # }
    /// ```
    ///
    /// # Panics
    ///
    /// This function panics if the spawn fails. Failure occurs if the executor
    /// is currently at capacity and is unable to spawn a new future.
    #[cfg(feature = "rt-core")]
    pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
    where
        F: Future + Send + 'static,
        F::Output: Send + 'static,
    {
        match &self.kind {
            Kind::Shell => panic!("spawning not enabled for runtime"),
            #[cfg(feature = "rt-core")]
            Kind::Basic(spawner) => spawner.spawn(future),
            #[cfg(feature = "rt-full")]
            Kind::ThreadPool(spawner) => spawner.spawn(future),
        }
    }

    /// Enter the runtime context
    pub fn enter<F, R>(&self, f: F) -> R
    where
        F: FnOnce() -> R,
    {
        self.blocking_spawner.enter(|| {
            let _io = io::set_default(&self.io_handles[0]);

            time::with_default(&self.time_handles[0], &self.clock, f)
        })
    }
}