ittapi/
task.rs

1use crate::{domain::Domain, string::StringHandle};
2
3/// A task is a logical unit of work performed by a particular thread. See the [Task API]
4/// documentation for more information.
5///
6/// [Task API]:
7///     https://www.intel.com/content/www/us/en/develop/documentation/vtune-help/top/api-support/instrumentation-and-tracing-technology-apis/instrumentation-tracing-technology-api-reference/task-api.html
8///
9/// ```
10/// # use ittapi::{Domain, StringHandle, Task};
11/// let _env_path = scoped_env::ScopedEnv::set("INTEL_LIBITTNOTIFY64", "<some path>");
12/// let domain = Domain::new("domain");
13/// let name = StringHandle::new("task");
14/// // Measure a task using a pre-initialized string handle (most efficient).
15/// {
16///     let task = Task::begin(&domain, name);
17///     let _ = 2 + 2;
18///     task.end(); // Task ended here.
19///     let _ = 3 + 3;
20/// }
21/// // Measure a task using a string reference (most convenient).
22/// {
23///     let _task = Task::begin(&domain, "task");
24///     let _ = 2 + 2;
25///     // Task ended here, when dropped.
26/// }
27/// ```
28pub struct Task<'a>(&'a Domain);
29impl<'a> Task<'a> {
30    /// Start a task on the current thread.
31    pub fn begin(domain: &'a Domain, name: impl Into<StringHandle>) -> Self {
32        if let Some(create_fn) = unsafe { ittapi_sys::__itt_task_begin_ptr__3_0 } {
33            // Currently the `taskid` and `parentid` parameters are unimplemented (TODO).
34            unsafe { create_fn(domain.as_ptr(), ITT_NULL, ITT_NULL, name.into().as_ptr()) };
35        }
36        Self(domain)
37    }
38
39    /// Finish the task.
40    #[allow(clippy::unused_self)]
41    pub fn end(self) {
42        // Do nothing; the `Drop` implementation does the work. See discussion at
43        // https://stackoverflow.com/questions/53254645.
44    }
45}
46
47impl<'a> Drop for Task<'a> {
48    fn drop(&mut self) {
49        // If `ittnotify` has not been initialized, this function may not be wired up.
50        if let Some(end_fn) = unsafe { ittapi_sys::__itt_task_end_ptr__3_0 } {
51            unsafe { end_fn(self.0.as_ptr()) }
52        }
53    }
54}
55
56/// Using the `__itt_null` symbol results in errors so we redefine it here.
57const ITT_NULL: ittapi_sys::__itt_id = ittapi_sys::__itt_id {
58    d1: 0,
59    d2: 0,
60    d3: 0,
61};
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66
67    #[test]
68    fn sanity() {
69        let domain = Domain::new("domain");
70        let name = StringHandle::new("task");
71        let _task = Task::begin(&domain, name);
72    }
73}