|
1 | 1 | //! Unbounded channel implemented as a linked list. |
2 | 2 |
|
3 | | -use std::alloc::{alloc_zeroed, Layout}; |
| 3 | +use std::alloc::{alloc_zeroed, handle_alloc_error, Layout}; |
4 | 4 | use std::boxed::Box; |
5 | 5 | use std::cell::UnsafeCell; |
6 | 6 | use std::marker::PhantomData; |
@@ -74,15 +74,22 @@ struct Block<T> { |
74 | 74 | impl<T> Block<T> { |
75 | 75 | /// Creates an empty block. |
76 | 76 | fn new() -> Box<Self> { |
| 77 | + let layout = Layout::new::<Self>(); |
| 78 | + assert!(layout.size() != 0, "Block should never be zero-sized, as it has an AtomicPtr field"); |
| 79 | + // SAFETY: layout is not zero-sized |
| 80 | + let ptr = unsafe { alloc_zeroed(layout) }; |
| 81 | + // Handle allocation failure |
| 82 | + if ptr.is_null() { |
| 83 | + handle_alloc_error(layout) |
| 84 | + } |
77 | 85 | // SAFETY: This is safe because: |
78 | 86 | // [1] `Block::next` (AtomicPtr) may be safely zero initialized. |
79 | 87 | // [2] `Block::slots` (Array) may be safely zero initialized because of [3, 4]. |
80 | 88 | // [3] `Slot::msg` (UnsafeCell) may be safely zero initialized because it |
81 | 89 | // holds a MaybeUninit. |
82 | 90 | // [4] `Slot::state` (AtomicUsize) may be safely zero initialized. |
83 | 91 | // TODO: unsafe { Box::new_zeroed().assume_init() } |
84 | | - let layout = Layout::new::<Self>(); |
85 | | - unsafe { Box::from_raw(alloc_zeroed(layout).cast()) } |
| 92 | + unsafe { Box::from_raw(ptr.cast()) } |
86 | 93 | } |
87 | 94 |
|
88 | 95 | /// Waits until the next pointer is set. |
|
0 commit comments