forked from gnzlbg/jemallocator
-
Notifications
You must be signed in to change notification settings - Fork 47
/
thread.rs
127 lines (118 loc) · 3.77 KB
/
thread.rs
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
//! Thread specific operations.
use crate::error::Result;
use crate::raw::{read, read_mib};
option! {
allocatedp[ str: b"thread.allocatedp\0", non_str: 2 ] => *mut u64 |
ops: |
docs:
/// Access to the total number of bytes allocated by the current thread.
///
/// Unlike [`crate::stats::allocated`], the value returned by this type is not the
/// number of bytes *currently* allocated, but rather the number of bytes
/// that have *ever* been allocated by this thread.
///
/// The `read` method doesn't return the value directly, but actually a
/// pointer to the value. This allows for very fast repeated lookup, since
/// there is no function call overhead. The pointer type cannot be sent to
/// other threads, but `allocated::read` can be called on different threads
/// and will return the appropriate pointer for each of them.
///
/// # Example
///
/// ```
/// # #[global_allocator]
/// # static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
/// #
/// # fn main() {
/// use tikv_jemalloc_ctl::thread;
/// let allocated = thread::allocatedp::mib().unwrap();
/// let allocated = allocated.read().unwrap();
///
/// let a = allocated.get();
/// let buf = vec![0; 1024 * 1024];
/// let b = allocated.get();
/// drop( buf);
/// let c = allocated.get();
///
/// assert!(a < b);
/// assert_eq!(b, c);
/// # }
/// ```
mib_docs: /// See [`allocatedp`].
}
impl allocatedp {
/// Reads value using string API.
pub fn read() -> Result<ThreadLocal<u64>> {
unsafe { read(Self::name().as_bytes()).map(ThreadLocal) }
}
}
impl allocatedp_mib {
/// Reads value using MIB API.
pub fn read(&self) -> Result<ThreadLocal<u64>> {
unsafe { read_mib(self.0.as_ref()).map(ThreadLocal) }
}
}
option! {
deallocatedp[ str: b"thread.deallocatedp\0", non_str: 2 ] => *mut u64 |
ops: |
docs:
/// Access to the total number of bytes deallocated by the current thread.
///
/// The `read` method doesn't return the value directly, but actually a
/// pointer to the value. This allows for very fast repeated lookup, since
/// there is no function call overhead. The pointer type cannot be sent to
/// other threads, but [`deallocatedp::read`] can be called on different
/// threads and will return the appropriate pointer for each of them.
///
/// # Example
///
/// ```
/// # #[global_allocator]
/// # static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
/// #
/// # fn main() {
/// use tikv_jemalloc_ctl::thread;
/// let deallocated = thread::deallocatedp::mib().unwrap();
/// let deallocated = deallocated.read().unwrap();
///
/// let a = deallocated.get();
/// let buf = vec![0; 1024 * 1024];
/// let b = deallocated.get();
/// drop(buf);
/// let c = deallocated.get();
///
/// assert_eq!(a, b);
/// assert!(b < c);
/// # }
/// ```
mib_docs: /// See [`deallocatedp`].
}
impl deallocatedp {
/// Reads value using string API.
pub fn read() -> Result<ThreadLocal<u64>> {
unsafe { read(Self::name().as_bytes()).map(ThreadLocal) }
}
}
impl deallocatedp_mib {
/// Reads value using MIB API.
pub fn read(&self) -> Result<ThreadLocal<u64>> {
unsafe { read_mib(self.0.as_ref()).map(ThreadLocal) }
}
}
/// A thread-local pointer.
///
/// It is neither `Sync` nor `Send`.
// NB we need *const here specifically since it's !Sync + !Send
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct ThreadLocal<T>(*const T);
impl<T> ThreadLocal<T>
where
T: Copy,
{
/// Returns the current value at the pointer.
#[inline]
pub fn get(self) -> T {
unsafe { *self.0 }
}
}