cros_tracing_types/
static_strings.rs

1// Copyright 2023 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Provides a mechanism to turn an arbitrary CStr into a static. The primary
6//! use is for FFIs like Perfetto which require any trace point names to be
7//! static.
8
9use std::collections::BTreeSet;
10use std::ffi::CString;
11use std::os::raw::c_char;
12
13use sync::Mutex;
14
15static STATIC_STRINGS: Mutex<BTreeSet<CString>> = Mutex::new(BTreeSet::new());
16
17/// Holds a reference to a 'static string that was registered via `register_string`.
18#[derive(Clone, Copy)]
19pub struct StaticString(*const c_char);
20
21impl StaticString {
22    #[inline]
23    pub fn as_ptr(&self) -> *const c_char {
24        self.0
25    }
26
27    /// Turns a given string into a *c_char which has static lifetime measured
28    /// from the moment this function returns. Registering the same string
29    /// multiple times behaves like interning (will not use additional
30    /// resources).
31    ///
32    /// WARNING: this function creates data with static lifetime. It should only
33    /// be called on a finite set of unique strings. Using it on a non-finite
34    /// set will appear to be a memory leak since the space used will grow
35    /// without bound.
36    pub fn register(str: &str) -> Self {
37        let c_str = CString::new(str).expect("failed to convert a tracing string to a CString.");
38        let mut strings = STATIC_STRINGS.lock();
39        strings.insert(c_str.clone());
40        Self(strings.get(&c_str).unwrap().as_ptr())
41    }
42}
43
44// Safety: pointers are safe to send between threads.
45unsafe impl Send for StaticString {}
46// SAFETY:
47// Safe to share across threads, because `register` is protected by a lock and strings inserted
48// are never removed.
49unsafe impl Sync for StaticString {}