|
1 | 1 | #[cfg(all(feature = "export-globals", feature = "import-globals"))]
|
2 |
| -compile_error!("The features `export-globals` and `import-globals` cannot be used together"); |
| 2 | +compile_error!("The features `export-globals` and `import-globals` are mutually exclusive, see https://github.com/bearcove/rubicon"); |
3 | 3 |
|
4 | 4 | #[cfg(any(feature = "export-globals", feature = "import-globals"))]
|
5 | 5 | pub use paste::paste;
|
@@ -48,17 +48,24 @@ impl<T> Deref for TrustedExternDouble<T> {
|
48 | 48 | /// Usage:
|
49 | 49 | ///
|
50 | 50 | /// ```ignore
|
51 |
| -/// use rubicon::process_local; |
52 |
| -/// |
53 |
| -/// process_local! { |
54 |
| -/// static FOO: u32 = 42; |
| 51 | +/// rubicon::thread_local! { |
| 52 | +/// static FOO: AtomicU32 = AtomicU32::new(42); |
55 | 53 | /// }
|
56 | 54 | /// ```
|
57 | 55 | ///
|
58 | 56 | /// This will import `FOO` if the `import-globals` feature is enabled, and export it if the
|
59 | 57 | /// `export-globals` feature is enabled.
|
60 | 58 | ///
|
61 |
| -/// If neither feature is enabled, this will expand to the static declaration itself. |
| 59 | +/// If neither feature is enabled, this will be equivalent to `std::thread_local!`. |
| 60 | +/// |
| 61 | +/// This macro supports multiple declarations: |
| 62 | +/// |
| 63 | +/// ```ignore |
| 64 | +/// rubicon::thread_local! { |
| 65 | +/// static FOO: AtomicU32 = AtomicU32::new(42); |
| 66 | +/// static BAR: AtomicU32 = AtomicU32::new(43); |
| 67 | +/// } |
| 68 | +/// ``` |
62 | 69 | #[cfg(not(any(feature = "import-globals", feature = "export-globals")))]
|
63 | 70 | #[macro_export]
|
64 | 71 | macro_rules! thread_local {
|
@@ -148,6 +155,13 @@ macro_rules! thread_local_inner {
|
148 | 155 | ///
|
149 | 156 | /// This macro supports multiple declarations, along with `static mut` declarations
|
150 | 157 | /// (which have a slightly different expansion).
|
| 158 | +/// |
| 159 | +/// ```ignore |
| 160 | +/// rubicon::thread_local! { |
| 161 | +/// static FOO: AtomicU32 = AtomicU32::new(42); |
| 162 | +/// static mut BAR: Dispatcher = Dispatcher::new(); |
| 163 | +/// } |
| 164 | +/// ``` |
151 | 165 | #[cfg(all(not(feature = "import-globals"), not(feature = "export-globals")))]
|
152 | 166 | #[macro_export]
|
153 | 167 | macro_rules! process_local {
|
@@ -242,171 +256,3 @@ macro_rules! process_local_inner_mut {
|
242 | 256 | }
|
243 | 257 | };
|
244 | 258 | }
|
245 |
| - |
246 |
| -//============================================================================== |
247 |
| -// soprintln |
248 |
| -//============================================================================== |
249 |
| - |
250 |
| -/// Note: there's one copy of this static per shared object on purpose — that's the one |
251 |
| -/// static we DON'T want to deduplicate. |
252 |
| -#[used] |
253 |
| -static SHARED_OBJECT_ID_REF: u64 = 0; |
254 |
| - |
255 |
| -/// Returns a unique identifier for the current shared object. |
256 |
| -pub fn shared_object_id() -> u64 { |
257 |
| - &SHARED_OBJECT_ID_REF as *const _ as u64 |
258 |
| -} |
259 |
| - |
260 |
| -/// Defined to `I` when importing globals, `E` when exporting globals, and `N` otherwise. |
261 |
| -#[cfg(feature = "import-globals")] |
262 |
| -pub static RUBICON_MODE: &str = "I"; // "import" |
263 |
| - |
264 |
| -/// Defined to `I` when importing globals, `E` when exporting globals, and `N` otherwise. |
265 |
| -#[cfg(feature = "export-globals")] |
266 |
| -pub static RUBICON_MODE: &str = "E"; // "export" |
267 |
| - |
268 |
| -/// Defined to `I` when importing globals, `E` when exporting globals, and `N` otherwise. |
269 |
| -#[cfg(not(any(feature = "import-globals", feature = "export-globals")))] |
270 |
| -pub static RUBICON_MODE: &str = "N"; // "normal" |
271 |
| - |
272 |
| -#[cfg(all(feature = "import-globals", feature = "export-globals"))] |
273 |
| -compile_error!("The features \"import-globals\" and \"export-globals\" are mutually exclusive"); |
274 |
| - |
275 |
| -/// A `u64` whose 24-bit ANSI color is determined by its value. |
276 |
| -/// |
277 |
| -/// Used by the [`soprintln`] macro to visually distinguish shared objects and threads. |
278 |
| -pub struct Beacon<'a> { |
279 |
| - fg: (u8, u8, u8), |
280 |
| - bg: (u8, u8, u8), |
281 |
| - name: &'a str, |
282 |
| - val: u64, |
283 |
| -} |
284 |
| - |
285 |
| -impl<'a> Beacon<'a> { |
286 |
| - /// Creates a new `Beacon` from a pointer. |
287 |
| - pub fn from_ptr<T>(name: &'a str, ptr: *const T) -> Self { |
288 |
| - Self::new(name, ptr as u64) |
289 |
| - } |
290 |
| - |
291 |
| - /// Creates a new `Beacon` from a reference. |
292 |
| - pub fn from_ref<T>(name: &'a str, r: &T) -> Self { |
293 |
| - Self::new(name, r as *const T as u64) |
294 |
| - } |
295 |
| - |
296 |
| - /// Creates a new `Beacon` with the given extra string and value. |
297 |
| - pub fn new(name: &'a str, u: u64) -> Self { |
298 |
| - fn hash(mut x: u64) -> u64 { |
299 |
| - const K: u64 = 0x517cc1b727220a95; |
300 |
| - x = x.wrapping_mul(K); |
301 |
| - x ^= x >> 32; |
302 |
| - x = x.wrapping_mul(K); |
303 |
| - x ^= x >> 32; |
304 |
| - x = x.wrapping_mul(K); |
305 |
| - x |
306 |
| - } |
307 |
| - |
308 |
| - let hashed_float = (hash(u) as f64) / (u64::MAX as f64); |
309 |
| - let h = hashed_float * 360.0; |
310 |
| - let s = 50.0; |
311 |
| - let l = 70.0; |
312 |
| - |
313 |
| - fn hsl_to_rgb(h: f64, s: f64, l: f64) -> (u8, u8, u8) { |
314 |
| - let h = h / 360.0; |
315 |
| - let s = s / 100.0; |
316 |
| - let l = l / 100.0; |
317 |
| - |
318 |
| - let c = (1.0 - (2.0 * l - 1.0).abs()) * s; |
319 |
| - let x = c * (1.0 - ((h * 6.0) % 2.0 - 1.0).abs()); |
320 |
| - let m = l - c / 2.0; |
321 |
| - |
322 |
| - let (r, g, b) = match (h * 6.0) as u8 { |
323 |
| - 0 | 6 => (c, x, 0.0), |
324 |
| - 1 => (x, c, 0.0), |
325 |
| - 2 => (0.0, c, x), |
326 |
| - 3 => (0.0, x, c), |
327 |
| - 4 => (x, 0.0, c), |
328 |
| - _ => (c, 0.0, x), |
329 |
| - }; |
330 |
| - |
331 |
| - ( |
332 |
| - ((r + m) * 255.0) as u8, |
333 |
| - ((g + m) * 255.0) as u8, |
334 |
| - ((b + m) * 255.0) as u8, |
335 |
| - ) |
336 |
| - } |
337 |
| - |
338 |
| - let fg = hsl_to_rgb(h, s, l); |
339 |
| - let bg = hsl_to_rgb(h, s * 0.8, l * 0.5); |
340 |
| - |
341 |
| - Self { |
342 |
| - fg, |
343 |
| - bg, |
344 |
| - name, |
345 |
| - val: u, |
346 |
| - } |
347 |
| - } |
348 |
| -} |
349 |
| - |
350 |
| -impl<'a> std::fmt::Display for Beacon<'a> { |
351 |
| - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
352 |
| - write!( |
353 |
| - f, |
354 |
| - "\x1b[48;2;{};{};{}m\x1b[38;2;{};{};{}m{}#{:0x}\x1b[0m", |
355 |
| - self.bg.0, self.bg.1, self.bg.2, self.fg.0, self.fg.1, self.fg.2, self.name, self.val |
356 |
| - ) |
357 |
| - } |
358 |
| -} |
359 |
| - |
360 |
| -/// Prints a message, prefixed with a cycling millisecond timestamp (wraps at 99999), |
361 |
| -/// a colorized shared object id, a colorized thread name+id, and the given message. |
362 |
| -#[macro_export] |
363 |
| -#[cfg(feature = "soprintln")] |
364 |
| -macro_rules! soprintln { |
365 |
| - ($($arg:tt)*) => { |
366 |
| - { |
367 |
| - use std::sync::atomic::{AtomicBool, Ordering}; |
368 |
| - static ENV_CHECKED: std::sync::Once = std::sync::Once::new(); |
369 |
| - static SHOULD_PRINT: AtomicBool = AtomicBool::new(false); |
370 |
| - ENV_CHECKED.call_once(|| { |
371 |
| - let should_print = std::env::var("SO_PRINTLN").map(|v| v == "1").unwrap_or(false); |
372 |
| - SHOULD_PRINT.store(should_print, Ordering::Relaxed); |
373 |
| - }); |
374 |
| - |
375 |
| - if SHOULD_PRINT.load(Ordering::Relaxed) { |
376 |
| - // this formatting is terribly wasteful — PRs welcome |
377 |
| - |
378 |
| - let so_id = $crate::shared_object_id(); |
379 |
| - let so_mode_and_id = $crate::Beacon::new($crate::RUBICON_MODE, so_id); |
380 |
| - let curr_thread = std::thread::current(); |
381 |
| - let tid = format!("{:?}", curr_thread.id()); |
382 |
| - // strip `ThreadId(` prefix |
383 |
| - let tid = tid.strip_prefix("ThreadId(").unwrap_or(&tid); |
384 |
| - // strip `)` suffix |
385 |
| - let tid = tid.strip_suffix(")").unwrap_or(&tid); |
386 |
| - // parse tid as u64 |
387 |
| - let tid = tid.parse::<u64>().unwrap_or(0); |
388 |
| - |
389 |
| - let thread_name = curr_thread.name().unwrap_or("<unnamed>"); |
390 |
| - let thread = $crate::Beacon::new(thread_name, tid); |
391 |
| - |
392 |
| - let timestamp = ::std::time::SystemTime::now().duration_since(::std::time::UNIX_EPOCH).unwrap().as_millis() % 99999; |
393 |
| - // FIXME: this is probably not necessary, but without it, rustc complains about |
394 |
| - // capturing variables in format_args? |
395 |
| - let msg = format!($($arg)*); |
396 |
| - eprintln!("{timestamp:05} {so_mode_and_id} {thread} {msg}"); |
397 |
| - } |
398 |
| - } |
399 |
| - }; |
400 |
| -} |
401 |
| - |
402 |
| -/// `soprintln!` prints a message prefixed by a truncated timestamp, shared object ID and thread ID. |
403 |
| -/// |
404 |
| -/// It is costly, which is why it's behind a cargo feature AND an environment variable. |
405 |
| -/// |
406 |
| -/// To see soprintln output, enable the `soprintln` cargo feature, and set the `SO_PRINTLN` |
407 |
| -/// environment variable to `1`. |
408 |
| -#[macro_export] |
409 |
| -#[cfg(not(feature = "soprintln"))] |
410 |
| -macro_rules! soprintln { |
411 |
| - ($($arg:tt)*) => {}; |
412 |
| -} |
0 commit comments