|
1 |
| -use std::ffi::CString; |
2 |
| -use std::sync::OnceLock; |
3 |
| - |
| 1 | +#[cfg(target_os = "linux")] |
4 | 2 | mod ffi;
|
5 | 3 |
|
6 |
| -pub struct InstrumentHooks(*mut ffi::InstrumentHooks); |
| 4 | +#[cfg(target_os = "linux")] |
| 5 | +mod linux_impl { |
| 6 | + use nix::sys::time::TimeValLike; |
7 | 7 |
|
8 |
| -unsafe impl Send for InstrumentHooks {} |
9 |
| -unsafe impl Sync for InstrumentHooks {} |
| 8 | + use super::ffi; |
| 9 | + use std::ffi::CString; |
| 10 | + use std::sync::OnceLock; |
10 | 11 |
|
11 |
| -impl InstrumentHooks { |
12 |
| - #[inline(always)] |
13 |
| - pub fn new() -> Option<Self> { |
14 |
| - let ptr = unsafe { ffi::instrument_hooks_init() }; |
15 |
| - if ptr.is_null() { |
16 |
| - None |
17 |
| - } else { |
18 |
| - Some(InstrumentHooks(ptr)) |
19 |
| - } |
20 |
| - } |
| 12 | + pub struct InstrumentHooks(*mut ffi::InstrumentHooks); |
21 | 13 |
|
22 |
| - /// Returns a singleton instance of `InstrumentHooks`. |
23 |
| - #[inline(always)] |
24 |
| - pub fn instance() -> &'static Self { |
25 |
| - static INSTANCE: OnceLock<InstrumentHooks> = OnceLock::new(); |
26 |
| - INSTANCE.get_or_init(|| { |
27 |
| - let instance = InstrumentHooks::new().expect("Failed to initialize InstrumentHooks"); |
28 |
| - instance |
29 |
| - .set_integration("codspeed-rust", env!("CARGO_PKG_VERSION")) |
30 |
| - .expect("Failed to set integration"); |
31 |
| - instance |
32 |
| - }) |
33 |
| - } |
| 14 | + unsafe impl Send for InstrumentHooks {} |
| 15 | + unsafe impl Sync for InstrumentHooks {} |
34 | 16 |
|
35 |
| - #[inline(always)] |
36 |
| - pub fn is_instrumented(&self) -> bool { |
37 |
| - unsafe { ffi::instrument_hooks_is_instrumented(self.0) } |
38 |
| - } |
| 17 | + impl InstrumentHooks { |
| 18 | + #[inline(always)] |
| 19 | + pub fn new() -> Option<Self> { |
| 20 | + let ptr = unsafe { ffi::instrument_hooks_init() }; |
| 21 | + if ptr.is_null() { |
| 22 | + None |
| 23 | + } else { |
| 24 | + Some(InstrumentHooks(ptr)) |
| 25 | + } |
| 26 | + } |
39 | 27 |
|
40 |
| - #[inline(always)] |
41 |
| - pub fn start_benchmark(&self) -> Result<(), u8> { |
42 |
| - let result = unsafe { ffi::instrument_hooks_start_benchmark(self.0) }; |
43 |
| - if result == 0 { |
44 |
| - Ok(()) |
45 |
| - } else { |
46 |
| - Err(result) |
| 28 | + /// Returns a singleton instance of `InstrumentHooks`. |
| 29 | + #[inline(always)] |
| 30 | + pub fn instance() -> &'static Self { |
| 31 | + static INSTANCE: OnceLock<InstrumentHooks> = OnceLock::new(); |
| 32 | + INSTANCE.get_or_init(|| { |
| 33 | + let instance = |
| 34 | + InstrumentHooks::new().expect("Failed to initialize InstrumentHooks"); |
| 35 | + instance |
| 36 | + .set_integration("codspeed-rust", env!("CARGO_PKG_VERSION")) |
| 37 | + .expect("Failed to set integration"); |
| 38 | + instance |
| 39 | + }) |
47 | 40 | }
|
48 |
| - } |
49 | 41 |
|
50 |
| - #[inline(always)] |
51 |
| - pub fn stop_benchmark(&self) -> Result<(), u8> { |
52 |
| - let result = unsafe { ffi::instrument_hooks_stop_benchmark(self.0) }; |
53 |
| - if result == 0 { |
54 |
| - Ok(()) |
55 |
| - } else { |
56 |
| - Err(result) |
| 42 | + #[inline(always)] |
| 43 | + pub fn is_instrumented(&self) -> bool { |
| 44 | + unsafe { ffi::instrument_hooks_is_instrumented(self.0) } |
57 | 45 | }
|
58 |
| - } |
59 | 46 |
|
60 |
| - #[inline(always)] |
61 |
| - pub fn set_executed_benchmark(&self, uri: &str) -> Result<(), u8> { |
62 |
| - let pid = std::process::id() as i32; |
63 |
| - let c_uri = CString::new(uri).map_err(|_| 1u8)?; |
64 |
| - let result = |
65 |
| - unsafe { ffi::instrument_hooks_set_executed_benchmark(self.0, pid, c_uri.as_ptr()) }; |
66 |
| - if result == 0 { |
67 |
| - Ok(()) |
68 |
| - } else { |
69 |
| - Err(result) |
| 47 | + #[inline(always)] |
| 48 | + pub fn start_benchmark(&self) -> Result<(), i8> { |
| 49 | + let result = unsafe { ffi::instrument_hooks_start_benchmark(self.0) }; |
| 50 | + if result == 0 { |
| 51 | + Ok(()) |
| 52 | + } else { |
| 53 | + Err(result) |
| 54 | + } |
70 | 55 | }
|
71 |
| - } |
72 | 56 |
|
73 |
| - #[inline(always)] |
74 |
| - pub fn set_integration(&self, name: &str, version: &str) -> Result<(), u8> { |
75 |
| - let c_name = CString::new(name).map_err(|_| 1u8)?; |
76 |
| - let c_version = CString::new(version).map_err(|_| 1u8)?; |
77 |
| - let result = unsafe { |
78 |
| - ffi::instrument_hooks_set_integration(self.0, c_name.as_ptr(), c_version.as_ptr()) |
79 |
| - }; |
80 |
| - if result == 0 { |
81 |
| - Ok(()) |
82 |
| - } else { |
83 |
| - Err(result) |
| 57 | + #[inline(always)] |
| 58 | + pub fn stop_benchmark(&self) -> Result<(), i8> { |
| 59 | + let result = unsafe { ffi::instrument_hooks_stop_benchmark(self.0) }; |
| 60 | + if result == 0 { |
| 61 | + Ok(()) |
| 62 | + } else { |
| 63 | + Err(result) |
| 64 | + } |
84 | 65 | }
|
85 |
| - } |
86 | 66 |
|
87 |
| - #[inline(always)] |
88 |
| - pub fn add_benchmark_timestamps(&self, start: u64, end: u64) { |
89 |
| - let pid = std::process::id(); |
90 |
| - |
91 |
| - unsafe { |
92 |
| - ffi::instrument_hooks_add_marker( |
93 |
| - self.0, |
94 |
| - pid, |
95 |
| - ffi::MARKER_TYPE_BENCHMARK_START as u8, |
96 |
| - start, |
97 |
| - ) |
98 |
| - }; |
99 |
| - unsafe { |
100 |
| - ffi::instrument_hooks_add_marker(self.0, pid, ffi::MARKER_TYPE_BENCHMARK_END as u8, end) |
101 |
| - }; |
102 |
| - } |
| 67 | + #[inline(always)] |
| 68 | + pub fn set_executed_benchmark(&self, uri: &str) -> Result<(), i8> { |
| 69 | + let pid = std::process::id() as i32; |
| 70 | + let c_uri = CString::new(uri).map_err(|_| -1i8)?; |
| 71 | + let result = unsafe { |
| 72 | + ffi::instrument_hooks_set_executed_benchmark(self.0, pid, c_uri.as_ptr()) |
| 73 | + }; |
| 74 | + if result == 0 { |
| 75 | + Ok(()) |
| 76 | + } else { |
| 77 | + Err(result) |
| 78 | + } |
| 79 | + } |
103 | 80 |
|
104 |
| - #[inline(always)] |
105 |
| - pub fn current_timestamp() -> u64 { |
106 |
| - #[cfg(not(target_os = "linux"))] |
107 |
| - { |
108 |
| - unsafe { ffi::instrument_hooks_current_timestamp() } |
| 81 | + #[inline(always)] |
| 82 | + pub fn set_integration(&self, name: &str, version: &str) -> Result<(), i8> { |
| 83 | + let c_name = CString::new(name).map_err(|_| -1i8)?; |
| 84 | + let c_version = CString::new(version).map_err(|_| -1i8)?; |
| 85 | + let result = unsafe { |
| 86 | + ffi::instrument_hooks_set_integration(self.0, c_name.as_ptr(), c_version.as_ptr()) |
| 87 | + }; |
| 88 | + if result == 0 { |
| 89 | + Ok(()) |
| 90 | + } else { |
| 91 | + Err(result) |
| 92 | + } |
109 | 93 | }
|
110 | 94 |
|
111 |
| - // Custom implementation to avoid the extra FFI call |
112 |
| - #[cfg(target_os = "linux")] |
113 |
| - { |
114 |
| - use nix::sys::time::TimeValLike; |
| 95 | + #[inline(always)] |
| 96 | + pub fn add_benchmark_timestamps(&self, start: u64, end: u64) { |
| 97 | + let pid = std::process::id(); |
| 98 | + |
| 99 | + unsafe { |
| 100 | + ffi::instrument_hooks_add_marker( |
| 101 | + self.0, |
| 102 | + pid, |
| 103 | + ffi::MARKER_TYPE_BENCHMARK_START as u8, |
| 104 | + start, |
| 105 | + ) |
| 106 | + }; |
| 107 | + unsafe { |
| 108 | + ffi::instrument_hooks_add_marker( |
| 109 | + self.0, |
| 110 | + pid, |
| 111 | + ffi::MARKER_TYPE_BENCHMARK_END as u8, |
| 112 | + end, |
| 113 | + ) |
| 114 | + }; |
| 115 | + } |
| 116 | + |
| 117 | + #[inline(always)] |
| 118 | + pub fn current_timestamp() -> u64 { |
115 | 119 | nix::time::clock_gettime(nix::time::ClockId::CLOCK_MONOTONIC)
|
116 | 120 | .expect("Failed to get current time")
|
117 | 121 | .num_nanoseconds() as u64
|
118 | 122 | }
|
119 | 123 | }
|
| 124 | + |
| 125 | + impl Drop for InstrumentHooks { |
| 126 | + fn drop(&mut self) { |
| 127 | + if !self.0.is_null() { |
| 128 | + unsafe { ffi::instrument_hooks_deinit(self.0) }; |
| 129 | + } |
| 130 | + } |
| 131 | + } |
120 | 132 | }
|
121 | 133 |
|
122 |
| -impl Drop for InstrumentHooks { |
123 |
| - fn drop(&mut self) { |
124 |
| - if !self.0.is_null() { |
125 |
| - unsafe { ffi::instrument_hooks_deinit(self.0) }; |
| 134 | +#[cfg(not(target_os = "linux"))] |
| 135 | +mod other_impl { |
| 136 | + pub struct InstrumentHooks; |
| 137 | + |
| 138 | + impl InstrumentHooks { |
| 139 | + pub fn instance() -> &'static Self { |
| 140 | + static INSTANCE: InstrumentHooks = InstrumentHooks; |
| 141 | + &INSTANCE |
| 142 | + } |
| 143 | + |
| 144 | + pub fn is_instrumented(&self) -> bool { |
| 145 | + false |
| 146 | + } |
| 147 | + |
| 148 | + pub fn start_benchmark(&self) -> Result<(), i8> { |
| 149 | + Ok(()) |
| 150 | + } |
| 151 | + |
| 152 | + pub fn stop_benchmark(&self) -> Result<(), i8> { |
| 153 | + Ok(()) |
| 154 | + } |
| 155 | + |
| 156 | + pub fn set_executed_benchmark(&self, _uri: &str) -> Result<(), i8> { |
| 157 | + Ok(()) |
| 158 | + } |
| 159 | + |
| 160 | + pub fn set_integration(&self, _name: &str, _version: &str) -> Result<(), i8> { |
| 161 | + Ok(()) |
| 162 | + } |
| 163 | + |
| 164 | + pub fn add_benchmark_timestamps(&self, _start: u64, _end: u64) {} |
| 165 | + |
| 166 | + pub fn current_timestamp() -> u64 { |
| 167 | + 0 |
126 | 168 | }
|
127 | 169 | }
|
128 | 170 | }
|
129 | 171 |
|
| 172 | +#[cfg(target_os = "linux")] |
| 173 | +pub use linux_impl::InstrumentHooks; |
| 174 | + |
| 175 | +#[cfg(not(target_os = "linux"))] |
| 176 | +pub use other_impl::InstrumentHooks; |
| 177 | + |
130 | 178 | #[cfg(test)]
|
131 | 179 | mod tests {
|
132 | 180 | use super::InstrumentHooks;
|
|
0 commit comments