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
//! Thread specific operations. use error::Result; use 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 [`::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 /// /// ``` /// # extern crate jemallocator; /// # extern crate jemalloc_ctl; /// # /// # #[global_allocator] /// # static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; /// # /// # fn main() { /// use 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 /// /// ``` /// # extern crate jemallocator; /// # extern crate jemalloc_ctl; /// # /// # #[global_allocator] /// # static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; /// # /// # fn main() { /// use 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 } } }