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}