tikv_jemalloc_ctl/
thread.rs

1//! Thread specific operations.
2
3use crate::error::Result;
4use crate::raw::{read, read_mib};
5
6option! {
7    allocatedp[ str: b"thread.allocatedp\0", non_str: 2 ] => *mut u64 |
8    ops:  |
9    docs:
10    /// Access to the total number of bytes allocated by the current thread.
11    ///
12    /// Unlike [`crate::stats::allocated`], the value returned by this type is not the
13    /// number of bytes *currently* allocated, but rather the number of bytes
14    /// that have *ever* been allocated by this thread.
15    ///
16    /// The `read` method doesn't return the value directly, but actually a
17    /// pointer to the value. This allows for very fast repeated lookup, since
18    /// there is no function call overhead. The pointer type cannot be sent to
19    /// other threads, but `allocated::read` can be called on different threads
20    /// and will return the appropriate pointer for each of them.
21    ///
22    /// # Example
23    ///
24    /// ```
25    /// # #[global_allocator]
26    /// # static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
27    /// #
28    /// # fn main() {
29    /// use tikv_jemalloc_ctl::thread;
30    /// let allocated = thread::allocatedp::mib().unwrap();
31    /// let allocated = allocated.read().unwrap();
32    ///
33    /// let a = allocated.get();
34    /// let buf = vec![0; 1024 * 1024];
35    /// let b = allocated.get();
36    /// drop(    buf);
37    /// let c = allocated.get();
38    ///
39    /// assert!(a < b);
40    /// assert_eq!(b, c);
41    /// # }
42    /// ```
43    mib_docs: /// See [`allocatedp`].
44}
45
46impl allocatedp {
47    /// Reads value using string API.
48    pub fn read() -> Result<ThreadLocal<u64>> {
49        unsafe { read(Self::name().as_bytes()).map(ThreadLocal) }
50    }
51}
52
53impl allocatedp_mib {
54    /// Reads value using MIB API.
55    pub fn read(&self) -> Result<ThreadLocal<u64>> {
56        unsafe { read_mib(self.0.as_ref()).map(ThreadLocal) }
57    }
58}
59
60option! {
61    deallocatedp[ str: b"thread.deallocatedp\0", non_str: 2 ] => *mut u64 |
62    ops:  |
63    docs:
64    /// Access to the total number of bytes deallocated by the current thread.
65    ///
66    /// The `read` method doesn't return the value directly, but actually a
67    /// pointer to the value. This allows for very fast repeated lookup, since
68    /// there is no function call overhead. The pointer type cannot be sent to
69    /// other threads, but [`deallocatedp::read`] can be called on different
70    /// threads and will return the appropriate pointer for each of them.
71    ///
72    /// # Example
73    ///
74    /// ```
75    /// # #[global_allocator]
76    /// # static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
77    /// #
78    /// # fn main() {
79    /// use tikv_jemalloc_ctl::thread;
80    /// let deallocated = thread::deallocatedp::mib().unwrap();
81    /// let deallocated = deallocated.read().unwrap();
82    ///
83    /// let a = deallocated.get();
84    /// let buf = vec![0; 1024 * 1024];
85    /// let b = deallocated.get();
86    /// drop(buf);
87    /// let c = deallocated.get();
88    ///
89    /// assert_eq!(a, b);
90    /// assert!(b < c);
91    /// # }
92    /// ```
93    mib_docs: /// See [`deallocatedp`].
94}
95
96impl deallocatedp {
97    /// Reads value using string API.
98    pub fn read() -> Result<ThreadLocal<u64>> {
99        unsafe { read(Self::name().as_bytes()).map(ThreadLocal) }
100    }
101}
102
103impl deallocatedp_mib {
104    /// Reads value using MIB API.
105    pub fn read(&self) -> Result<ThreadLocal<u64>> {
106        unsafe { read_mib(self.0.as_ref()).map(ThreadLocal) }
107    }
108}
109
110/// A thread-local pointer.
111///
112/// It is neither `Sync` nor `Send`.
113// NB we need *const here specifically since it's !Sync + !Send
114#[repr(transparent)]
115#[derive(Copy, Clone)]
116pub struct ThreadLocal<T>(*const T);
117
118impl<T> ThreadLocal<T>
119where
120    T: Copy,
121{
122    /// Returns the current value at the pointer.
123    #[inline]
124    pub fn get(self) -> T {
125        unsafe { *self.0 }
126    }
127}