From 31bacde1fd61d2a678ecf2177deaac1e8b142d51 Mon Sep 17 00:00:00 2001 From: Will Killian Date: Tue, 26 Mar 2024 15:58:08 -0400 Subject: [PATCH 01/10] Update documentation (part 1) Signed-off-by: Will Killian --- README.md | 8 ++++++ src/category.rs | 4 ++- src/color.rs | 11 ++++++++ src/event_argument.rs | 24 +++++++++++++++-- src/event_attributes.rs | 59 +++++++++++++++++++++++++++++++++++++---- src/lib.rs | 37 ++++++++++++++++++++++++-- src/local_range.rs | 15 +++++++++++ src/message.rs | 3 +++ src/payload.rs | 21 ++++++++++----- src/range.rs | 15 +++++++++++ src/str.rs | 3 +++ src/sync.rs | 36 +++++++++++++++++++++++++ 12 files changed, 219 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 75ee8cc..5a6fe60 100644 --- a/README.md +++ b/README.md @@ -1 +1,9 @@ # nvtx-rs + +nvtx-rs provides Rust bindings for NVIDIA's nvtx library. + +See the generated documentation for more details and the examples for sample usage. + +## Compatibility + +The `nvtx-rs` crate requires rustc 1.70 or greater diff --git a/src/category.rs b/src/category.rs index f27deb1..08f400c 100644 --- a/src/category.rs +++ b/src/category.rs @@ -2,7 +2,7 @@ use std::sync::atomic::{AtomicU32, Ordering}; use crate::Str; -/// Represents a category for use with event and range grouping. See [`crate::register_category`], [`crate::register_categories`] +/// Represents a category for use with event and range grouping. See also: [`crate::register_category`], [`crate::register_categories`] #[derive(Debug, Clone, Copy)] pub struct Category { pub(super) id: u32, @@ -10,6 +10,8 @@ pub struct Category { impl Category { /// Create a new category not affiliated with any domain + /// + /// See [`Str`] for valid input types pub fn new(name: impl Into) -> Category { static COUNT: AtomicU32 = AtomicU32::new(0); let id: u32 = 1 + COUNT.fetch_add(1, Ordering::SeqCst); diff --git a/src/color.rs b/src/color.rs index e9fc0ee..04dc152 100644 --- a/src/color.rs +++ b/src/color.rs @@ -3,6 +3,17 @@ use crate::TypeValueEncodable; pub use color_name::colors::*; /// Represents a color in use for controlling appearance within NSight Systems +/// +/// ``` +/// // creation of a color from specific channel values: +/// let translucent_orange = nvtx::Color::new(255, 192, 0, 128); +/// +/// // creation of a color from pre-specified names: +/// #[cfg(feature = "color-name")] +/// let salmon : nvtx::Color = nvtx::colors::salmon.into(); +/// +/// // modification of a color after creation: +/// let translucent_salmon = salmon.with_alpha(128); #[derive(Debug, Clone, Copy)] pub struct Color { /// alpha channel diff --git a/src/event_argument.rs b/src/event_argument.rs index 4e7bafe..ae04726 100644 --- a/src/event_argument.rs +++ b/src/event_argument.rs @@ -1,8 +1,13 @@ -use crate::{EventAttributes, Message}; +use crate::{EventAttributes, Message, Str}; use std::ffi::{CStr, CString}; use widestring::WideCString; -/// Convenience wrapper for all valid argument types +/// Convenience wrapper for all valid argument types to ranges and marks +/// +/// * If a Rust string, it will automatically be converted into [`EventArgument::Unicode`] +/// * If a C string, it will automatically be converted into [`EventArgument::Ascii`] +/// * If a [`Str`], it will automatically be converted to its underlying active discriminant +/// * If an [`EventArgument::EventAttribute`] only specifies a [`Message`], it will automatically be converted into the message's underlying active discriminant #[derive(Debug, Clone)] pub enum EventArgument { /// discriminant for an owned ASCII string @@ -39,6 +44,12 @@ impl From<&str> for EventArgument { } } +impl From for EventArgument { + fn from(v: String) -> Self { + Self::Unicode(WideCString::from_str(v).expect("Could not convert to wide string")) + } +} + impl From for EventArgument { fn from(v: CString) -> Self { Self::Ascii(v) @@ -50,3 +61,12 @@ impl From<&CStr> for EventArgument { Self::Ascii(CString::from(v)) } } + +impl From for EventArgument { + fn from(value: Str) -> Self { + match value { + Str::Ascii(s) => Self::Ascii(s), + Str::Unicode(s) => Self::Unicode(s), + } + } +} diff --git a/src/event_attributes.rs b/src/event_attributes.rs index a69b486..0a23c11 100644 --- a/src/event_attributes.rs +++ b/src/event_attributes.rs @@ -45,6 +45,17 @@ impl EventAttributes { } /// Builder to facilitate easier construction of [`EventAttributes`] +/// +/// ``` +/// let cat = nvtx::Category::new("Category1"); +/// +/// let attr = nvtx::EventAttributesBuilder::default() +/// .category(&cat) +/// .color(nvtx::color::salmon) +/// .payload(3.141592) +/// .message("Hello") +/// .build(); +/// ``` #[derive(Debug, Clone, Default)] pub struct EventAttributesBuilder<'a> { pub(super) category: Option<&'a Category>, @@ -54,31 +65,69 @@ pub struct EventAttributesBuilder<'a> { } impl<'a> EventAttributesBuilder<'a> { - /// update the attribute's category + /// Update the builder's held [`Category`]. + /// + /// ``` + /// let cat = nvtx::Category::new("Category1"); + /// let attr = nvtx::EventAttributesBuilder::default() + /// // Sample usage for this API + /// .category(&cat) + /// .message("a simple range with category") + /// .build(); + /// let range = nvtx::Range::new(attr); + /// ``` pub fn category(mut self, category: &'a Category) -> EventAttributesBuilder<'a> { self.category = Some(category); self } - /// update the attribute's color + /// Update the builder's held [`Color`]. See [`Color`] for valid conversions. + /// + /// ``` + /// let builder = nvtx::EventAttributesBuilder::default() + /// // ... + /// let builder = builder.color(nvtx::color::white); + /// ``` pub fn color(mut self, color: impl Into) -> EventAttributesBuilder<'a> { self.color = Some(color.into()); self } - /// update the attribute's payload + /// Update the builder's held [`Payload`]. See [`Payload`] for valid conversions. + /// + /// ``` + /// let builder = nvtx::EventAttributesBuilder::default() + /// // ... + /// let builder = builder.payload(3.1415926535); + /// ``` pub fn payload(mut self, payload: impl Into) -> EventAttributesBuilder<'a> { self.payload = Some(payload.into()); self } - /// update the attribute's message + /// Update the the builder's held [`Message`]. See [`Message`] for valid conversions. + /// + /// ``` + /// let builder = nvtx::EventAttributesBuilder::default() + /// // ... + /// let builder = builder.message("test"); + /// ``` pub fn message(mut self, message: impl Into) -> EventAttributesBuilder<'a> { self.message = Some(message.into()); self } - /// build the attribute from the builder's state + /// Construct an [`EventAttributes`] from the builder's held state + /// + /// ``` + /// let cat = nvtx::Category::new("Category1"); + /// let attr = nvtx::EventAttributesBuilder::default() + /// .message("Example Range") + /// .color(nvtx::colors::blanchedalmond) + /// .category(&cat) + /// .payload(1234567) + /// .build(); + /// ``` pub fn build(self) -> EventAttributes { EventAttributes { category: self.category.copied(), diff --git a/src/lib.rs b/src/lib.rs index 8e2fad1..dfcf522 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,7 +38,16 @@ trait TypeValueEncodable { fn default_encoding() -> (Self::Type, Self::Value); } -/// Marks an instantaneous event in the application. A marker can contain a text message or specify additional information using the event attributes structure. These attributes include a text message, color, category, and a payload. Each of the attributes is optional. +/// Marks an instantaneous event in the application. +/// +/// A marker can contain a text message or specify additional information using the event attributes structure. These attributes include a text message, color, category, and a payload. Each of the attributes is optional. +/// ``` +/// nvtx::mark("Sample mark"); +/// +/// nvtx::mark(c"Another example"); +/// +/// nvtx::mark(nvtx::EventAttributeBuilder::default().message("Interesting example").color(nvtx::colors::red).build()); +/// ``` pub fn mark(argument: impl Into) { match argument.into() { EventArgument::Ascii(s) => unsafe { nvtx_sys::ffi::nvtxMarkA(s.as_ptr()) }, @@ -47,7 +56,16 @@ pub fn mark(argument: impl Into) { } } -/// Name an active thread of the current process. If an invalid thread ID is provided or a thread ID from a different process is used the behavior of the tool is implementation dependent. +/// Name an active thread of the current process. +/// +/// If an invalid thread ID is provided or a thread ID from a different process is used the behavior of the tool is implementation dependent. +/// +/// See [`Str`] for valid conversions +/// +/// Note: getting the native TID is not necessarily simple. If you are trying to name the current thread, please use [`name_current_thread`] +/// ``` +/// nvtx::name_thread(get_native_tid(), "My custom name"); +/// ``` pub fn name_thread(native_tid: u32, name: impl Into) { match name.into() { Str::Ascii(s) => unsafe { nvtx_sys::ffi::nvtxNameOsThreadA(native_tid, s.as_ptr()) }, @@ -59,6 +77,11 @@ pub fn name_thread(native_tid: u32, name: impl Into) { #[cfg(feature = "name-current-thread")] /// Name the current thread of the current process +/// +/// See [`Str`] for valid conversions +/// ``` +/// nvtx::name_current_thread("Main thread"); +/// ``` pub fn name_current_thread(name: impl Into) { let tid = gettid::gettid() as u32; match name.into() { @@ -68,11 +91,21 @@ pub fn name_current_thread(name: impl Into) { } /// Register a new category within the default (global) scope. Categories are used to group sets of events. +/// +/// See [`Str`] for valid conversions +/// ``` +/// let cat_a = nvtx::register_category("Category A"); +/// ``` pub fn register_category(name: impl Into) -> Category { Category::new(name) } /// Register many categories within the default (global) scope. Categories are used to group sets of events. +/// +/// See [`Str`] for valid conversions +/// ``` +/// let [cat_a, cat_b] = nvtx::register_categories(["Category A", "Category B"]); +/// ``` pub fn register_categories(names: [impl Into; C]) -> [Category; C] { names.map(register_category) } diff --git a/src/local_range.rs b/src/local_range.rs index 35e6454..620c39f 100644 --- a/src/local_range.rs +++ b/src/local_range.rs @@ -12,6 +12,21 @@ pub struct LocalRange { impl LocalRange { /// Create an RAII-friendly range type which (1) cannot be moved across thread boundaries and (2) automatically ended when dropped. Panics on drop() if the opening level doesn't match the closing level (since it must model a perfect stack). + /// + /// ``` + /// // creation from a unicode string + /// let range = nvtx::LocalRange::new("simple name"); + /// + /// // creation from a c string (from rust 1.77+) + /// let range = nvtx::LocalRange::new(c"simple name"); + /// + /// // creation from an EventAttribute + /// let attr = nvtx::EventAttributeBuilder::default().payload(1).message("complex range").build(); + /// let range = nvtx::LocalRange::new(attr); + /// + /// // explicitly end a range + /// drop(range) + /// ``` pub fn new(arg: impl Into) -> LocalRange { let argument = arg.into(); let level = match &argument { diff --git a/src/message.rs b/src/message.rs index ab759ac..cbf3512 100644 --- a/src/message.rs +++ b/src/message.rs @@ -3,6 +3,9 @@ use std::ffi::{CStr, CString}; use widestring::WideCString; /// Represents a message for use within events and ranges +/// +/// * [`Message::Ascii`] is the discriminator for C strings +/// * [`Message::Unicode`] is the discriminator for Rust strings #[derive(Debug, Clone)] pub enum Message { /// discriminant for an owned ASCII string diff --git a/src/payload.rs b/src/payload.rs index 5a64d26..252486d 100644 --- a/src/payload.rs +++ b/src/payload.rs @@ -1,19 +1,26 @@ use crate::TypeValueEncodable; -/// Represents a payload value for use within event attributes +/// Represents a payload value for use within [`crate::EventAttributes`] and [`crate::domain::EventAttributes`] +/// +/// * [`Payload::Float`] holds a 32-bit floating-point playload +/// * [`Payload::Double`] holds a 64-bit floating-point playload +/// * [`Payload::Int32`] holds a 32-bit integral playload +/// * [`Payload::Int64`] holds a 64-bit integral playload +/// * [`Payload::Uint32`] holds a 32-bit unsigned integral playload +/// * [`Payload::Uint64`] holds a 64-bit unsigned integral playload #[derive(Debug, Clone, Copy)] pub enum Payload { - /// the payload shall hold a 32-bit floating-point value + /// a 32-bit floating-point value Float(f32), - /// the payload shall hold a 64-bit floating-point value + /// a 64-bit floating-point value Double(f64), - /// the payload shall hold a 32-bit integral value + /// a 32-bit integral value Int32(i32), - /// the payload shall hold a 64-bit integral value + /// a 64-bit integral value Int64(i64), - /// the payload shall hold a 32-bit unsigned integral value + /// a 32-bit unsigned integral value Uint32(u32), - /// the payload shall hold a 64-bit unsigned integral value + /// a 64-bit unsigned integral value Uint64(u64), } diff --git a/src/range.rs b/src/range.rs index 834152e..327c885 100644 --- a/src/range.rs +++ b/src/range.rs @@ -8,6 +8,21 @@ pub struct Range { impl Range { /// Create an RAII-friendly range type which (1) can be moved across thread boundaries and (2) automatically ended when dropped + /// + /// ``` + /// // creation from a unicode string + /// let range = nvtx::Range::new("simple name"); + /// + /// // creation from a c string (from rust 1.77+) + /// let range = nvtx::Range::new(c"simple name"); + /// + /// // creation from an EventAttribute + /// let attr = nvtx::EventAttributeBuilder::default().payload(1).message("complex range").build(); + /// let range = nvtx::Range::new(attr); + /// + /// // explicitly end a range + /// drop(range) + /// ``` pub fn new(arg: impl Into) -> Range { let argument = arg.into(); let id = match &argument { diff --git a/src/str.rs b/src/str.rs index 365c296..8445166 100644 --- a/src/str.rs +++ b/src/str.rs @@ -2,6 +2,9 @@ use std::ffi::{CStr, CString}; use widestring::WideCString; /// A convenience wrapper for various string types +/// +/// * [`Str::Ascii`] is the discriminator for C string types +/// * [`Str::Unicode`] is the discriminator for Rust string types #[derive(Debug, Clone)] pub enum Str { /// Represents an ASCII friendly string diff --git a/src/sync.rs b/src/sync.rs index ecee43b..f360c10 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -8,6 +8,13 @@ pub struct UserSync<'a> { impl<'a> UserSync<'a> { /// Signal to tools that an attempt to acquire a user defined synchronization object. + /// + /// ``` + /// let d = nvtx::Domain::new("domain"); + /// let us = d.user_sync(); + /// // ... + /// let started = us.acquire(); + /// ``` #[must_use = "Dropping the return will violate the state machine"] pub fn acquire(self) -> UserSyncAcquireStart<'a> { unsafe { nvtx_sys::ffi::nvtxDomainSyncUserAcquireStart(self.handle) } @@ -28,6 +35,15 @@ pub struct UserSyncAcquireStart<'a> { impl<'a> UserSyncAcquireStart<'a> { /// Signal to tools of failure in acquiring a user defined synchronization object. + /// + /// ``` + /// let d = nvtx::Domain::new("domain"); + /// let us = d.user_sync(); + /// // ... + /// let started = us.acquire(); + /// // ... + /// let us2 = started.failed(); + /// ``` #[must_use = "Dropping the return will result in the Synchronization Object being destroyed"] pub fn failed(self) -> UserSync<'a> { unsafe { nvtx_sys::ffi::nvtxDomainSyncUserAcquireFailed(self.sync_object.handle) } @@ -35,6 +51,15 @@ impl<'a> UserSyncAcquireStart<'a> { } /// Signal to tools of success in acquiring a user defined synchronization object. + /// + /// ``` + /// let d = nvtx::Domain::new("domain"); + /// let us = d.user_sync(); + /// // ... + /// let started = us.acquire(); + /// // ... + /// let success = started.success(); + /// ``` #[must_use = "Dropping the return will violate the state machine"] pub fn success(self) -> UserSyncSuccess<'a> { unsafe { nvtx_sys::ffi::nvtxDomainSyncUserAcquireSuccess(self.sync_object.handle) } @@ -51,6 +76,17 @@ pub struct UserSyncSuccess<'a> { impl<'a> UserSyncSuccess<'a> { /// Signal to tools of releasing a reservation on user defined synchronization object. + /// + /// ``` + /// let d = nvtx::Domain::new("domain"); + /// let us = d.user_sync(); + /// // ... + /// let started = us.acquire(); + /// // ... + /// let success = started.success(); + /// // ... + /// let us2 = success.release(); + /// ``` #[must_use = "Dropping the return will result in the Synchronization Object being destroyed"] pub fn releasing(self) -> UserSync<'a> { unsafe { nvtx_sys::ffi::nvtxDomainSyncUserReleasing(self.sync_object.handle) } From 04a871afcf544c9b50c6678e7c6f76e6e6dee544 Mon Sep 17 00:00:00 2001 From: Will Killian Date: Tue, 26 Mar 2024 20:59:16 -0400 Subject: [PATCH 02/10] Add remaining documentation Signed-off-by: Will Killian --- src/category.rs | 2 +- src/domain.rs | 133 +++++++++++++++++++++++++++++---- src/domain/event_argument.rs | 45 ++++------- src/domain/event_attributes.rs | 71 +++++++++++++++++- src/domain/local_range.rs | 20 +---- src/domain/message.rs | 37 ++++----- src/domain/range.rs | 19 +---- src/event_argument.rs | 59 +++------------ src/event_attributes.rs | 20 +++-- src/lib.rs | 2 +- src/local_range.rs | 8 +- src/message.rs | 31 ++------ src/range.rs | 4 +- src/str.rs | 20 ++++- 14 files changed, 273 insertions(+), 198 deletions(-) diff --git a/src/category.rs b/src/category.rs index 08f400c..778e687 100644 --- a/src/category.rs +++ b/src/category.rs @@ -11,7 +11,7 @@ pub struct Category { impl Category { /// Create a new category not affiliated with any domain /// - /// See [`Str`] for valid input types + /// See [`Str`] for valid conversions pub fn new(name: impl Into) -> Category { static COUNT: AtomicU32 = AtomicU32::new(0); let id: u32 = 1 + COUNT.fetch_add(1, Ordering::SeqCst); diff --git a/src/domain.rs b/src/domain.rs index e436453..e7a0463 100644 --- a/src/domain.rs +++ b/src/domain.rs @@ -35,17 +35,31 @@ pub struct Domain { impl Domain { /// Register a NVTX domain - pub fn new(name: impl Into) -> Self { + /// + /// See [`Str`] for valid conversions + /// + /// ``` + /// let domain = nvtx::Domain::new("Domain"); + /// ``` + pub fn new<'a>(name: impl Into) -> Self { Domain { handle: match name.into() { - Str::Ascii(s) => unsafe { nvtx_sys::ffi::nvtxDomainCreateA(s.as_ptr()) }, - Str::Unicode(s) => unsafe { nvtx_sys::ffi::nvtxDomainCreateW(s.as_ptr().cast()) }, + crate::Str::Ascii(s) => unsafe { nvtx_sys::ffi::nvtxDomainCreateA(s.as_ptr()) }, + crate::Str::Unicode(s) => unsafe { + nvtx_sys::ffi::nvtxDomainCreateW(s.as_ptr().cast()) + }, }, registered_categories: AtomicU32::new(0), } } /// Gets a new builder instance for event attribute construction in the current domain + /// + /// ``` + /// let domain = nvtx::Domain::new("Domain"); + /// // ... + /// let builder = domain.event_attributes_builder(); + /// ``` pub fn event_attributes_builder(&self) -> EventAttributesBuilder<'_> { EventAttributesBuilder { domain: self, @@ -57,12 +71,22 @@ impl Domain { } /// Registers an immutable string within the current domain - pub fn register_string(&self, string: impl Into) -> RegisteredString<'_> { + /// + /// Returns a handle to the immutable string registered to nvtx. + /// + /// See [`Str`] for valid conversions + /// + /// ``` + /// let domain = nvtx::Domain::new("Domain"); + /// // ... + /// let my_str = domain.register_string("My immutable string"); + /// ``` + pub fn register_string(&self, string: impl Into) -> RegisteredString<'_> { let handle = match string.into() { - Str::Ascii(s) => unsafe { + crate::Str::Ascii(s) => unsafe { nvtx_sys::ffi::nvtxDomainRegisterStringA(self.handle, s.as_ptr()) }, - Str::Unicode(s) => unsafe { + crate::Str::Unicode(s) => unsafe { nvtx_sys::ffi::nvtxDomainRegisterStringW(self.handle, s.as_ptr().cast()) }, }; @@ -73,15 +97,35 @@ impl Domain { } /// Register many immutable strings within the current domain + /// + /// Returns an array of handles to the immutable strings registered to nvtx. + /// + /// See [`Str`] for valid conversions + /// + /// ``` + /// let domain = nvtx::Domain::new("Domain"); + /// // ... + /// let [a, b, c] = domain.register_strings(["A", "B", "C"]); + /// ``` pub fn register_strings( &self, - strings: [impl Into; N], + strings: [impl Into; N], ) -> [RegisteredString<'_>; N] { strings.map(|string| self.register_string(string)) } /// Register a new category within the domain. Categories are used to group sets of events. - pub fn register_category(&self, name: impl Into) -> Category<'_> { + /// + /// Returns a handle to the category registered to nvtx. + /// + /// See [`Str`] for valid conversions + /// + /// ``` + /// let domain = nvtx::Domain::new("Domain"); + /// // ... + /// let cat = domain.register_category("Category"); + /// ``` + pub fn register_category(&self, name: impl Into) -> Category<'_> { let id = 1 + self.registered_categories.fetch_add(1, Ordering::SeqCst); match name.into() { Str::Ascii(s) => unsafe { @@ -95,33 +139,90 @@ impl Domain { } /// Register new categories within the domain. Categories are used to group sets of events. + /// + /// Returns an array of handles to the categories registered to nvtx. + /// + /// See [`Str`] for valid conversions + /// + /// ``` + /// let domain = nvtx::Domain::new("Domain"); + /// // ... + /// let [cat_a, cat_b] = domain.register_categories(["CatA", "CatB"]); + /// ``` pub fn register_categories( &self, - names: [impl Into; N], + names: [impl Into; N], ) -> [Category<'_>; N] { names.map(|name| self.register_category(name)) } - /// Marks an instantaneous event in the application. A marker can contain a text message or specify additional information using the event attributes structure. These attributes include a text message, color, category, and a payload. Each of the attributes is optional. + /// Marks an instantaneous event in the application belonging to a domain. + /// + /// A marker can contain a text message or specify additional information using the event attributes structure. These attributes include a text message, color, category, and a payload. Each of the attributes is optional. + /// + /// ``` + /// let domain = nvtx::Domain::new("Domain"); + /// // ... + /// domain.mark("Sample mark"); + /// + /// domain.mark(c"Another example"); + /// + /// domain.mark(domain.event_attributes_builder().message("Interesting example").color(nvtx::colors::red).build()); + /// + /// let reg_str = domain.register_string("Registered String"); + /// domain.mark() + /// ``` pub fn mark<'a>(&'a self, arg: impl Into>) { - let attribute = match arg.into() { + let attribute: EventAttributes<'a> = match arg.into() { EventArgument::EventAttribute(attr) => attr, - EventArgument::Ascii(s) => self.event_attributes_builder().message(s).build(), - EventArgument::Unicode(s) => self - .event_attributes_builder() - .message(Message::Unicode(s)) - .build(), + EventArgument::Ascii(s) => Message::from(s).into(), + EventArgument::Unicode(s) => Message::from(s).into(), + EventArgument::Registered(s) => Message::from(s).into(), }; let encoded = attribute.encode(); unsafe { nvtx_sys::ffi::nvtxDomainMarkEx(self.handle, &encoded) } } /// Create an RAII-friendly, domain-owned range type which (1) cannot be moved across thread boundaries and (2) automatically ended when dropped. Panics on drop() if the opening level doesn't match the closing level (since it must model a perfect stack). + /// + /// ``` + /// let domain = nxtx::Domain::new("Domain"); + /// + /// // creation from Rust string + /// let range = domain.local_range("simple name"); + /// + /// // creation from C string (since 1.77) + /// let range = domain.local_range(c"simple name"); + /// + /// // creation from EventAttributes + /// let attr = domain.event_attributes_builder().payload(1).message("complex range").build(); + /// let range = domain.local_range(attr); + /// + /// // explicitly end a range + /// drop(range) + /// ``` pub fn local_range<'a>(&'a self, arg: impl Into>) -> LocalRange<'a> { LocalRange::new(arg, self) } /// Create an RAII-friendly, domain-owned range type which (1) can be moved across thread boundaries and (2) automatically ended when dropped + /// + /// ``` + /// let domain = nxtx::Domain::new("Domain"); + /// + /// // creation from a unicode string + /// let range = domain.range("simple name"); + /// + /// // creation from a c string (from rust 1.77+) + /// let range = domain.range(c"simple name"); + /// + /// // creation from EventAttributes + /// let attr = domain.event_attributes_builder().payload(1).message("complex range").build(); + /// let range = domain.range(attr); + /// + /// // explicitly end a range + /// drop(range) + /// ``` pub fn range<'a>(&'a self, arg: impl Into>) -> Range<'a> { Range::new(arg, self) } diff --git a/src/domain/event_argument.rs b/src/domain/event_argument.rs index d262bd4..2a1e11b 100644 --- a/src/domain/event_argument.rs +++ b/src/domain/event_argument.rs @@ -1,52 +1,33 @@ -use super::{event_attributes::EventAttributes, message::Message}; -use std::ffi::{CStr, CString}; +use super::{EventAttributes, RegisteredString}; +use std::ffi::CString; use widestring::WideCString; -/// Convenience wrapper for all valid argument types +/// Convenience wrapper for all valid argument types to ranges and marks +/// +/// * Any string type will be translated to [`EventArgument::Ascii`], [`EventArgument::Unicode`], or [`EventArgument::Registered`] depending on its type. +/// * If [`EventArgument::EventAttribute`] is the active discriminator and its held [`EventAttributes`] only specifies a message, it will automatically be converted into the message's underlying active discriminant. Otherwise, the existing [`EventAttributes`] will be used for the event. #[derive(Debug, Clone)] pub enum EventArgument<'a> { /// discriminant for an owned ASCII string Ascii(CString), /// discriminant for an owned Unicode string Unicode(WideCString), + /// discriminant for a referenced registered string + Registered(&'a RegisteredString<'a>), /// discriminant for a detailed Attribute EventAttribute(EventAttributes<'a>), } -impl<'a> From> for EventArgument<'a> { - fn from(value: EventAttributes<'a>) -> Self { - match value { +impl<'a, T: Into>> From for EventArgument<'a> { + fn from(value: T) -> Self { + match value.into() { EventAttributes { category: None, color: None, payload: None, - message: Some(Message::Ascii(s)), - } => EventArgument::Ascii(s), - EventAttributes { - category: None, - color: None, - payload: None, - message: Some(Message::Unicode(s)), - } => EventArgument::Unicode(s), + message: Some(m), + } => m.into(), attr => EventArgument::EventAttribute(attr), } } } - -impl From<&str> for EventArgument<'_> { - fn from(v: &str) -> Self { - Self::Unicode(WideCString::from_str(v).expect("Could not convert to wide string")) - } -} - -impl From for EventArgument<'_> { - fn from(v: CString) -> Self { - Self::Ascii(v) - } -} - -impl From<&CStr> for EventArgument<'_> { - fn from(v: &CStr) -> Self { - Self::Ascii(CString::from(v)) - } -} diff --git a/src/domain/event_attributes.rs b/src/domain/event_attributes.rs index e732ecf..24e136c 100644 --- a/src/domain/event_attributes.rs +++ b/src/domain/event_attributes.rs @@ -1,4 +1,4 @@ -use super::{category::Category, message::Message, Domain}; +use super::{Category, Domain, Message}; use crate::{Color, Payload, TypeValueEncodable}; /// All attributes that are associated with marks and ranges @@ -45,7 +45,29 @@ impl<'a> EventAttributes<'a> { } } +impl<'a, T: Into>> From for EventAttributes<'a> { + fn from(value: T) -> Self { + EventAttributes { + category: None, + color: None, + payload: None, + message: Some(value.into()), + } + } +} + /// Builder to facilitate easier construction of [`EventAttributes`] +/// +/// ``` +/// let cat = nvtx::Category::new("Category1"); +/// +/// let attr = nvtx::EventAttributesBuilder::default() +/// .category(&cat) +/// .color(nvtx::color::salmon) +/// .payload(3.141592) +/// .message("Hello") +/// .build(); +/// ``` #[derive(Debug, Clone)] pub struct EventAttributesBuilder<'a> { pub(super) domain: &'a Domain, @@ -57,6 +79,15 @@ pub struct EventAttributesBuilder<'a> { impl<'a> EventAttributesBuilder<'a> { /// Update the attribute's category. An assertion will be thrown if a Category is passed in whose domain is not the same as this builder + /// + /// ``` + /// let domain = nvtx::Domain::new("Domain"); + /// let cat = domain.register_category("Category1"); + /// // ... + /// let builder = domain.event_attributes_builder(); + /// // ... + /// let builder = builder.category(&cat); + /// ``` pub fn category(mut self, category: &'a Category<'a>) -> EventAttributesBuilder<'a> { assert!( std::ptr::eq(category.domain, self.domain), @@ -66,19 +97,40 @@ impl<'a> EventAttributesBuilder<'a> { self } - /// update the attribute's color + /// Update the builder's held [`Color`]. See [`Color`] for valid conversions. + /// + /// ``` + /// let domain = nvtx::Domain::new("Domain"); + /// let builder = domain.event_attributes_builder(); + /// // ... + /// let builder = builder.color(nvtx::color::white); + /// ``` pub fn color(mut self, color: impl Into) -> EventAttributesBuilder<'a> { self.color = Some(color.into()); self } - /// update the attribute's payload + /// Update the builder's held [`Payload`]. See [`Payload`] for valid conversions. + /// + /// ``` + /// let domain = nvtx::Domain::new("Domain"); + /// let builder = domain.event_attributes_builder(); + /// // ... + /// let builder = builder.payload(3.1415926535); + /// ``` pub fn payload(mut self, payload: impl Into) -> EventAttributesBuilder<'a> { self.payload = Some(payload.into()); self } /// Update the attribute's message. An assertion will be thrown if a RegisteredString is passed in whose domain is not the same as this builder + /// + /// ``` + /// let domain = nvtx::Domain::new("Domain"); + /// let builder = domain.event_attributes_builder(); + /// // ... + /// let builder = builder.message("test"); + /// ``` pub fn message(mut self, message: impl Into>) -> EventAttributesBuilder<'a> { let msg: Message = message.into(); if let Message::Registered(r) = &msg { @@ -91,7 +143,18 @@ impl<'a> EventAttributesBuilder<'a> { self } - /// build the attribute from the builder's state + /// Construct an [`EventAttributes`] from the builder's held state + /// + /// ``` + /// let domain = nvtx::domain::new("Domain"); + /// let cat = domain.register_category("Category1"); + /// let attr = domain.event_attributes_builder() + /// .message("Example Range") + /// .color(nvtx::colors::blanchedalmond) + /// .category(&cat) + /// .payload(1234567) + /// .build(); + /// ``` pub fn build(self) -> EventAttributes<'a> { EventAttributes { category: self.category.copied(), diff --git a/src/domain/local_range.rs b/src/domain/local_range.rs index 27d8883..19efd30 100644 --- a/src/domain/local_range.rs +++ b/src/domain/local_range.rs @@ -1,9 +1,6 @@ +use super::{Domain, EventArgument}; use std::marker::PhantomData; -use super::{ - event_argument::EventArgument, event_attributes::EventAttributes, message::Message, Domain, -}; - /// A RAII-like object for modeling callstack Ranges within a Domain #[derive(Debug)] pub struct LocalRange<'a> { @@ -18,18 +15,9 @@ impl<'a> LocalRange<'a> { let argument = arg.into(); let arg = match argument { EventArgument::EventAttribute(attr) => attr, - EventArgument::Ascii(s) => EventAttributes { - category: None, - color: None, - payload: None, - message: Some(Message::Ascii(s)), - }, - EventArgument::Unicode(s) => EventAttributes { - category: None, - color: None, - payload: None, - message: Some(Message::Unicode(s)), - }, + EventArgument::Ascii(s) => domain.event_attributes_builder().message(s).build(), + EventArgument::Unicode(s) => domain.event_attributes_builder().message(s).build(), + EventArgument::Registered(s) => domain.event_attributes_builder().message(s).build(), }; let level = unsafe { nvtx_sys::ffi::nvtxDomainRangePushEx(domain.handle, &arg.encode()) }; LocalRange { diff --git a/src/domain/message.rs b/src/domain/message.rs index ccdbad2..c09b0fa 100644 --- a/src/domain/message.rs +++ b/src/domain/message.rs @@ -1,9 +1,13 @@ -use super::registered_string::RegisteredString; -use crate::TypeValueEncodable; -use std::ffi::{CStr, CString}; +use super::RegisteredString; +use crate::{Str, TypeValueEncodable}; +use std::ffi::CString; use widestring::WideCString; /// Represents a message for use within events and ranges +/// +/// * [`Message::Ascii`] is the discriminator for C strings +/// * [`Message::Unicode`] is the discriminator for Rust strings +/// * [`Message::Registered`] is the discriminator for nvtx domain-registered strings #[derive(Debug, Clone)] pub enum Message<'a> { /// discriminant for an owned ASCII string @@ -20,27 +24,12 @@ impl<'a> From<&'a RegisteredString<'a>> for Message<'a> { } } -impl From for Message<'_> { - fn from(v: String) -> Self { - Self::Unicode(WideCString::from_str(v.as_str()).expect("Could not convert to wide string")) - } -} - -impl From<&str> for Message<'_> { - fn from(v: &str) -> Self { - Self::Unicode(WideCString::from_str(v).expect("Could not convert to wide string")) - } -} - -impl From for Message<'_> { - fn from(v: CString) -> Self { - Self::Ascii(v) - } -} - -impl From<&CStr> for Message<'_> { - fn from(v: &CStr) -> Self { - Self::Ascii(CString::from(v)) +impl<'a, T: Into> From for Message<'a> { + fn from(value: T) -> Self { + match value.into() { + Str::Ascii(s) => Message::Ascii(s), + Str::Unicode(s) => Message::Unicode(s), + } } } diff --git a/src/domain/range.rs b/src/domain/range.rs index d084691..cf966a1 100644 --- a/src/domain/range.rs +++ b/src/domain/range.rs @@ -1,6 +1,4 @@ -use super::{ - event_argument::EventArgument, event_attributes::EventAttributes, message::Message, Domain, -}; +use super::{Domain, EventArgument, Message}; /// A RAII-like object for modeling start/end Ranges within a Domain #[derive(Debug)] @@ -14,18 +12,9 @@ impl<'a> Range<'a> { let argument = arg.into(); let arg = match argument { EventArgument::EventAttribute(attr) => attr, - EventArgument::Ascii(s) => EventAttributes { - category: None, - color: None, - payload: None, - message: Some(Message::Ascii(s)), - }, - EventArgument::Unicode(s) => EventAttributes { - category: None, - color: None, - payload: None, - message: Some(Message::Unicode(s)), - }, + EventArgument::Ascii(s) => Message::from(s).into(), + EventArgument::Unicode(s) => Message::from(s).into(), + EventArgument::Registered(s) => Message::from(s).into(), }; let id = unsafe { nvtx_sys::ffi::nvtxDomainRangeStartEx(domain.handle, &arg.encode()) }; Range { id, domain } diff --git a/src/event_argument.rs b/src/event_argument.rs index ae04726..69187c2 100644 --- a/src/event_argument.rs +++ b/src/event_argument.rs @@ -1,13 +1,11 @@ -use crate::{EventAttributes, Message, Str}; -use std::ffi::{CStr, CString}; +use crate::EventAttributes; +use std::ffi::CString; use widestring::WideCString; /// Convenience wrapper for all valid argument types to ranges and marks /// -/// * If a Rust string, it will automatically be converted into [`EventArgument::Unicode`] -/// * If a C string, it will automatically be converted into [`EventArgument::Ascii`] -/// * If a [`Str`], it will automatically be converted to its underlying active discriminant -/// * If an [`EventArgument::EventAttribute`] only specifies a [`Message`], it will automatically be converted into the message's underlying active discriminant +/// * Any string type will be translated to [`EventArgument::Ascii`] or [`EventArgument::Unicode`] depending on its type. +/// * If [`EventArgument::EventAttribute`] is the active discriminator and its held [`EventAttributes`] only specifies a message, it will automatically be converted into the message's underlying active discriminant. Otherwise, the existing [`EventAttributes`] will be used for the event. #[derive(Debug, Clone)] pub enum EventArgument { /// discriminant for an owned ASCII string @@ -18,55 +16,16 @@ pub enum EventArgument { EventAttribute(EventAttributes), } -impl From for EventArgument { - fn from(value: EventAttributes) -> Self { - match value { +impl> From for EventArgument { + fn from(value: T) -> Self { + match value.into() { EventAttributes { category: None, color: None, payload: None, - message: Some(Message::Ascii(s)), - } => EventArgument::Ascii(s), - EventAttributes { - category: None, - color: None, - payload: None, - message: Some(Message::Unicode(s)), - } => EventArgument::Unicode(s), + message: Some(m), + } => m.into(), attr => EventArgument::EventAttribute(attr), } } } - -impl From<&str> for EventArgument { - fn from(v: &str) -> Self { - Self::Unicode(WideCString::from_str(v).expect("Could not convert to wide string")) - } -} - -impl From for EventArgument { - fn from(v: String) -> Self { - Self::Unicode(WideCString::from_str(v).expect("Could not convert to wide string")) - } -} - -impl From for EventArgument { - fn from(v: CString) -> Self { - Self::Ascii(v) - } -} - -impl From<&CStr> for EventArgument { - fn from(v: &CStr) -> Self { - Self::Ascii(CString::from(v)) - } -} - -impl From for EventArgument { - fn from(value: Str) -> Self { - match value { - Str::Ascii(s) => Self::Ascii(s), - Str::Unicode(s) => Self::Unicode(s), - } - } -} diff --git a/src/event_attributes.rs b/src/event_attributes.rs index 0a23c11..a426b11 100644 --- a/src/event_attributes.rs +++ b/src/event_attributes.rs @@ -44,6 +44,17 @@ impl EventAttributes { } } +impl> From for EventAttributes { + fn from(value: T) -> Self { + EventAttributes { + category: None, + color: None, + payload: None, + message: Some(value.into()), + } + } +} + /// Builder to facilitate easier construction of [`EventAttributes`] /// /// ``` @@ -69,12 +80,9 @@ impl<'a> EventAttributesBuilder<'a> { /// /// ``` /// let cat = nvtx::Category::new("Category1"); - /// let attr = nvtx::EventAttributesBuilder::default() - /// // Sample usage for this API - /// .category(&cat) - /// .message("a simple range with category") - /// .build(); - /// let range = nvtx::Range::new(attr); + /// let builder = nvtx::EventAttributesBuilder::default() + /// // ... + /// let builder = builder.category(&cat); /// ``` pub fn category(mut self, category: &'a Category) -> EventAttributesBuilder<'a> { self.category = Some(category); diff --git a/src/lib.rs b/src/lib.rs index dfcf522..749172f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,7 +46,7 @@ trait TypeValueEncodable { /// /// nvtx::mark(c"Another example"); /// -/// nvtx::mark(nvtx::EventAttributeBuilder::default().message("Interesting example").color(nvtx::colors::red).build()); +/// nvtx::mark(nvtx::EventAttributesBuilder::default().message("Interesting example").color(nvtx::colors::red).build()); /// ``` pub fn mark(argument: impl Into) { match argument.into() { diff --git a/src/local_range.rs b/src/local_range.rs index 620c39f..77851d7 100644 --- a/src/local_range.rs +++ b/src/local_range.rs @@ -14,14 +14,14 @@ impl LocalRange { /// Create an RAII-friendly range type which (1) cannot be moved across thread boundaries and (2) automatically ended when dropped. Panics on drop() if the opening level doesn't match the closing level (since it must model a perfect stack). /// /// ``` - /// // creation from a unicode string + /// // creation from Rust string /// let range = nvtx::LocalRange::new("simple name"); /// - /// // creation from a c string (from rust 1.77+) + /// // creation from C string (since 1.77) /// let range = nvtx::LocalRange::new(c"simple name"); /// - /// // creation from an EventAttribute - /// let attr = nvtx::EventAttributeBuilder::default().payload(1).message("complex range").build(); + /// // creation from EventAttributes + /// let attr = nvtx::EventAttributesBuilder::default().payload(1).message("complex range").build(); /// let range = nvtx::LocalRange::new(attr); /// /// // explicitly end a range diff --git a/src/message.rs b/src/message.rs index cbf3512..01564ad 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1,5 +1,5 @@ -use crate::TypeValueEncodable; -use std::ffi::{CStr, CString}; +use crate::{Str, TypeValueEncodable}; +use std::ffi::CString; use widestring::WideCString; /// Represents a message for use within events and ranges @@ -14,27 +14,12 @@ pub enum Message { Unicode(WideCString), } -impl From for Message { - fn from(v: String) -> Self { - Self::Unicode(WideCString::from_str(v.as_str()).expect("Could not convert to wide string")) - } -} - -impl From<&str> for Message { - fn from(v: &str) -> Self { - Self::Unicode(WideCString::from_str(v).expect("Could not convert to wide string")) - } -} - -impl From for Message { - fn from(v: CString) -> Self { - Self::Ascii(v) - } -} - -impl From<&CStr> for Message { - fn from(v: &CStr) -> Self { - Self::Ascii(CString::from(v)) +impl> From for Message { + fn from(value: T) -> Self { + match value.into() { + Str::Ascii(s) => Message::Ascii(s), + Str::Unicode(s) => Message::Unicode(s), + } } } diff --git a/src/range.rs b/src/range.rs index 327c885..e018b8c 100644 --- a/src/range.rs +++ b/src/range.rs @@ -16,8 +16,8 @@ impl Range { /// // creation from a c string (from rust 1.77+) /// let range = nvtx::Range::new(c"simple name"); /// - /// // creation from an EventAttribute - /// let attr = nvtx::EventAttributeBuilder::default().payload(1).message("complex range").build(); + /// // creation from EventAttributes + /// let attr = nvtx::EventAttributesBuilder::default().payload(1).message("complex range").build(); /// let range = nvtx::Range::new(attr); /// /// // explicitly end a range diff --git a/src/str.rs b/src/str.rs index 8445166..32ed25e 100644 --- a/src/str.rs +++ b/src/str.rs @@ -1,10 +1,10 @@ use std::ffi::{CStr, CString}; -use widestring::WideCString; +use widestring::{WideCStr, WideCString}; /// A convenience wrapper for various string types /// /// * [`Str::Ascii`] is the discriminator for C string types -/// * [`Str::Unicode`] is the discriminator for Rust string types +/// * [`Str::Unicode`] is the discriminator for Rust string types and C wide string types #[derive(Debug, Clone)] pub enum Str { /// Represents an ASCII friendly string @@ -21,7 +21,7 @@ impl From for Str { impl From<&str> for Str { fn from(v: &str) -> Self { - Self::Unicode(WideCString::from_str(v).expect("Could not convert to wide string")) + String::from(v).into() } } @@ -33,6 +33,18 @@ impl From for Str { impl From<&CStr> for Str { fn from(v: &CStr) -> Self { - Self::Ascii(CString::from(v)) + CString::from(v).into() + } +} + +impl From for Str { + fn from(v: WideCString) -> Self { + Self::Unicode(v) + } +} + +impl From<&WideCStr> for Str { + fn from(v: &WideCStr) -> Self { + WideCString::from(v).into() } } From 9c1436dd37357498164d8222fe2f0785b3a839c2 Mon Sep 17 00:00:00 2001 From: Will Killian Date: Tue, 26 Mar 2024 21:05:30 -0400 Subject: [PATCH 03/10] Fix doctest (pt 1) Signed-off-by: Will Killian --- src/color.rs | 2 +- src/domain.rs | 2 +- src/domain/event_attributes.rs | 2 +- src/event_attributes.rs | 2 +- src/lib.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/color.rs b/src/color.rs index 04dc152..15b30de 100644 --- a/src/color.rs +++ b/src/color.rs @@ -10,7 +10,7 @@ pub use color_name::colors::*; /// /// // creation of a color from pre-specified names: /// #[cfg(feature = "color-name")] -/// let salmon : nvtx::Color = nvtx::colors::salmon.into(); +/// let salmon : nvtx::Color = nvtx::color::salmon.into(); /// /// // modification of a color after creation: /// let translucent_salmon = salmon.with_alpha(128); diff --git a/src/domain.rs b/src/domain.rs index e7a0463..9397fd1 100644 --- a/src/domain.rs +++ b/src/domain.rs @@ -167,7 +167,7 @@ impl Domain { /// /// domain.mark(c"Another example"); /// - /// domain.mark(domain.event_attributes_builder().message("Interesting example").color(nvtx::colors::red).build()); + /// domain.mark(domain.event_attributes_builder().message("Interesting example").color(nvtx::color::red).build()); /// /// let reg_str = domain.register_string("Registered String"); /// domain.mark() diff --git a/src/domain/event_attributes.rs b/src/domain/event_attributes.rs index 24e136c..e2990ed 100644 --- a/src/domain/event_attributes.rs +++ b/src/domain/event_attributes.rs @@ -150,7 +150,7 @@ impl<'a> EventAttributesBuilder<'a> { /// let cat = domain.register_category("Category1"); /// let attr = domain.event_attributes_builder() /// .message("Example Range") - /// .color(nvtx::colors::blanchedalmond) + /// .color(nvtx::color::blanchedalmond) /// .category(&cat) /// .payload(1234567) /// .build(); diff --git a/src/event_attributes.rs b/src/event_attributes.rs index a426b11..e28ad5f 100644 --- a/src/event_attributes.rs +++ b/src/event_attributes.rs @@ -131,7 +131,7 @@ impl<'a> EventAttributesBuilder<'a> { /// let cat = nvtx::Category::new("Category1"); /// let attr = nvtx::EventAttributesBuilder::default() /// .message("Example Range") - /// .color(nvtx::colors::blanchedalmond) + /// .color(nvtx::color::blanchedalmond) /// .category(&cat) /// .payload(1234567) /// .build(); diff --git a/src/lib.rs b/src/lib.rs index 749172f..9b72ded 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,7 +46,7 @@ trait TypeValueEncodable { /// /// nvtx::mark(c"Another example"); /// -/// nvtx::mark(nvtx::EventAttributesBuilder::default().message("Interesting example").color(nvtx::colors::red).build()); +/// nvtx::mark(nvtx::EventAttributesBuilder::default().message("Interesting example").color(nvtx::color::red).build()); /// ``` pub fn mark(argument: impl Into) { match argument.into() { From 1c205bade07345f1b32837563bf19e0c4de830b1 Mon Sep 17 00:00:00 2001 From: Will Killian Date: Tue, 26 Mar 2024 21:12:34 -0400 Subject: [PATCH 04/10] Fix doctest (pt 2) Signed-off-by: Will Killian --- src/domain.rs | 6 +++--- src/domain/event_attributes.rs | 2 +- src/event_attributes.rs | 8 ++++---- src/lib.rs | 2 +- src/sync.rs | 8 ++++---- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/domain.rs b/src/domain.rs index 9397fd1..43065c1 100644 --- a/src/domain.rs +++ b/src/domain.rs @@ -170,7 +170,7 @@ impl Domain { /// domain.mark(domain.event_attributes_builder().message("Interesting example").color(nvtx::color::red).build()); /// /// let reg_str = domain.register_string("Registered String"); - /// domain.mark() + /// domain.mark(®_str); /// ``` pub fn mark<'a>(&'a self, arg: impl Into>) { let attribute: EventAttributes<'a> = match arg.into() { @@ -186,7 +186,7 @@ impl Domain { /// Create an RAII-friendly, domain-owned range type which (1) cannot be moved across thread boundaries and (2) automatically ended when dropped. Panics on drop() if the opening level doesn't match the closing level (since it must model a perfect stack). /// /// ``` - /// let domain = nxtx::Domain::new("Domain"); + /// let domain = nvtx::Domain::new("Domain"); /// /// // creation from Rust string /// let range = domain.local_range("simple name"); @@ -208,7 +208,7 @@ impl Domain { /// Create an RAII-friendly, domain-owned range type which (1) can be moved across thread boundaries and (2) automatically ended when dropped /// /// ``` - /// let domain = nxtx::Domain::new("Domain"); + /// let domain = nvtx::Domain::new("Domain"); /// /// // creation from a unicode string /// let range = domain.range("simple name"); diff --git a/src/domain/event_attributes.rs b/src/domain/event_attributes.rs index e2990ed..734ad37 100644 --- a/src/domain/event_attributes.rs +++ b/src/domain/event_attributes.rs @@ -146,7 +146,7 @@ impl<'a> EventAttributesBuilder<'a> { /// Construct an [`EventAttributes`] from the builder's held state /// /// ``` - /// let domain = nvtx::domain::new("Domain"); + /// let domain = nvtx::Domain::new("Domain"); /// let cat = domain.register_category("Category1"); /// let attr = domain.event_attributes_builder() /// .message("Example Range") diff --git a/src/event_attributes.rs b/src/event_attributes.rs index e28ad5f..9e84768 100644 --- a/src/event_attributes.rs +++ b/src/event_attributes.rs @@ -80,7 +80,7 @@ impl<'a> EventAttributesBuilder<'a> { /// /// ``` /// let cat = nvtx::Category::new("Category1"); - /// let builder = nvtx::EventAttributesBuilder::default() + /// let builder = nvtx::EventAttributesBuilder::default(); /// // ... /// let builder = builder.category(&cat); /// ``` @@ -92,7 +92,7 @@ impl<'a> EventAttributesBuilder<'a> { /// Update the builder's held [`Color`]. See [`Color`] for valid conversions. /// /// ``` - /// let builder = nvtx::EventAttributesBuilder::default() + /// let builder = nvtx::EventAttributesBuilder::default(); /// // ... /// let builder = builder.color(nvtx::color::white); /// ``` @@ -104,7 +104,7 @@ impl<'a> EventAttributesBuilder<'a> { /// Update the builder's held [`Payload`]. See [`Payload`] for valid conversions. /// /// ``` - /// let builder = nvtx::EventAttributesBuilder::default() + /// let builder = nvtx::EventAttributesBuilder::default(); /// // ... /// let builder = builder.payload(3.1415926535); /// ``` @@ -116,7 +116,7 @@ impl<'a> EventAttributesBuilder<'a> { /// Update the the builder's held [`Message`]. See [`Message`] for valid conversions. /// /// ``` - /// let builder = nvtx::EventAttributesBuilder::default() + /// let builder = nvtx::EventAttributesBuilder::default(); /// // ... /// let builder = builder.message("test"); /// ``` diff --git a/src/lib.rs b/src/lib.rs index 9b72ded..8d4a43a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,7 +64,7 @@ pub fn mark(argument: impl Into) { /// /// Note: getting the native TID is not necessarily simple. If you are trying to name the current thread, please use [`name_current_thread`] /// ``` -/// nvtx::name_thread(get_native_tid(), "My custom name"); +/// nvtx::name_thread(12345, "My custom name"); /// ``` pub fn name_thread(native_tid: u32, name: impl Into) { match name.into() { diff --git a/src/sync.rs b/src/sync.rs index f360c10..8ee02b1 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -11,7 +11,7 @@ impl<'a> UserSync<'a> { /// /// ``` /// let d = nvtx::Domain::new("domain"); - /// let us = d.user_sync(); + /// let us = d.user_sync("custom object"); /// // ... /// let started = us.acquire(); /// ``` @@ -38,7 +38,7 @@ impl<'a> UserSyncAcquireStart<'a> { /// /// ``` /// let d = nvtx::Domain::new("domain"); - /// let us = d.user_sync(); + /// let us = d.user_sync("custom object"); /// // ... /// let started = us.acquire(); /// // ... @@ -54,7 +54,7 @@ impl<'a> UserSyncAcquireStart<'a> { /// /// ``` /// let d = nvtx::Domain::new("domain"); - /// let us = d.user_sync(); + /// let us = d.user_sync("custom object"); /// // ... /// let started = us.acquire(); /// // ... @@ -79,7 +79,7 @@ impl<'a> UserSyncSuccess<'a> { /// /// ``` /// let d = nvtx::Domain::new("domain"); - /// let us = d.user_sync(); + /// let us = d.user_sync("custom object"); /// // ... /// let started = us.acquire(); /// // ... From f3acf4e30ecaa0ef23aa1f8609795eff7f8bb7a7 Mon Sep 17 00:00:00 2001 From: Will Killian Date: Tue, 26 Mar 2024 21:27:56 -0400 Subject: [PATCH 05/10] Fix doctest (pt 3) Signed-off-by: Will Killian --- examples/domain.rs | 2 +- examples/range.rs | 6 +++--- src/domain/local_range.rs | 10 ++-------- src/local_range.rs | 9 +++------ src/sync.rs | 2 +- 5 files changed, 10 insertions(+), 19 deletions(-) diff --git a/examples/domain.rs b/examples/domain.rs index 0c84f9c..cfd43d3 100644 --- a/examples/domain.rs +++ b/examples/domain.rs @@ -26,7 +26,7 @@ fn main() { thread::sleep(time::Duration::from_millis(10)); let yy = xx.success(); thread::sleep(time::Duration::from_millis(10)); - let zz = yy.releasing(); + let zz = yy.release(); drop(zz); thread::sleep(time::Duration::from_millis(10)); diff --git a/examples/range.rs b/examples/range.rs index fb7c8cd..874e18e 100644 --- a/examples/range.rs +++ b/examples/range.rs @@ -3,7 +3,7 @@ use std::{thread, time}; fn main() { // we must hold ranges with a proper name // _ will not work since drop() is called immediately - let _x = nvtx::Range::new( + let _x = nvtx::LocalRange::new( nvtx::EventAttributesBuilder::default() .color(nvtx::color::salmon) .message("Start 🦀") @@ -12,7 +12,7 @@ fn main() { thread::sleep(time::Duration::from_millis(5)); for i in 1..=10 { { - let _rng = nvtx::Range::new( + let _rng = nvtx::LocalRange::new( nvtx::EventAttributesBuilder::default() .color(nvtx::color::cornflowerblue) .message(format!("Iteration Number {}", i)) @@ -21,7 +21,7 @@ fn main() { ); for j in 1..=i { { - let _r = nvtx::Range::new( + let _r = nvtx::LocalRange::new( nvtx::EventAttributesBuilder::default() .color(nvtx::color::beige) .payload(j) diff --git a/src/domain/local_range.rs b/src/domain/local_range.rs index 19efd30..b6b1365 100644 --- a/src/domain/local_range.rs +++ b/src/domain/local_range.rs @@ -4,7 +4,6 @@ use std::marker::PhantomData; /// A RAII-like object for modeling callstack Ranges within a Domain #[derive(Debug)] pub struct LocalRange<'a> { - pub(super) level: i32, pub(super) domain: &'a Domain, // prevent Sync + Send _phantom: PhantomData<*mut i32>, @@ -19,9 +18,8 @@ impl<'a> LocalRange<'a> { EventArgument::Unicode(s) => domain.event_attributes_builder().message(s).build(), EventArgument::Registered(s) => domain.event_attributes_builder().message(s).build(), }; - let level = unsafe { nvtx_sys::ffi::nvtxDomainRangePushEx(domain.handle, &arg.encode()) }; + unsafe { nvtx_sys::ffi::nvtxDomainRangePushEx(domain.handle, &arg.encode()) }; LocalRange { - level, domain, _phantom: PhantomData, } @@ -30,10 +28,6 @@ impl<'a> LocalRange<'a> { impl<'a> Drop for LocalRange<'a> { fn drop(&mut self) { - let end_level = unsafe { nvtx_sys::ffi::nvtxDomainRangePop(self.domain.handle) }; - assert_eq!( - self.level, end_level, - "Mismatch on levels for domain::LocalRange" - ); + unsafe { nvtx_sys::ffi::nvtxDomainRangePop(self.domain.handle) }; } } diff --git a/src/local_range.rs b/src/local_range.rs index 77851d7..c215d6c 100644 --- a/src/local_range.rs +++ b/src/local_range.rs @@ -5,13 +5,12 @@ use crate::event_argument::EventArgument; /// A RAII-like object for modeling callstack Ranges #[derive(Debug)] pub struct LocalRange { - level: i32, // prevent Sync + Send _phantom: PhantomData<*mut i32>, } impl LocalRange { - /// Create an RAII-friendly range type which (1) cannot be moved across thread boundaries and (2) automatically ended when dropped. Panics on drop() if the opening level doesn't match the closing level (since it must model a perfect stack). + /// Create an RAII-friendly range type which (1) cannot be moved across thread boundaries and (2) automatically ended when dropped. /// /// ``` /// // creation from Rust string @@ -29,7 +28,7 @@ impl LocalRange { /// ``` pub fn new(arg: impl Into) -> LocalRange { let argument = arg.into(); - let level = match &argument { + match &argument { EventArgument::Ascii(s) => unsafe { nvtx_sys::ffi::nvtxRangePushA(s.as_ptr()) }, EventArgument::Unicode(s) => unsafe { nvtx_sys::ffi::nvtxRangePushW(s.as_ptr().cast()) @@ -39,7 +38,6 @@ impl LocalRange { }, }; LocalRange { - level, _phantom: PhantomData, } } @@ -47,7 +45,6 @@ impl LocalRange { impl Drop for LocalRange { fn drop(&mut self) { - let end_level = unsafe { nvtx_sys::ffi::nvtxRangePop() }; - assert_eq!(self.level, end_level, "Mismatch on levels for LocalRange"); + unsafe { nvtx_sys::ffi::nvtxRangePop() }; } } diff --git a/src/sync.rs b/src/sync.rs index 8ee02b1..ecb1e88 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -88,7 +88,7 @@ impl<'a> UserSyncSuccess<'a> { /// let us2 = success.release(); /// ``` #[must_use = "Dropping the return will result in the Synchronization Object being destroyed"] - pub fn releasing(self) -> UserSync<'a> { + pub fn release(self) -> UserSync<'a> { unsafe { nvtx_sys::ffi::nvtxDomainSyncUserReleasing(self.sync_object.handle) } self.sync_object } From cef00d6c62ecaa601ef7c676136cf2554d5393b4 Mon Sep 17 00:00:00 2001 From: Will Killian Date: Wed, 27 Mar 2024 06:57:12 -0400 Subject: [PATCH 06/10] Update simple range example Signed-off-by: Will Killian --- examples/range.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/examples/range.rs b/examples/range.rs index 874e18e..0c11508 100644 --- a/examples/range.rs +++ b/examples/range.rs @@ -3,12 +3,7 @@ use std::{thread, time}; fn main() { // we must hold ranges with a proper name // _ will not work since drop() is called immediately - let _x = nvtx::LocalRange::new( - nvtx::EventAttributesBuilder::default() - .color(nvtx::color::salmon) - .message("Start 🦀") - .build(), - ); + let _x = nvtx::LocalRange::new("Start"); thread::sleep(time::Duration::from_millis(5)); for i in 1..=10 { { From d64c560d0841b10288fba92db9e5668eb10f48cc Mon Sep 17 00:00:00 2001 From: Will Killian Date: Wed, 27 Mar 2024 07:13:54 -0400 Subject: [PATCH 07/10] Fix doctest Signed-off-by: Will Killian --- examples/range.rs | 2 +- src/domain/event_argument.rs | 20 +++++++++++++------- src/domain/local_range.rs | 3 +-- src/domain/message.rs | 6 +++--- src/event_argument.rs | 18 +++++++++++------- src/local_range.rs | 3 +-- src/message.rs | 4 ++-- 7 files changed, 32 insertions(+), 24 deletions(-) diff --git a/examples/range.rs b/examples/range.rs index 0c11508..0975e03 100644 --- a/examples/range.rs +++ b/examples/range.rs @@ -3,7 +3,7 @@ use std::{thread, time}; fn main() { // we must hold ranges with a proper name // _ will not work since drop() is called immediately - let _x = nvtx::LocalRange::new("Start"); + let _x = nvtx::LocalRange::new("Start 🦀"); thread::sleep(time::Duration::from_millis(5)); for i in 1..=10 { { diff --git a/src/domain/event_argument.rs b/src/domain/event_argument.rs index 2a1e11b..6078def 100644 --- a/src/domain/event_argument.rs +++ b/src/domain/event_argument.rs @@ -1,20 +1,22 @@ -use super::{EventAttributes, RegisteredString}; +use super::{EventAttributes, Message, RegisteredString}; use std::ffi::CString; use widestring::WideCString; /// Convenience wrapper for all valid argument types to ranges and marks /// /// * Any string type will be translated to [`EventArgument::Ascii`], [`EventArgument::Unicode`], or [`EventArgument::Registered`] depending on its type. -/// * If [`EventArgument::EventAttribute`] is the active discriminator and its held [`EventAttributes`] only specifies a message, it will automatically be converted into the message's underlying active discriminant. Otherwise, the existing [`EventAttributes`] will be used for the event. +/// * If [`EventArgument::EventAttribute`] is the active discriminator: +/// - The if its held [`EventAttributes`] only specifies a message, it will be converted into the message's active discriminator. +/// - Otherwise, the existing [`EventAttributes`] will be used for the event. #[derive(Debug, Clone)] pub enum EventArgument<'a> { - /// discriminant for an owned ASCII string + /// discriminator for an owned ASCII string Ascii(CString), - /// discriminant for an owned Unicode string + /// discriminator for an owned Unicode string Unicode(WideCString), - /// discriminant for a referenced registered string + /// discriminator for a referenced registered string Registered(&'a RegisteredString<'a>), - /// discriminant for a detailed Attribute + /// discriminator for a detailed Attribute EventAttribute(EventAttributes<'a>), } @@ -26,7 +28,11 @@ impl<'a, T: Into>> From for EventArgument<'a> { color: None, payload: None, message: Some(m), - } => m.into(), + } => match m { + Message::Ascii(s) => EventArgument::Ascii(s), + Message::Unicode(s) => EventArgument::Unicode(s), + Message::Registered(s) => EventArgument::Registered(s), + }, attr => EventArgument::EventAttribute(attr), } } diff --git a/src/domain/local_range.rs b/src/domain/local_range.rs index b6b1365..ba6b255 100644 --- a/src/domain/local_range.rs +++ b/src/domain/local_range.rs @@ -11,8 +11,7 @@ pub struct LocalRange<'a> { impl<'a> LocalRange<'a> { pub(super) fn new(arg: impl Into>, domain: &'a Domain) -> LocalRange<'a> { - let argument = arg.into(); - let arg = match argument { + let arg = match arg.into() { EventArgument::EventAttribute(attr) => attr, EventArgument::Ascii(s) => domain.event_attributes_builder().message(s).build(), EventArgument::Unicode(s) => domain.event_attributes_builder().message(s).build(), diff --git a/src/domain/message.rs b/src/domain/message.rs index c09b0fa..c1bf934 100644 --- a/src/domain/message.rs +++ b/src/domain/message.rs @@ -10,11 +10,11 @@ use widestring::WideCString; /// * [`Message::Registered`] is the discriminator for nvtx domain-registered strings #[derive(Debug, Clone)] pub enum Message<'a> { - /// discriminant for an owned ASCII string + /// discriminator for an owned ASCII string Ascii(CString), - /// discriminant for an owned Unicode string + /// discriminator for an owned Unicode string Unicode(WideCString), - /// discriminant for a registered string belonging to a domain + /// discriminator for a registered string belonging to a domain Registered(&'a RegisteredString<'a>), } diff --git a/src/event_argument.rs b/src/event_argument.rs index 69187c2..d785d5c 100644 --- a/src/event_argument.rs +++ b/src/event_argument.rs @@ -1,18 +1,19 @@ -use crate::EventAttributes; +use crate::{EventAttributes, Message}; use std::ffi::CString; use widestring::WideCString; /// Convenience wrapper for all valid argument types to ranges and marks /// /// * Any string type will be translated to [`EventArgument::Ascii`] or [`EventArgument::Unicode`] depending on its type. -/// * If [`EventArgument::EventAttribute`] is the active discriminator and its held [`EventAttributes`] only specifies a message, it will automatically be converted into the message's underlying active discriminant. Otherwise, the existing [`EventAttributes`] will be used for the event. -#[derive(Debug, Clone)] +/// * If [`EventArgument::EventAttribute`] is the active discriminator: +/// - Then if its held [`EventAttributes`] only specifies a message, it will be converted into the message's active discriminator. +/// - Otherwise, the existing [`EventAttributes`] will be used for the event.#[derive(Debug, Clone)] pub enum EventArgument { - /// discriminant for an owned ASCII string + /// discriminator for an owned ASCII string Ascii(CString), - /// discriminant for an owned Unicode string + /// discriminator for an owned Unicode string Unicode(WideCString), - /// discriminant for a detailed Attribute + /// discriminator for a detailed Attribute EventAttribute(EventAttributes), } @@ -24,7 +25,10 @@ impl> From for EventArgument { color: None, payload: None, message: Some(m), - } => m.into(), + } => match m { + Message::Ascii(s) => EventArgument::Ascii(s), + Message::Unicode(s) => EventArgument::Unicode(s), + }, attr => EventArgument::EventAttribute(attr), } } diff --git a/src/local_range.rs b/src/local_range.rs index c215d6c..0098820 100644 --- a/src/local_range.rs +++ b/src/local_range.rs @@ -27,8 +27,7 @@ impl LocalRange { /// drop(range) /// ``` pub fn new(arg: impl Into) -> LocalRange { - let argument = arg.into(); - match &argument { + match arg.into() { EventArgument::Ascii(s) => unsafe { nvtx_sys::ffi::nvtxRangePushA(s.as_ptr()) }, EventArgument::Unicode(s) => unsafe { nvtx_sys::ffi::nvtxRangePushW(s.as_ptr().cast()) diff --git a/src/message.rs b/src/message.rs index 01564ad..2ae1e1c 100644 --- a/src/message.rs +++ b/src/message.rs @@ -8,9 +8,9 @@ use widestring::WideCString; /// * [`Message::Unicode`] is the discriminator for Rust strings #[derive(Debug, Clone)] pub enum Message { - /// discriminant for an owned ASCII string + /// discriminator for an owned ASCII string Ascii(CString), - /// discriminant for an owned Unicode string + /// discriminator for an owned Unicode string Unicode(WideCString), } From e1ab7f5566b1778e6444f31a14738464fb0fe6ca Mon Sep 17 00:00:00 2001 From: Will Killian Date: Wed, 27 Mar 2024 07:20:06 -0400 Subject: [PATCH 08/10] Move sync to more appropriate location Signed-off-by: Will Killian --- src/domain.rs | 21 +++++++++++---------- src/{ => domain}/sync.rs | 0 src/lib.rs | 2 -- src/local_range.rs | 2 +- src/range.rs | 2 +- 5 files changed, 13 insertions(+), 14 deletions(-) rename src/{ => domain}/sync.rs (100%) diff --git a/src/domain.rs b/src/domain.rs index 43065c1..acd1c04 100644 --- a/src/domain.rs +++ b/src/domain.rs @@ -9,7 +9,6 @@ pub use self::{ registered_string::RegisteredString, resource::Resource, }; -pub use crate::sync; use crate::{Str, TypeValueEncodable}; use std::{ marker::PhantomData, @@ -25,6 +24,8 @@ mod message; mod range; mod registered_string; mod resource; +/// user-defined synchronization objects +pub mod sync; /// Represents a domain for high-level grouping #[derive(Debug)] @@ -41,11 +42,11 @@ impl Domain { /// ``` /// let domain = nvtx::Domain::new("Domain"); /// ``` - pub fn new<'a>(name: impl Into) -> Self { + pub fn new<'a>(name: impl Into) -> Self { Domain { handle: match name.into() { - crate::Str::Ascii(s) => unsafe { nvtx_sys::ffi::nvtxDomainCreateA(s.as_ptr()) }, - crate::Str::Unicode(s) => unsafe { + Str::Ascii(s) => unsafe { nvtx_sys::ffi::nvtxDomainCreateA(s.as_ptr()) }, + Str::Unicode(s) => unsafe { nvtx_sys::ffi::nvtxDomainCreateW(s.as_ptr().cast()) }, }, @@ -81,12 +82,12 @@ impl Domain { /// // ... /// let my_str = domain.register_string("My immutable string"); /// ``` - pub fn register_string(&self, string: impl Into) -> RegisteredString<'_> { + pub fn register_string(&self, string: impl Into) -> RegisteredString<'_> { let handle = match string.into() { - crate::Str::Ascii(s) => unsafe { + Str::Ascii(s) => unsafe { nvtx_sys::ffi::nvtxDomainRegisterStringA(self.handle, s.as_ptr()) }, - crate::Str::Unicode(s) => unsafe { + Str::Unicode(s) => unsafe { nvtx_sys::ffi::nvtxDomainRegisterStringW(self.handle, s.as_ptr().cast()) }, }; @@ -109,7 +110,7 @@ impl Domain { /// ``` pub fn register_strings( &self, - strings: [impl Into; N], + strings: [impl Into; N], ) -> [RegisteredString<'_>; N] { strings.map(|string| self.register_string(string)) } @@ -125,7 +126,7 @@ impl Domain { /// // ... /// let cat = domain.register_category("Category"); /// ``` - pub fn register_category(&self, name: impl Into) -> Category<'_> { + pub fn register_category(&self, name: impl Into) -> Category<'_> { let id = 1 + self.registered_categories.fetch_add(1, Ordering::SeqCst); match name.into() { Str::Ascii(s) => unsafe { @@ -151,7 +152,7 @@ impl Domain { /// ``` pub fn register_categories( &self, - names: [impl Into; N], + names: [impl Into; N], ) -> [Category<'_>; N] { names.map(|name| self.register_category(name)) } diff --git a/src/sync.rs b/src/domain/sync.rs similarity index 100% rename from src/sync.rs rename to src/domain/sync.rs diff --git a/src/lib.rs b/src/lib.rs index 8d4a43a..10115a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,8 +19,6 @@ pub use crate::{ pub mod color; /// specialized types for use within a domain context pub mod domain; -/// user-defined synchronization objects -pub mod sync; mod category; mod event_argument; diff --git a/src/local_range.rs b/src/local_range.rs index 0098820..c6c7ceb 100644 --- a/src/local_range.rs +++ b/src/local_range.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; -use crate::event_argument::EventArgument; +use crate::EventArgument; /// A RAII-like object for modeling callstack Ranges #[derive(Debug)] diff --git a/src/range.rs b/src/range.rs index e018b8c..c28748a 100644 --- a/src/range.rs +++ b/src/range.rs @@ -1,4 +1,4 @@ -use crate::event_argument::EventArgument; +use crate::EventArgument; /// A RAII-like object for modeling start/end Ranges #[derive(Debug)] From 2e4c963f3b0282373ebd91748c5ac3501a4b735b Mon Sep 17 00:00:00 2001 From: Will Killian Date: Wed, 27 Mar 2024 07:51:37 -0400 Subject: [PATCH 09/10] Improve API internals; add more documentation Signed-off-by: Will Killian --- src/category.rs | 3 +-- src/color.rs | 32 ++++++++++++++++++++++++- src/domain.rs | 35 +++++++++++++-------------- src/domain/event_argument.rs | 30 ++++++++--------------- src/domain/local_range.rs | 6 ++--- src/domain/message.rs | 4 ++-- src/domain/range.rs | 11 ++++----- src/event_argument.rs | 28 +++++++++------------- src/lib.rs | 46 +++++++++++++++++++++++------------- src/local_range.rs | 12 ++++------ src/message.rs | 4 ++-- src/range.rs | 12 ++++------ 12 files changed, 119 insertions(+), 104 deletions(-) diff --git a/src/category.rs b/src/category.rs index 778e687..c7dba34 100644 --- a/src/category.rs +++ b/src/category.rs @@ -1,6 +1,5 @@ -use std::sync::atomic::{AtomicU32, Ordering}; - use crate::Str; +use std::sync::atomic::{AtomicU32, Ordering}; /// Represents a category for use with event and range grouping. See also: [`crate::register_category`], [`crate::register_categories`] #[derive(Debug, Clone, Copy)] diff --git a/src/color.rs b/src/color.rs index 15b30de..f99634f 100644 --- a/src/color.rs +++ b/src/color.rs @@ -1,4 +1,5 @@ use crate::TypeValueEncodable; + #[cfg(feature = "color-name")] pub use color_name::colors::*; @@ -13,7 +14,12 @@ pub use color_name::colors::*; /// let salmon : nvtx::Color = nvtx::color::salmon.into(); /// /// // modification of a color after creation: +/// +/// let opaque_orange = translucent_orange.with_alpha(255); +/// +/// #[cfg(feature = "color-name")] /// let translucent_salmon = salmon.with_alpha(128); +/// #[derive(Debug, Clone, Copy)] pub struct Color { /// alpha channel @@ -39,26 +45,50 @@ impl From<[u8; 3]> for Color { impl Color { /// Create a new color from specified channels - pub fn new(a: u8, r: u8, g: u8, b: u8) -> Self { + /// + /// ``` + /// let nice_blue = nvtx::Color::new(0, 192, 255, 255); + /// ``` + pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self { Self { a, r, g, b } } /// Change the alpha channel for the color and yield a new color + /// + /// ``` + /// let nice_blue = nvtx::Color::new(0, 192, 255, 255); + /// let translucent_blue = nice_blue.with_alpha(128); + /// ``` pub fn with_alpha(&self, a: u8) -> Self { Color { a, ..*self } } /// Change the red channel for the color and yield a new color + /// + /// ``` + /// let dark_gray = nvtx::Color::new(32, 32, 32, 255); + /// let dark_red = dark_gray.with_red(128); + /// ``` pub fn with_red(&self, r: u8) -> Self { Color { r, ..*self } } /// Change the green channel for the color and yield a new color + /// + /// ``` + /// let dark_gray = nvtx::Color::new(32, 32, 32, 255); + /// let dark_green = dark_gray.with_green(128); + /// ``` pub fn with_green(&self, g: u8) -> Self { Color { g, ..*self } } /// Change the blue channel for the color and yield a new color + /// + /// ``` + /// let dark_gray = nvtx::Color::new(32, 32, 32, 255); + /// let dark_blue = dark_gray.with_blue(128); + /// ``` pub fn with_blue(&self, b: u8) -> Self { Color { b, ..*self } } diff --git a/src/domain.rs b/src/domain.rs index acd1c04..1e48a39 100644 --- a/src/domain.rs +++ b/src/domain.rs @@ -1,14 +1,3 @@ -pub use self::{ - category::Category, - event_argument::EventArgument, - event_attributes::{EventAttributes, EventAttributesBuilder}, - identifier::Identifier, - local_range::LocalRange, - message::Message, - range::Range, - registered_string::RegisteredString, - resource::Resource, -}; use crate::{Str, TypeValueEncodable}; use std::{ marker::PhantomData, @@ -27,6 +16,18 @@ mod resource; /// user-defined synchronization objects pub mod sync; +pub use self::{ + category::Category, + event_argument::EventArgument, + event_attributes::{EventAttributes, EventAttributesBuilder}, + identifier::Identifier, + local_range::LocalRange, + message::Message, + range::Range, + registered_string::RegisteredString, + resource::Resource, +}; + /// Represents a domain for high-level grouping #[derive(Debug)] pub struct Domain { @@ -42,13 +43,11 @@ impl Domain { /// ``` /// let domain = nvtx::Domain::new("Domain"); /// ``` - pub fn new<'a>(name: impl Into) -> Self { + pub fn new(name: impl Into) -> Self { Domain { handle: match name.into() { Str::Ascii(s) => unsafe { nvtx_sys::ffi::nvtxDomainCreateA(s.as_ptr()) }, - Str::Unicode(s) => unsafe { - nvtx_sys::ffi::nvtxDomainCreateW(s.as_ptr().cast()) - }, + Str::Unicode(s) => unsafe { nvtx_sys::ffi::nvtxDomainCreateW(s.as_ptr().cast()) }, }, registered_categories: AtomicU32::new(0), } @@ -175,10 +174,8 @@ impl Domain { /// ``` pub fn mark<'a>(&'a self, arg: impl Into>) { let attribute: EventAttributes<'a> = match arg.into() { - EventArgument::EventAttribute(attr) => attr, - EventArgument::Ascii(s) => Message::from(s).into(), - EventArgument::Unicode(s) => Message::from(s).into(), - EventArgument::Registered(s) => Message::from(s).into(), + EventArgument::Attributes(attr) => attr, + EventArgument::Message(m) => m.into(), }; let encoded = attribute.encode(); unsafe { nvtx_sys::ffi::nvtxDomainMarkEx(self.handle, &encoded) } diff --git a/src/domain/event_argument.rs b/src/domain/event_argument.rs index 6078def..8119b70 100644 --- a/src/domain/event_argument.rs +++ b/src/domain/event_argument.rs @@ -1,23 +1,17 @@ -use super::{EventAttributes, Message, RegisteredString}; -use std::ffi::CString; -use widestring::WideCString; +use super::{EventAttributes, Message}; /// Convenience wrapper for all valid argument types to ranges and marks /// -/// * Any string type will be translated to [`EventArgument::Ascii`], [`EventArgument::Unicode`], or [`EventArgument::Registered`] depending on its type. -/// * If [`EventArgument::EventAttribute`] is the active discriminator: -/// - The if its held [`EventAttributes`] only specifies a message, it will be converted into the message's active discriminator. +/// * Any string type will be translated to [`EventArgument::Message`]. +/// * If [`EventArgument::Attributes`] is the active discriminator: +/// - Then if its held [`EventAttributes`] only specifies a message, then it's Message will be used /// - Otherwise, the existing [`EventAttributes`] will be used for the event. #[derive(Debug, Clone)] pub enum EventArgument<'a> { - /// discriminator for an owned ASCII string - Ascii(CString), - /// discriminator for an owned Unicode string - Unicode(WideCString), - /// discriminator for a referenced registered string - Registered(&'a RegisteredString<'a>), - /// discriminator for a detailed Attribute - EventAttribute(EventAttributes<'a>), + /// discriminator for a Message + Message(Message<'a>), + /// discriminator for an EventAttributes + Attributes(EventAttributes<'a>), } impl<'a, T: Into>> From for EventArgument<'a> { @@ -28,12 +22,8 @@ impl<'a, T: Into>> From for EventArgument<'a> { color: None, payload: None, message: Some(m), - } => match m { - Message::Ascii(s) => EventArgument::Ascii(s), - Message::Unicode(s) => EventArgument::Unicode(s), - Message::Registered(s) => EventArgument::Registered(s), - }, - attr => EventArgument::EventAttribute(attr), + } => EventArgument::Message(m), + attr => EventArgument::Attributes(attr), } } } diff --git a/src/domain/local_range.rs b/src/domain/local_range.rs index ba6b255..8d4c135 100644 --- a/src/domain/local_range.rs +++ b/src/domain/local_range.rs @@ -12,10 +12,8 @@ pub struct LocalRange<'a> { impl<'a> LocalRange<'a> { pub(super) fn new(arg: impl Into>, domain: &'a Domain) -> LocalRange<'a> { let arg = match arg.into() { - EventArgument::EventAttribute(attr) => attr, - EventArgument::Ascii(s) => domain.event_attributes_builder().message(s).build(), - EventArgument::Unicode(s) => domain.event_attributes_builder().message(s).build(), - EventArgument::Registered(s) => domain.event_attributes_builder().message(s).build(), + EventArgument::Attributes(attr) => attr, + EventArgument::Message(m) => domain.event_attributes_builder().message(m).build(), }; unsafe { nvtx_sys::ffi::nvtxDomainRangePushEx(domain.handle, &arg.encode()) }; LocalRange { diff --git a/src/domain/message.rs b/src/domain/message.rs index c1bf934..9542387 100644 --- a/src/domain/message.rs +++ b/src/domain/message.rs @@ -5,8 +5,8 @@ use widestring::WideCString; /// Represents a message for use within events and ranges /// -/// * [`Message::Ascii`] is the discriminator for C strings -/// * [`Message::Unicode`] is the discriminator for Rust strings +/// * [`Message::Ascii`] is the discriminator for ASCII C strings +/// * [`Message::Unicode`] is the discriminator for Rust strings and wide C strings /// * [`Message::Registered`] is the discriminator for nvtx domain-registered strings #[derive(Debug, Clone)] pub enum Message<'a> { diff --git a/src/domain/range.rs b/src/domain/range.rs index cf966a1..0bb53b2 100644 --- a/src/domain/range.rs +++ b/src/domain/range.rs @@ -1,4 +1,4 @@ -use super::{Domain, EventArgument, Message}; +use super::{Domain, EventArgument}; /// A RAII-like object for modeling start/end Ranges within a Domain #[derive(Debug)] @@ -9,12 +9,9 @@ pub struct Range<'a> { impl<'a> Range<'a> { pub(super) fn new(arg: impl Into>, domain: &'a Domain) -> Range<'a> { - let argument = arg.into(); - let arg = match argument { - EventArgument::EventAttribute(attr) => attr, - EventArgument::Ascii(s) => Message::from(s).into(), - EventArgument::Unicode(s) => Message::from(s).into(), - EventArgument::Registered(s) => Message::from(s).into(), + let arg = match arg.into() { + EventArgument::Attributes(attr) => attr, + EventArgument::Message(m) => m.into(), }; let id = unsafe { nvtx_sys::ffi::nvtxDomainRangeStartEx(domain.handle, &arg.encode()) }; Range { id, domain } diff --git a/src/event_argument.rs b/src/event_argument.rs index d785d5c..b155d52 100644 --- a/src/event_argument.rs +++ b/src/event_argument.rs @@ -1,20 +1,17 @@ use crate::{EventAttributes, Message}; -use std::ffi::CString; -use widestring::WideCString; /// Convenience wrapper for all valid argument types to ranges and marks /// -/// * Any string type will be translated to [`EventArgument::Ascii`] or [`EventArgument::Unicode`] depending on its type. -/// * If [`EventArgument::EventAttribute`] is the active discriminator: -/// - Then if its held [`EventAttributes`] only specifies a message, it will be converted into the message's active discriminator. -/// - Otherwise, the existing [`EventAttributes`] will be used for the event.#[derive(Debug, Clone)] +/// * Any string type will be translated to [`EventArgument::Message`]. +/// * If [`EventArgument::Attributes`] is the active discriminator: +/// - Then if its held [`EventAttributes`] only specifies a message, then it's Message will be used +/// - Otherwise, the existing [`EventAttributes`] will be used for the event. +#[derive(Debug, Clone)] pub enum EventArgument { - /// discriminator for an owned ASCII string - Ascii(CString), - /// discriminator for an owned Unicode string - Unicode(WideCString), - /// discriminator for a detailed Attribute - EventAttribute(EventAttributes), + /// discriminator for a Message + Message(Message), + /// discriminator for an EventAttributes + Attributes(EventAttributes), } impl> From for EventArgument { @@ -25,11 +22,8 @@ impl> From for EventArgument { color: None, payload: None, message: Some(m), - } => match m { - Message::Ascii(s) => EventArgument::Ascii(s), - Message::Unicode(s) => EventArgument::Unicode(s), - }, - attr => EventArgument::EventAttribute(attr), + } => EventArgument::Message(m), + attr => EventArgument::Attributes(attr), } } } diff --git a/src/lib.rs b/src/lib.rs index 10115a9..98aa74b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,19 +1,18 @@ #![deny(missing_docs)] //! crate for interfacing with NVIDIA's nvtx API - -pub use crate::{ - category::Category, - color::Color, - domain::Domain, - event_argument::EventArgument, - event_attributes::{EventAttributes, EventAttributesBuilder}, - local_range::LocalRange, - message::Message, - payload::Payload, - range::Range, - str::Str, -}; +//! +//! When not running within NSight profilers, the calls will dispatch to +//! empty method stubs, thus enabling low-overhead profiling. +//! +//! * All events are fully supported: +//! * process ranges [`crate::Range`] and [`crate::domain::Range`] +//! * thread ranges [`crate::LocalRange`] and [`crate::domain::LocalRange`] +//! * marks [`crate::mark`] and [`crate::Domain::mark`] +//! * Naming threads is fully supported (See [`crate::name_thread`] and [`crate::name_current_thread`]) +//! * Domain, category, and registered strings are fully supported. +//! * The user-defined synchronization API is implemented +//! * The user-defined resource naming API is implemented for generic types only. /// color support pub mod color; @@ -29,6 +28,19 @@ mod payload; mod range; mod str; +pub use crate::{ + category::Category, + color::Color, + domain::Domain, + event_argument::EventArgument, + event_attributes::{EventAttributes, EventAttributesBuilder}, + local_range::LocalRange, + message::Message, + payload::Payload, + range::Range, + str::Str, +}; + trait TypeValueEncodable { type Type; type Value; @@ -48,9 +60,11 @@ trait TypeValueEncodable { /// ``` pub fn mark(argument: impl Into) { match argument.into() { - EventArgument::Ascii(s) => unsafe { nvtx_sys::ffi::nvtxMarkA(s.as_ptr()) }, - EventArgument::Unicode(s) => unsafe { nvtx_sys::ffi::nvtxMarkW(s.as_ptr().cast()) }, - EventArgument::EventAttribute(a) => unsafe { nvtx_sys::ffi::nvtxMarkEx(&a.encode()) }, + EventArgument::Message(m) => match m { + Message::Ascii(s) => unsafe { nvtx_sys::ffi::nvtxMarkA(s.as_ptr()) }, + Message::Unicode(s) => unsafe { nvtx_sys::ffi::nvtxMarkW(s.as_ptr().cast()) }, + }, + EventArgument::Attributes(a) => unsafe { nvtx_sys::ffi::nvtxMarkEx(&a.encode()) }, } } diff --git a/src/local_range.rs b/src/local_range.rs index c6c7ceb..505e3b5 100644 --- a/src/local_range.rs +++ b/src/local_range.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; -use crate::EventArgument; +use crate::{EventArgument, Message}; /// A RAII-like object for modeling callstack Ranges #[derive(Debug)] @@ -28,13 +28,11 @@ impl LocalRange { /// ``` pub fn new(arg: impl Into) -> LocalRange { match arg.into() { - EventArgument::Ascii(s) => unsafe { nvtx_sys::ffi::nvtxRangePushA(s.as_ptr()) }, - EventArgument::Unicode(s) => unsafe { - nvtx_sys::ffi::nvtxRangePushW(s.as_ptr().cast()) - }, - EventArgument::EventAttribute(a) => unsafe { - nvtx_sys::ffi::nvtxRangePushEx(&a.encode()) + EventArgument::Message(m) => match m { + Message::Ascii(s) => unsafe { nvtx_sys::ffi::nvtxRangePushA(s.as_ptr()) }, + Message::Unicode(s) => unsafe { nvtx_sys::ffi::nvtxRangePushW(s.as_ptr().cast()) }, }, + EventArgument::Attributes(a) => unsafe { nvtx_sys::ffi::nvtxRangePushEx(&a.encode()) }, }; LocalRange { _phantom: PhantomData, diff --git a/src/message.rs b/src/message.rs index 2ae1e1c..947a715 100644 --- a/src/message.rs +++ b/src/message.rs @@ -4,8 +4,8 @@ use widestring::WideCString; /// Represents a message for use within events and ranges /// -/// * [`Message::Ascii`] is the discriminator for C strings -/// * [`Message::Unicode`] is the discriminator for Rust strings +/// * [`Message::Ascii`] is the discriminator for ASCII C strings +/// * [`Message::Unicode`] is the discriminator for Rust strings and wide C strings #[derive(Debug, Clone)] pub enum Message { /// discriminator for an owned ASCII string diff --git a/src/range.rs b/src/range.rs index c28748a..64c4720 100644 --- a/src/range.rs +++ b/src/range.rs @@ -1,4 +1,4 @@ -use crate::EventArgument; +use crate::{EventArgument, Message}; /// A RAII-like object for modeling start/end Ranges #[derive(Debug)] @@ -26,13 +26,11 @@ impl Range { pub fn new(arg: impl Into) -> Range { let argument = arg.into(); let id = match &argument { - EventArgument::Ascii(s) => unsafe { nvtx_sys::ffi::nvtxRangeStartA(s.as_ptr()) }, - EventArgument::Unicode(s) => unsafe { - nvtx_sys::ffi::nvtxRangeStartW(s.as_ptr().cast()) - }, - EventArgument::EventAttribute(a) => unsafe { - nvtx_sys::ffi::nvtxRangeStartEx(&a.encode()) + EventArgument::Message(m) => match m { + Message::Ascii(s) => unsafe { nvtx_sys::ffi::nvtxRangeStartA(s.as_ptr()) }, + Message::Unicode(s) => unsafe { nvtx_sys::ffi::nvtxRangeStartW(s.as_ptr().cast()) }, }, + EventArgument::Attributes(a) => unsafe { nvtx_sys::ffi::nvtxRangeStartEx(&a.encode()) }, }; Range { id } } From 4dcff5523f5c143a8a53ddf1e36d050577b1a591 Mon Sep 17 00:00:00 2001 From: Will Killian Date: Wed, 27 Mar 2024 07:58:20 -0400 Subject: [PATCH 10/10] Appease --no-default-features check Signed-off-by: Will Killian --- src/domain.rs | 2 +- src/domain/event_attributes.rs | 6 +++--- src/event_attributes.rs | 6 +++--- src/lib.rs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/domain.rs b/src/domain.rs index 1e48a39..9ffa333 100644 --- a/src/domain.rs +++ b/src/domain.rs @@ -167,7 +167,7 @@ impl Domain { /// /// domain.mark(c"Another example"); /// - /// domain.mark(domain.event_attributes_builder().message("Interesting example").color(nvtx::color::red).build()); + /// domain.mark(domain.event_attributes_builder().message("Interesting example").color([255, 0, 0]).build()); /// /// let reg_str = domain.register_string("Registered String"); /// domain.mark(®_str); diff --git a/src/domain/event_attributes.rs b/src/domain/event_attributes.rs index 734ad37..a2980ea 100644 --- a/src/domain/event_attributes.rs +++ b/src/domain/event_attributes.rs @@ -63,7 +63,7 @@ impl<'a, T: Into>> From for EventAttributes<'a> { /// /// let attr = nvtx::EventAttributesBuilder::default() /// .category(&cat) -/// .color(nvtx::color::salmon) +/// .color([20, 192, 240]) /// .payload(3.141592) /// .message("Hello") /// .build(); @@ -103,7 +103,7 @@ impl<'a> EventAttributesBuilder<'a> { /// let domain = nvtx::Domain::new("Domain"); /// let builder = domain.event_attributes_builder(); /// // ... - /// let builder = builder.color(nvtx::color::white); + /// let builder = builder.color([255, 255, 255]); /// ``` pub fn color(mut self, color: impl Into) -> EventAttributesBuilder<'a> { self.color = Some(color.into()); @@ -150,7 +150,7 @@ impl<'a> EventAttributesBuilder<'a> { /// let cat = domain.register_category("Category1"); /// let attr = domain.event_attributes_builder() /// .message("Example Range") - /// .color(nvtx::color::blanchedalmond) + /// .color([224, 192, 128]) /// .category(&cat) /// .payload(1234567) /// .build(); diff --git a/src/event_attributes.rs b/src/event_attributes.rs index 9e84768..b70c105 100644 --- a/src/event_attributes.rs +++ b/src/event_attributes.rs @@ -62,7 +62,7 @@ impl> From for EventAttributes { /// /// let attr = nvtx::EventAttributesBuilder::default() /// .category(&cat) -/// .color(nvtx::color::salmon) +/// .color([20, 192, 240]) /// .payload(3.141592) /// .message("Hello") /// .build(); @@ -94,7 +94,7 @@ impl<'a> EventAttributesBuilder<'a> { /// ``` /// let builder = nvtx::EventAttributesBuilder::default(); /// // ... - /// let builder = builder.color(nvtx::color::white); + /// let builder = builder.color([255, 255, 255]); /// ``` pub fn color(mut self, color: impl Into) -> EventAttributesBuilder<'a> { self.color = Some(color.into()); @@ -131,7 +131,7 @@ impl<'a> EventAttributesBuilder<'a> { /// let cat = nvtx::Category::new("Category1"); /// let attr = nvtx::EventAttributesBuilder::default() /// .message("Example Range") - /// .color(nvtx::color::blanchedalmond) + /// .color([224, 192, 128]) /// .category(&cat) /// .payload(1234567) /// .build(); diff --git a/src/lib.rs b/src/lib.rs index 98aa74b..86f8197 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,7 +56,7 @@ trait TypeValueEncodable { /// /// nvtx::mark(c"Another example"); /// -/// nvtx::mark(nvtx::EventAttributesBuilder::default().message("Interesting example").color(nvtx::color::red).build()); +/// nvtx::mark(nvtx::EventAttributesBuilder::default().message("Interesting example").color([255, 0, 0]).build()); /// ``` pub fn mark(argument: impl Into) { match argument.into() {