1use std::sync::Arc;
7
8pub(crate) const QUARTZ_EVERY: u32 = 16;
11pub(crate) const DRIVE_BOUND: u64 = 1_000_000;
14
15#[derive(Clone, Debug)]
18pub(crate) struct Tuning {
19 pub(crate) driver_interval: u32,
21 pub(crate) drive_bound: u64,
25 pub(crate) inbox_interval: u32,
27 pub(crate) max_io_events: usize,
29 pub(crate) lifo: bool,
31 pub(crate) hooks: ThreadHooks,
32 pub(crate) blocking: Option<Arc<crate::sync::internal::AtomicUsize>>,
35 #[cfg(ring)]
38 pub(crate) zero_copy_min: usize,
39 pub(crate) record_latencies: bool,
41 #[cfg(feature = "io-stats")]
43 pub(crate) count_io: bool,
44}
45
46impl Default for Tuning {
47 fn default() -> Self {
48 Self {
49 driver_interval: super::shard::DRIVER_INTERVAL,
50 drive_bound: DRIVE_BOUND,
51 inbox_interval: super::shard::INBOX_INTERVAL,
52 max_io_events: usize::MAX,
53 lifo: true,
54 hooks: ThreadHooks::default(),
55 blocking: None,
56 #[cfg(ring)]
57 zero_copy_min: crate::io::source::ring::SEND_ZC_MIN,
58 record_latencies: false,
59 #[cfg(feature = "io-stats")]
60 count_io: false,
61 }
62 }
63}
64
65pub(crate) type Hook = Arc<dyn Fn() + Send + Sync>;
67
68#[derive(Clone, Default)]
70pub(crate) struct ThreadHooks {
71 pub(crate) start: Option<Hook>,
72 pub(crate) stop: Option<Hook>,
73 pub(crate) park: Option<Hook>,
74 pub(crate) unpark: Option<Hook>,
75}
76
77impl ThreadHooks {
78 pub(crate) fn started(&self) -> Stopping {
81 if let Some(start) = &self.start {
82 start();
83 }
84 Stopping(self.stop.clone())
85 }
86}
87
88pub(crate) struct Stopping(Option<Hook>);
90
91impl Drop for Stopping {
92 fn drop(&mut self) {
93 if let Some(stop) = &self.0 {
94 stop();
95 }
96 }
97}
98
99impl core::fmt::Debug for ThreadHooks {
100 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
101 f.debug_struct("ThreadHooks")
102 .field("start", &self.start.is_some())
103 .field("stop", &self.stop.is_some())
104 .field("park", &self.park.is_some())
105 .field("unpark", &self.unpark.is_some())
106 .finish()
107 }
108}
109
110#[derive(Debug)]
112pub struct TaskMeta<'a> {
113 id: crate::task::Id,
114 name: Option<Arc<str>>,
115 _task: core::marker::PhantomData<&'a ()>,
116}
117
118impl TaskMeta<'_> {
119 pub(crate) fn new(id: crate::task::Id) -> Self {
120 Self {
121 id,
122 name: super::task::names::get(id),
123 _task: core::marker::PhantomData,
124 }
125 }
126
127 pub fn id(&self) -> crate::task::Id {
129 self.id
130 }
131
132 pub fn name(&self) -> Option<&str> {
135 self.name.as_deref()
136 }
137}
138
139pub(crate) type TaskHook = Arc<dyn Fn(&TaskMeta<'_>) + Send + Sync>;
141
142#[derive(Clone, Default)]
145pub(crate) struct TaskHooks {
146 pub(crate) spawn: Option<TaskHook>,
147 pub(crate) before_poll: Option<TaskHook>,
148 pub(crate) after_poll: Option<TaskHook>,
149 pub(crate) terminate: Option<TaskHook>,
150 pub(crate) shutdown: Option<std::sync::Weak<super::runtime::Inner>>,
152}
153
154impl TaskHooks {
155 pub(crate) fn any(&self) -> bool {
156 self.spawn.is_some()
157 || self.before_poll.is_some()
158 || self.after_poll.is_some()
159 || self.terminate.is_some()
160 || self.shutdown.is_some()
161 }
162}
163
164pub(crate) static ANY_TASK_HOOKS: core::sync::atomic::AtomicBool =
167 core::sync::atomic::AtomicBool::new(false);
168
169#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
172#[non_exhaustive]
173pub enum UnhandledPanic {
174 #[default]
177 Ignore,
178 ShutdownRuntime,
182}
183
184pub(crate) fn call(hook: Option<&TaskHook>, id: crate::task::Id) {
187 if let Some(hook) = hook {
188 crate::rt::task::abort_on_panic(|| hook(&TaskMeta::new(id)));
189 }
190}