mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-09-07 00:00:08 +02:00
tokio: use ptr::addr_of instead of pointer arithmetic in linked_list (#6561)
This commit is contained in:
@@ -78,26 +78,19 @@ pub(crate) struct Pointers<T> {
|
|||||||
/// Additionally, we never access the `prev` or `next` fields directly, as any
|
/// Additionally, we never access the `prev` or `next` fields directly, as any
|
||||||
/// such access would implicitly involve the creation of a reference to the
|
/// 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
|
/// 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.
|
/// hence be given the `noalias` attribute if we were to do such an access. As
|
||||||
/// As an alternative to accessing the fields directly, the `Pointers` type
|
/// an alternative to accessing the fields directly, the `Pointers` type
|
||||||
/// provides getters and setters for the two fields, and those are implemented
|
/// 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
|
/// using `ptr`-specific methods which avoids the creation of intermediate
|
||||||
/// #[repr(C)].
|
/// references.
|
||||||
///
|
///
|
||||||
/// See this link for more information:
|
/// See this link for more information:
|
||||||
/// <https://github.com/rust-lang/rust/pull/82834>
|
/// <https://github.com/rust-lang/rust/pull/82834>
|
||||||
#[repr(C)]
|
|
||||||
struct PointersInner<T> {
|
struct PointersInner<T> {
|
||||||
/// The previous node in the list. null if there is no previous node.
|
/// The previous node in the list. null if there is no previous node.
|
||||||
///
|
|
||||||
/// This field is accessed through pointer manipulation, so it is not dead code.
|
|
||||||
#[allow(dead_code)]
|
|
||||||
prev: Option<NonNull<T>>,
|
prev: Option<NonNull<T>>,
|
||||||
|
|
||||||
/// The next node in the list. null if there is no previous node.
|
/// The next node in the list. null if there is no previous node.
|
||||||
///
|
|
||||||
/// This field is accessed through pointer manipulation, so it is not dead code.
|
|
||||||
#[allow(dead_code)]
|
|
||||||
next: Option<NonNull<T>>,
|
next: Option<NonNull<T>>,
|
||||||
|
|
||||||
/// This type is !Unpin due to the heuristic from:
|
/// This type is !Unpin due to the heuristic from:
|
||||||
@@ -418,38 +411,24 @@ impl<T> Pointers<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_prev(&self) -> Option<NonNull<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 through a reference.
|
||||||
unsafe {
|
unsafe { ptr::addr_of!((*self.inner.get()).prev).read() }
|
||||||
let inner = self.inner.get();
|
|
||||||
let prev = inner as *const Option<NonNull<T>>;
|
|
||||||
ptr::read(prev)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pub(crate) fn get_next(&self) -> Option<NonNull<T>> {
|
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 through a reference.
|
||||||
unsafe {
|
unsafe { ptr::addr_of!((*self.inner.get()).next).read() }
|
||||||
let inner = self.inner.get();
|
|
||||||
let prev = inner as *const Option<NonNull<T>>;
|
|
||||||
let next = prev.add(1);
|
|
||||||
ptr::read(next)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_prev(&mut self, value: Option<NonNull<T>>) {
|
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 through a mutable reference.
|
||||||
unsafe {
|
unsafe {
|
||||||
let inner = self.inner.get();
|
ptr::addr_of_mut!((*self.inner.get()).prev).write(value);
|
||||||
let prev = inner as *mut Option<NonNull<T>>;
|
|
||||||
ptr::write(prev, value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn set_next(&mut self, value: Option<NonNull<T>>) {
|
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 through a mutable reference.
|
||||||
unsafe {
|
unsafe {
|
||||||
let inner = self.inner.get();
|
ptr::addr_of_mut!((*self.inner.get()).next).write(value);
|
||||||
let prev = inner as *mut Option<NonNull<T>>;
|
|
||||||
let next = prev.add(1);
|
|
||||||
ptr::write(next, value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user