Skip to content

Commit

Permalink
util: Use ptr::addr_of over pointer arithmetics in linked_list
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog committed May 15, 2024
1 parent d085260 commit dcbdb3c
Showing 1 changed file with 13 additions and 23 deletions.
36 changes: 13 additions & 23 deletions tokio/src/util/linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ pub(crate) unsafe trait Link {
}

/// Previous / next pointers.
#[repr(transparent)]
pub(crate) struct Pointers<T> {
inner: UnsafeCell<PointersInner<T>>,
}
Expand All @@ -78,15 +79,14 @@ pub(crate) struct Pointers<T> {
/// Additionally, we never access the `prev` or `next` fields directly, as any
/// such access would implicitly involve the creation of a reference to the
/// field, which we want to avoid since the fields are not `!Unpin`, and would
/// hence be given the `noalias` attribute if we were to do such an access.
/// As an alternative to accessing the fields directly, the `Pointers` type
/// hence be given the `noalias` attribute if we were to do such an access. As
/// an alternative to accessing the fields directly, the `Pointers` type
/// provides getters and setters for the two fields, and those are implemented
/// using raw pointer casts and offsets, which is valid since the struct is
/// #[repr(C)].
/// using `ptr`-specific methods which avoids the creation of intermediate
/// references.
///
/// See this link for more information:
/// <https://github.com/rust-lang/rust/pull/82834>
#[repr(C)]
struct PointersInner<T> {
/// The previous node in the list. null if there is no previous node.
///
Expand Down Expand Up @@ -418,38 +418,28 @@ impl<T> Pointers<T> {
}

pub(crate) fn get_prev(&self) -> Option<NonNull<T>> {
// SAFETY: prev is the first field in PointersInner, which is #[repr(C)].
// SAFETY: Field is accessed immutably from a reference.
unsafe {
let inner = self.inner.get();
let prev = inner as *const Option<NonNull<T>>;
ptr::read(prev)
ptr::addr_of!((*self.inner.get()).prev).read()
}
}
pub(crate) fn get_next(&self) -> Option<NonNull<T>> {
// SAFETY: next is the second field in PointersInner, which is #[repr(C)].
// SAFETY: Field is accessed immutably from a reference.
unsafe {
let inner = self.inner.get();
let prev = inner as *const Option<NonNull<T>>;
let next = prev.add(1);
ptr::read(next)
ptr::addr_of!((*self.inner.get()).next).read()
}
}

fn set_prev(&mut self, value: Option<NonNull<T>>) {
// SAFETY: prev is the first field in PointersInner, which is #[repr(C)].
// SAFETY: Field is accessed mutably from a mutable reference.
unsafe {
let inner = self.inner.get();
let prev = inner as *mut Option<NonNull<T>>;
ptr::write(prev, value);
ptr::addr_of_mut!((*self.inner.get()).prev).write(value);
}
}
fn set_next(&mut self, value: Option<NonNull<T>>) {
// SAFETY: next is the second field in PointersInner, which is #[repr(C)].
// SAFETY: Field is accessed mutably from a mutable reference.
unsafe {
let inner = self.inner.get();
let prev = inner as *mut Option<NonNull<T>>;
let next = prev.add(1);
ptr::write(next, value);
ptr::addr_of_mut!((*self.inner.get()).next).write(value);
}
}
}
Expand Down

0 comments on commit dcbdb3c

Please sign in to comment.