diff --git a/rust/ittapi/src/domain.rs b/rust/ittapi/src/domain.rs index 6b41519a..3eaba33a 100644 --- a/rust/ittapi/src/domain.rs +++ b/rust/ittapi/src/domain.rs @@ -1,56 +1,56 @@ -use crate::util::access_sys_fn; -use std::ffi::CString; - -/// A domain enables tagging trace data for different modules or libraries in a program. See the -/// [Domain API] documentation for more information. -/// -/// [Domain API]: -/// https://www.intel.com/content/www/us/en/docs/vtune-profiler/user-guide/current/domain-api.html -pub struct Domain(*mut ittapi_sys::__itt_domain); -impl Domain { - /// Create a new domain. Note that, if the `ittnotify` library is not initialized, this call - /// will succeed but the domain will be invalid; see discussion TODO. - /// - /// ``` - /// # use ittapi::Domain; - /// let domain = Domain::new("test-domain"); - /// ``` - /// - /// # Panics - /// - /// Panics if the domain name contains a `0` byte. - #[must_use] - pub fn new(name: &str) -> Self { - #[cfg(unix)] - let create_fn = access_sys_fn!(__itt_domain_create_ptr__3_0); - #[cfg(windows)] - let create_fn = access_sys_fn!(__itt_domain_createA_ptr__3_0); - let c_string = - CString::new(name).expect("unable to create a CString; does it contain a 0 byte?"); - let domain = unsafe { create_fn(c_string.as_ptr()) }; - Self(domain) - } - - /// Use the `__itt_domain` pointer internally. - pub(crate) fn as_ptr(&self) -> *const ittapi_sys::__itt_domain { - self.0.cast_const() - } -} - -/// As discussed in the [ITT documentation], the `__itt_domain` structure is accessible by any -/// thread in the process. -/// -/// [ITT documentation]: -/// https://www.intel.com/content/www/us/en/docs/vtune-profiler/user-guide/current/domain-api.html -unsafe impl Sync for Domain {} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - #[should_panic(expected = "unable to create a CString; does it contain a 0 byte?")] - fn zero_byte() { - let _domain = Domain::new("zero\0byte\0name"); - } -} +use crate::util::access_sys_fn; +use std::ffi::CString; + +/// A domain enables tagging trace data for different modules or libraries in a program. See the +/// [Domain API] documentation for more information. +/// +/// [Domain API]: +/// https://www.intel.com/content/www/us/en/docs/vtune-profiler/user-guide/current/domain-api.html +pub struct Domain(*mut ittapi_sys::__itt_domain); +impl Domain { + /// Create a new domain. Note that, if the `ittnotify` library is not initialized, this call + /// will succeed but the domain will be invalid; see discussion TODO. + /// + /// ``` + /// # use ittapi::Domain; + /// let domain = Domain::new("test-domain"); + /// ``` + /// + /// # Panics + /// + /// Panics if the domain name contains a `0` byte. + #[must_use] + pub fn new(name: &str) -> Self { + #[cfg(unix)] + let create_fn = access_sys_fn!(__itt_domain_create_ptr__3_0); + #[cfg(windows)] + let create_fn = access_sys_fn!(__itt_domain_createA_ptr__3_0); + let c_string = + CString::new(name).expect("unable to create a CString; does it contain a 0 byte?"); + let domain = unsafe { create_fn(c_string.as_ptr()) }; + Self(domain) + } + + /// Use the `__itt_domain` pointer internally. + pub(crate) fn as_ptr(&self) -> *const ittapi_sys::__itt_domain { + self.0.cast_const() + } +} + +/// As discussed in the [ITT documentation], the `__itt_domain` structure is accessible by any +/// thread in the process. +/// +/// [ITT documentation]: +/// https://www.intel.com/content/www/us/en/docs/vtune-profiler/user-guide/current/domain-api.html +unsafe impl Sync for Domain {} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[should_panic(expected = "unable to create a CString; does it contain a 0 byte?")] + fn zero_byte() { + let _domain = Domain::new("zero\0byte\0name"); + } +} diff --git a/rust/ittapi/src/event.rs b/rust/ittapi/src/event.rs index ef60682f..76daa719 100644 --- a/rust/ittapi/src/event.rs +++ b/rust/ittapi/src/event.rs @@ -1,94 +1,94 @@ -use std::{ffi::CString, marker::PhantomData}; - -/// See the [Event API] documentation. -/// -/// [Event API]: https://www.intel.com/content/www/us/en/docs/vtune-profiler/user-guide/current/event-api.html -/// -/// ``` -/// let event = ittapi::Event::new("foo"); -/// { -/// let span = event.start(); -/// // do some work... -/// // ...the event is stopped when `span` is dropped -/// } -/// ``` -pub struct Event(ittapi_sys::__itt_event); -impl Event { - /// Create the event. - /// - /// # Panics - /// - /// Panics if the name contains a `0` byte or if its size will not fit in a 32-bit - /// representation. - #[must_use] - pub fn new(name: &str) -> Self { - #[cfg(unix)] - let create_fn = unsafe { ittapi_sys::__itt_event_create_ptr__3_0 }; - #[cfg(windows)] - let create_fn = unsafe { ittapi_sys::__itt_event_createA_ptr__3_0 }; - if let Some(create_fn) = create_fn { - let c_string = - CString::new(name).expect("unable to create a CString; does it contain a 0 byte?"); - let size = name - .len() - .try_into() - .expect("unable to fit the name length into an i32"); - let event = unsafe { create_fn(c_string.as_ptr(), size) }; - Self(event) - } else { - Self(-1) - } - } - - /// Start the event. - /// - /// # Panics - /// - /// This will panic if the ITT library cannot start the event. - #[must_use] - pub fn start(&self) -> StartedEvent { - if let Some(start_fn) = unsafe { ittapi_sys::__itt_event_start_ptr__3_0 } { - let result = unsafe { start_fn(self.0) }; - assert!(result == 0, "unable to start event"); - } - StartedEvent { - event: self.0, - phantom: PhantomData, - } - } -} - -pub struct StartedEvent<'a> { - event: ittapi_sys::__itt_event, - phantom: PhantomData<&'a mut ()>, -} - -impl StartedEvent<'_> { - /// End the event. - #[allow(clippy::unused_self)] - pub fn end(self) { - // Do nothing; the `Drop` implementation does the work. See discussion at - // https://stackoverflow.com/questions/53254645. - } -} - -impl Drop for StartedEvent<'_> { - fn drop(&mut self) { - if let Some(end_fn) = unsafe { ittapi_sys::__itt_event_end_ptr__3_0 } { - let result = unsafe { end_fn(self.event) }; - assert!(result == 0, "unable to stop event"); - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn sanity() { - let event = Event::new("test"); - let _started_event = event.start(); - // Dropping `started_event` ends the event. - } -} +use std::{ffi::CString, marker::PhantomData}; + +/// See the [Event API] documentation. +/// +/// [Event API]: https://www.intel.com/content/www/us/en/docs/vtune-profiler/user-guide/current/event-api.html +/// +/// ``` +/// let event = ittapi::Event::new("foo"); +/// { +/// let span = event.start(); +/// // do some work... +/// // ...the event is stopped when `span` is dropped +/// } +/// ``` +pub struct Event(ittapi_sys::__itt_event); +impl Event { + /// Create the event. + /// + /// # Panics + /// + /// Panics if the name contains a `0` byte or if its size will not fit in a 32-bit + /// representation. + #[must_use] + pub fn new(name: &str) -> Self { + #[cfg(unix)] + let create_fn = unsafe { ittapi_sys::__itt_event_create_ptr__3_0 }; + #[cfg(windows)] + let create_fn = unsafe { ittapi_sys::__itt_event_createA_ptr__3_0 }; + if let Some(create_fn) = create_fn { + let c_string = + CString::new(name).expect("unable to create a CString; does it contain a 0 byte?"); + let size = name + .len() + .try_into() + .expect("unable to fit the name length into an i32"); + let event = unsafe { create_fn(c_string.as_ptr(), size) }; + Self(event) + } else { + Self(-1) + } + } + + /// Start the event. + /// + /// # Panics + /// + /// This will panic if the ITT library cannot start the event. + #[must_use] + pub fn start(&self) -> StartedEvent { + if let Some(start_fn) = unsafe { ittapi_sys::__itt_event_start_ptr__3_0 } { + let result = unsafe { start_fn(self.0) }; + assert!(result == 0, "unable to start event"); + } + StartedEvent { + event: self.0, + phantom: PhantomData, + } + } +} + +pub struct StartedEvent<'a> { + event: ittapi_sys::__itt_event, + phantom: PhantomData<&'a mut ()>, +} + +impl StartedEvent<'_> { + /// End the event. + #[allow(clippy::unused_self)] + pub fn end(self) { + // Do nothing; the `Drop` implementation does the work. See discussion at + // https://stackoverflow.com/questions/53254645. + } +} + +impl Drop for StartedEvent<'_> { + fn drop(&mut self) { + if let Some(end_fn) = unsafe { ittapi_sys::__itt_event_end_ptr__3_0 } { + let result = unsafe { end_fn(self.event) }; + assert!(result == 0, "unable to stop event"); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn sanity() { + let event = Event::new("test"); + let _started_event = event.start(); + // Dropping `started_event` ends the event. + } +}