nuclei/rt/runtime/
enter.rs1use core::fmt;
7use core::marker::PhantomData;
8use std::sync::Arc;
9
10use super::{Inner, Runtime, RuntimeHandle};
11use crate::rt::context;
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
15pub struct RuntimeId(u64);
16
17impl RuntimeId {
18 pub(crate) fn from_raw(id: u64) -> Self {
19 Self(id)
20 }
21}
22
23impl fmt::Display for RuntimeId {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 self.0.fmt(f)
26 }
27}
28
29#[must_use = "the runtime is set only while the guard lives"]
33pub struct EnterGuard<'a> {
34 _set: context::RuntimeSet,
35 _runtime: PhantomData<&'a ()>,
36 _not_send: PhantomData<*const ()>,
37}
38
39impl fmt::Debug for EnterGuard<'_> {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 f.debug_struct("EnterGuard").finish_non_exhaustive()
42 }
43}
44
45#[derive(Clone, Copy, Debug, PartialEq, Eq)]
47pub struct TryCurrentError {
48 _private: (),
49}
50
51impl TryCurrentError {
52 pub fn is_missing_context(&self) -> bool {
54 true
55 }
56}
57
58impl fmt::Display for TryCurrentError {
59 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60 f.write_str(
61 "no runtime is set on this thread: call it inside `block_on`, a task, or `enter`",
62 )
63 }
64}
65
66impl std::error::Error for TryCurrentError {}
67
68fn enter(inner: &Arc<Inner>) -> EnterGuard<'_> {
69 EnterGuard {
70 _set: context::set_runtime(inner),
71 _runtime: PhantomData,
72 _not_send: PhantomData,
73 }
74}
75
76impl Runtime {
77 pub fn enter(&self) -> EnterGuard<'_> {
87 enter(&self.inner)
88 }
89
90 pub fn id(&self) -> RuntimeId {
92 RuntimeId(self.inner.id)
93 }
94
95 pub fn shutdown_background(self) {
100 let lingering = self.inner.lingering();
101 lingering.close();
102 self.inner.workers.stop_all();
103 drop(self.inner.workers.take_threads());
106 lingering.end();
107 }
108}
109
110impl RuntimeHandle {
111 pub fn enter(&self) -> EnterGuard<'_> {
114 enter(&self.inner)
115 }
116
117 pub fn id(&self) -> RuntimeId {
119 RuntimeId(self.inner.id)
120 }
121
122 pub fn try_current() -> Result<Self, TryCurrentError> {
127 context::runtime()
128 .map(|inner| Self { inner })
129 .ok_or(TryCurrentError { _private: () })
130 }
131}
132
133pub fn worker_index() -> Option<usize> {
137 let runtime = context::runtime()?;
138 context::current(|shard| shard.and_then(|shard| shard.worker_index(runtime.id)))
139}