nu_protocol/pipeline/
signals.rs1use crate::{ShellError, Span};
2use nu_glob::Interruptible;
3use serde::{Deserialize, Serialize};
4use std::sync::{
5 Arc,
6 atomic::{AtomicBool, Ordering},
7};
8
9#[derive(Debug, Clone)]
13pub struct Signals {
14 signals: Option<Arc<AtomicBool>>,
15}
16
17impl Signals {
18 pub const EMPTY: Self = Signals { signals: None };
22
23 pub fn new(ctrlc: Arc<AtomicBool>) -> Self {
28 Self {
29 signals: Some(ctrlc),
30 }
31 }
32
33 pub const fn empty() -> Self {
40 Self::EMPTY
41 }
42
43 #[inline]
47 pub fn check(&self, span: Span) -> Result<(), ShellError> {
48 #[inline]
49 #[cold]
50 fn interrupt_error(span: Span) -> Result<(), ShellError> {
51 Err(ShellError::Interrupted { span })
52 }
53
54 if self.interrupted() {
55 interrupt_error(span)
56 } else {
57 Ok(())
58 }
59 }
60
61 pub fn trigger(&self) {
63 if let Some(signals) = &self.signals {
64 signals.store(true, Ordering::Relaxed);
65 }
66 }
67
68 #[inline]
70 pub fn interrupted(&self) -> bool {
71 self.signals
72 .as_deref()
73 .is_some_and(|b| b.load(Ordering::Relaxed))
74 }
75
76 pub(crate) fn is_empty(&self) -> bool {
77 self.signals.is_none()
78 }
79
80 pub fn reset(&self) {
81 if let Some(signals) = &self.signals {
82 signals.store(false, Ordering::Relaxed);
83 }
84 }
85}
86
87impl Interruptible for Signals {
88 #[inline]
89 fn interrupted(&self) -> bool {
90 self.interrupted()
91 }
92}
93
94#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
97pub enum SignalAction {
98 Interrupt,
99 Reset,
100}