loom.rs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. pub(crate) use self::inner::*;
  2. #[cfg(test)]
  3. mod inner {
  4. pub(crate) mod atomic {
  5. pub use loom::sync::atomic::*;
  6. pub use std::sync::atomic::Ordering;
  7. }
  8. pub(crate) use loom::{cell::UnsafeCell, hint, sync, thread};
  9. pub(crate) fn model(f: impl Fn() + Sync + Send + 'static) {
  10. let iteration = core::sync::atomic::AtomicUsize::new(0);
  11. loom::model(move || {
  12. println!(
  13. "\n---- iteration {} ----\n",
  14. iteration.fetch_add(1, atomic::Ordering::Relaxed)
  15. );
  16. f();
  17. })
  18. }
  19. pub(crate) mod alloc {
  20. #![allow(dead_code)]
  21. use loom::alloc;
  22. use std::fmt;
  23. /// Track allocations, detecting leaks
  24. ///
  25. /// This is a version of `loom::alloc::Track` that adds a missing
  26. /// `Default` impl.
  27. pub struct Track<T>(alloc::Track<T>);
  28. impl<T> Track<T> {
  29. /// Track a value for leaks
  30. #[inline(always)]
  31. pub fn new(value: T) -> Track<T> {
  32. Track(alloc::Track::new(value))
  33. }
  34. /// Get a reference to the value
  35. #[inline(always)]
  36. pub fn get_ref(&self) -> &T {
  37. self.0.get_ref()
  38. }
  39. /// Get a mutable reference to the value
  40. #[inline(always)]
  41. pub fn get_mut(&mut self) -> &mut T {
  42. self.0.get_mut()
  43. }
  44. /// Stop tracking the value for leaks
  45. #[inline(always)]
  46. pub fn into_inner(self) -> T {
  47. self.0.into_inner()
  48. }
  49. }
  50. impl<T: fmt::Debug> fmt::Debug for Track<T> {
  51. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  52. self.0.fmt(f)
  53. }
  54. }
  55. impl<T: Default> Default for Track<T> {
  56. fn default() -> Self {
  57. Self::new(T::default())
  58. }
  59. }
  60. }
  61. }
  62. #[cfg(not(test))]
  63. mod inner {
  64. #![allow(dead_code)]
  65. pub(crate) use core::sync::atomic;
  66. #[cfg(feature = "std")]
  67. pub use std::thread;
  68. pub(crate) mod hint {
  69. #[inline(always)]
  70. pub(crate) fn spin_loop() {
  71. // MSRV: std::hint::spin_loop() stabilized in 1.49.0
  72. #[allow(deprecated)]
  73. super::atomic::spin_loop_hint()
  74. }
  75. }
  76. #[derive(Debug)]
  77. pub(crate) struct UnsafeCell<T>(core::cell::UnsafeCell<T>);
  78. impl<T> UnsafeCell<T> {
  79. pub const fn new(data: T) -> UnsafeCell<T> {
  80. UnsafeCell(core::cell::UnsafeCell::new(data))
  81. }
  82. #[inline(always)]
  83. pub fn with<F, R>(&self, f: F) -> R
  84. where
  85. F: FnOnce(*const T) -> R,
  86. {
  87. f(self.0.get())
  88. }
  89. #[inline(always)]
  90. pub fn with_mut<F, R>(&self, f: F) -> R
  91. where
  92. F: FnOnce(*mut T) -> R,
  93. {
  94. f(self.0.get())
  95. }
  96. }
  97. pub(crate) mod alloc {
  98. /// Track allocations, detecting leaks
  99. #[derive(Debug, Default)]
  100. pub struct Track<T> {
  101. value: T,
  102. }
  103. impl<T> Track<T> {
  104. /// Track a value for leaks
  105. #[inline(always)]
  106. pub fn new(value: T) -> Track<T> {
  107. Track { value }
  108. }
  109. /// Get a reference to the value
  110. #[inline(always)]
  111. pub fn get_ref(&self) -> &T {
  112. &self.value
  113. }
  114. /// Get a mutable reference to the value
  115. #[inline(always)]
  116. pub fn get_mut(&mut self) -> &mut T {
  117. &mut self.value
  118. }
  119. /// Stop tracking the value for leaks
  120. #[inline(always)]
  121. pub fn into_inner(self) -> T {
  122. self.value
  123. }
  124. }
  125. }
  126. }