threadid/
debug.rs

1//! Identifies a thread in a form useful for debugging.
2
3use core::fmt::{Debug, Display, Formatter};
4
5use crate::UniqueThreadId;
6
7/// Identifies a thread in a form useful for debugging.
8///
9/// Uses the [name] if possible and the id where it is not.
10///
11/// [name]: std::thread::Thread::name
12#[derive(Clone)]
13#[must_use]
14pub struct DebugThreadId {
15    /// This is really an `Arc<ThreadInfo>`,
16    /// so it is cheap to Clone and fine if it lives beyond thread death
17    info: std::thread::Thread,
18    id: UniqueThreadId,
19}
20impl DebugThreadId {
21    /// Get the [`DebugThreadId`] of the current thread.
22    ///
23    /// Will be significantly slower than [`UniqueThreadId::current`],
24    /// due to the need to fetch the thread's name.
25    pub fn current() -> DebugThreadId {
26        DebugThreadId {
27            info: std::thread::current(),
28            id: UniqueThreadId::current(),
29        }
30    }
31
32    /// Get the name of the thread, or `None` if not available.
33    #[inline]
34    #[must_use]
35    pub fn name(&self) -> Option<&'_ str> {
36        self.info.name()
37    }
38
39    /// Get the id of this thread as a [`UniqueThreadId`].
40    #[inline]
41    pub fn id(&self) -> UniqueThreadId {
42        self.id
43    }
44}
45impl Display for DebugThreadId {
46    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
47        write!(f, "{}", self.id.to_int())?;
48        if let Some(name) = self.name() {
49            write!(f, "({name:?})")?;
50        }
51        Ok(())
52    }
53}
54impl Debug for DebugThreadId {
55    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
56        write!(f, "ThreadId({}", self.id.to_int())?;
57        if let Some(name) = self.name() {
58            write!(f, ", {name:?})")?;
59        } else {
60            f.write_str(")")?;
61        }
62        Ok(())
63    }
64}
65#[cfg(feature = "slog")]
66impl slog::Value for DebugThreadId {
67    fn serialize(&self, _record: &slog::Record, key: slog::Key, serializer: &mut dyn slog::Serializer) -> slog::Result {
68        serializer.emit_arguments(key, &format_args!("{self}"))
69    }
70}
71#[cfg(feature = "serde")]
72impl serde::Serialize for DebugThreadId {
73    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
74    where
75        S: serde::Serializer,
76    {
77        use serde::ser::SerializeStruct;
78        let name = self.name();
79        let mut ser = serializer.serialize_struct("ThreadDebugId", if name.is_some() { 2 } else { 1 })?;
80        if let Some(name) = name {
81            ser.serialize_field("name", &name)?;
82        } else {
83            ser.skip_field("name")?;
84        }
85        ser.serialize_field("id", &self.id())?;
86        ser.end()
87    }
88}