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
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//! Utilities for the context library
//!
//! Also used by some collector implementations.
use core::fmt::{self, Debug, Formatter, Display};
#[cfg(not(feature = "sync"))]
use core::cell::Cell;

#[cfg(feature = "sync")]
pub type AtomicCell<T> = ::crossbeam_utils::atomic::AtomicCell<T>;
/// Fallback `AtomicCell` implementation when we actually
/// don't care about thread safety
#[cfg(not(feature = "sync"))]
#[derive(Default)]
pub struct AtomicCell<T>(Cell<T>);
#[cfg(not(feature = "sync"))]
impl<T: Copy> AtomicCell<T> {
    pub const fn new(value: T) -> Self {
        AtomicCell(Cell::new(value))
    }
    pub fn store(&self, value: T) {
        self.0.set(value)
    }
    pub fn load(&self) -> T {
        self.0.get()
    }
    pub fn compare_exchange(&self, expected: T, updated: T) -> Result<T, T>
        where T: PartialEq {
        let existing = self.0.get();
        if existing == expected {
            self.0.set(updated);
            Ok(existing)
        } else {
            Err(existing)
        }
    }
}

#[derive(Clone)]
pub enum ThreadId {
    #[allow(unused)]
    Nop,
    #[cfg(feature = "std")]
    Enabled {
        id: std::thread::ThreadId,
        name: Option<String>
    }
}
impl ThreadId {
    #[cfg(feature = "std")]
    pub fn current() -> ThreadId {
        // NOTE: It's okay: `sync` requires std
        let thread = std::thread::current();
        ThreadId::Enabled {
            id: thread.id(),
            name: thread.name().map(String::from)
        }
    }
    #[cfg(not(feature = "std"))]
    #[inline]
    pub fn current() -> ThreadId {
        ThreadId::Nop
    }
}
impl slog::Value for ThreadId {
    #[cfg(not(feature = "std"))]
    fn serialize(
        &self, _record: &slog::Record,
        _key: &'static str,
        _serializer: &mut dyn slog::Serializer
    ) -> slog::Result<()> {
        Ok(()) // Nop
    }
    #[cfg(feature = "std")]
    fn serialize(
        &self, _record: &slog::Record,
        key: &'static str,
        serializer: &mut dyn slog::Serializer
    ) -> slog::Result<()> {
        let (id, name) = match *self {
            ThreadId::Nop => return Ok(()),
            ThreadId::Enabled { ref id, ref name } => (id, name)
        };
        match *name {
            Some(ref name) => {
                serializer.emit_arguments(key, &format_args!(
                    "{}: {:?}", *name, id
                ))
            },
            None => {
                serializer.emit_arguments(key, &format_args!(
                    "{:?}", id
                ))
            },
        }
    }
}
impl Debug for ThreadId {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match *self {
            ThreadId::Nop => f.write_str("ThreadId(??)"),
            #[cfg(feature = "std")]
            ThreadId::Enabled { id, name: None } => {
                write!(f, "{:?}", id)
            },
            #[cfg(feature = "std")]
            ThreadId::Enabled { id, name: Some(ref name) } => {
                f.debug_tuple("ThreadId")
                    .field(&id)
                    .field(name)
                    .finish()
            }
        }
    }
}
/// The size of memory in bytes
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct MemorySize {
    pub bytes: usize
}
impl Display for MemorySize {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        if f.alternate() {
            write!(f, "{}", self.bytes)
        } else {
            // Write approximation
            let bytes = self.bytes;
            let (amount, suffix) = if bytes > 1024 * 1024 * 1024 {
                (1024 * 1024 * 1024, "GB")
            } else if bytes > 1024 * 1024 {
                (1024 * 1024, "MB")
            } else if bytes > 1024 {
                (1024, "KB")
            } else {
                (1, "")
            };
            write!(f, "{:.2}{}", bytes as f64 / amount as f64, suffix)
        }
    }
}