最终代码

这是最终代码,添加了一些注释和重新排序的导入:

  1. use std::marker::PhantomData;
  2. use std::ops::Deref;
  3. use std::ptr::NonNull;
  4. use std::sync::atomic::{self, AtomicUsize, Ordering};
  5. pub struct Arc<T> {
  6. ptr: NonNull<ArcInner<T>>,
  7. phantom: PhantomData<ArcInner<T>>,
  8. }
  9. pub struct ArcInner<T> {
  10. rc: AtomicUsize,
  11. data: T,
  12. }
  13. impl<T> Arc<T> {
  14. pub fn new(data: T) -> Arc<T> {
  15. // We start the reference count at 1, as that first reference is the
  16. // current pointer.
  17. let boxed = Box::new(ArcInner {
  18. rc: AtomicUsize::new(1),
  19. data,
  20. });
  21. Arc {
  22. // It is okay to call `.unwrap()` here as we get a pointer from
  23. // `Box::into_raw` which is guaranteed to not be null.
  24. ptr: NonNull::new(Box::into_raw(boxed)).unwrap(),
  25. phantom: PhantomData,
  26. }
  27. }
  28. }
  29. unsafe impl<T: Sync + Send> Send for Arc<T> {}
  30. unsafe impl<T: Sync + Send> Sync for Arc<T> {}
  31. impl<T> Deref for Arc<T> {
  32. type Target = T;
  33. fn deref(&self) -> &T {
  34. let inner = unsafe { self.ptr.as_ref() };
  35. &inner.data
  36. }
  37. }
  38. impl<T> Clone for Arc<T> {
  39. fn clone(&self) -> Arc<T> {
  40. let inner = unsafe { self.ptr.as_ref() };
  41. // Using a relaxed ordering is alright here as we don't need any atomic
  42. // synchronization here as we're not modifying or accessing the inner
  43. // data.
  44. let old_rc = inner.rc.fetch_add(1, Ordering::Relaxed);
  45. if old_rc >= isize::MAX as usize {
  46. std::process::abort();
  47. }
  48. Self {
  49. ptr: self.ptr,
  50. phantom: PhantomData,
  51. }
  52. }
  53. }
  54. impl<T> Drop for Arc<T> {
  55. fn drop(&mut self) {
  56. let inner = unsafe { self.ptr.as_ref() };
  57. if inner.rc.fetch_sub(1, Ordering::Release) != 1 {
  58. return;
  59. }
  60. // This fence is needed to prevent reordering of the use and deletion
  61. // of the data.
  62. atomic::fence(Ordering::Acquire);
  63. // This is safe as we know we have the last pointer to the `ArcInner`
  64. // and that its pointer is valid.
  65. unsafe { Box::from_raw(self.ptr.as_ptr()); }
  66. }
  67. }