locked.rs 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. mod proof;
  2. use core::{cell::UnsafeCell, fmt, ptr::NonNull};
  3. pub use proof::{AsProof, AsProofMut, Proof, ProofMut};
  4. /// A lock to protect a value of type `T` using the proof of access to some
  5. /// value of type `U`.
  6. pub struct Locked<T, U>
  7. where
  8. U: ?Sized,
  9. {
  10. inner: UnsafeCell<T>,
  11. #[cfg(not(feature = "no_check_locked"))]
  12. guard: NonNull<U>,
  13. #[cfg(feature = "no_check_locked")]
  14. _phantom: core::marker::PhantomData<NonNull<U>>,
  15. }
  16. /// SAFETY: The `Locked` type is safe to send across threads as long as
  17. /// the inner type `T` is `Send`. The `guard` pointer is not used to access
  18. /// the inner value, so no constraints are needed on it.
  19. unsafe impl<T, U> Send for Locked<T, U>
  20. where
  21. T: Send,
  22. U: ?Sized,
  23. {
  24. }
  25. /// SAFETY: The `Locked` type is safe to share across threads as long as
  26. /// the inner type `T` is `Send` and `Sync`. The `guard` pointer is not used
  27. /// to access the inner value, so no constraints are needed on it.
  28. unsafe impl<T, U> Sync for Locked<T, U>
  29. where
  30. T: Send + Sync,
  31. U: ?Sized,
  32. {
  33. }
  34. impl<T, U> Locked<T, U>
  35. where
  36. U: ?Sized,
  37. {
  38. pub const fn new(value: T, guard: &U) -> Self {
  39. Self {
  40. inner: UnsafeCell::new(value),
  41. #[cfg(not(feature = "no_check_locked"))]
  42. // SAFETY: The validity of address is guaranteed by the borrow checker.
  43. guard: unsafe { NonNull::new_unchecked(&raw const *guard as *mut U) },
  44. #[cfg(feature = "no_check_locked")]
  45. guard: core::marker::PhantomData,
  46. }
  47. }
  48. }
  49. impl<T, U> Locked<T, U>
  50. where
  51. T: Send + Sync,
  52. U: ?Sized,
  53. {
  54. pub fn access<'a, 'b>(&'a self, _guard: Proof<'b, U>) -> &'a T
  55. where
  56. 'b: 'a,
  57. {
  58. #[cfg(not(feature = "no_check_locked"))]
  59. assert_eq!(self.guard, _guard.address, "Locked::access(): Wrong guard");
  60. // SAFETY: The guard protects the shared access to the inner value.
  61. unsafe { self.inner.get().as_ref().unwrap() }
  62. }
  63. pub fn access_mut<'a, 'b>(&'a self, _guard: ProofMut<'b, U>) -> &'a mut T
  64. where
  65. 'b: 'a,
  66. {
  67. #[cfg(not(feature = "no_check_locked"))]
  68. assert_eq!(
  69. self.guard, _guard.address,
  70. "Locked::access_mut(): Wrong guard"
  71. );
  72. // SAFETY: The guard protects the exclusive access to the inner value.
  73. unsafe { self.inner.get().as_mut().unwrap() }
  74. }
  75. }
  76. impl<T, U> fmt::Debug for Locked<T, U>
  77. where
  78. U: ?Sized,
  79. {
  80. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  81. f.debug_struct("Locked")
  82. .field("value", &self.inner)
  83. .field("guard", &self.guard)
  84. .finish()
  85. }
  86. }