brintos

brintos / linux-shallow public Read only

0
0
Text · 3.4 KiB · 2330f67 Raw
97 lines · rust
1// SPDX-License-Identifier: GPL-2.02 3// Copyright (C) 2024 Google LLC.4 5//! A field that is exclusively owned by a [`ListArc`].6//!7//! This can be used to have reference counted struct where one of the reference counted pointers8//! has exclusive access to a field of the struct.9//!10//! [`ListArc`]: crate::list::ListArc11 12use core::cell::UnsafeCell;13 14/// A field owned by a specific [`ListArc`].15///16/// [`ListArc`]: crate::list::ListArc17pub struct ListArcField<T, const ID: u64 = 0> {18    value: UnsafeCell<T>,19}20 21// SAFETY: If the inner type is thread-safe, then it's also okay for `ListArc` to be thread-safe.22unsafe impl<T: Send + Sync, const ID: u64> Send for ListArcField<T, ID> {}23// SAFETY: If the inner type is thread-safe, then it's also okay for `ListArc` to be thread-safe.24unsafe impl<T: Send + Sync, const ID: u64> Sync for ListArcField<T, ID> {}25 26impl<T, const ID: u64> ListArcField<T, ID> {27    /// Creates a new `ListArcField`.28    pub fn new(value: T) -> Self {29        Self {30            value: UnsafeCell::new(value),31        }32    }33 34    /// Access the value when we have exclusive access to the `ListArcField`.35    ///36    /// This allows access to the field using an `UniqueArc` instead of a `ListArc`.37    pub fn get_mut(&mut self) -> &mut T {38        self.value.get_mut()39    }40 41    /// Unsafely assert that you have shared access to the `ListArc` for this field.42    ///43    /// # Safety44    ///45    /// The caller must have shared access to the `ListArc<ID>` containing the struct with this46    /// field for the duration of the returned reference.47    pub unsafe fn assert_ref(&self) -> &T {48        // SAFETY: The caller has shared access to the `ListArc`, so they also have shared access49        // to this field.50        unsafe { &*self.value.get() }51    }52 53    /// Unsafely assert that you have mutable access to the `ListArc` for this field.54    ///55    /// # Safety56    ///57    /// The caller must have mutable access to the `ListArc<ID>` containing the struct with this58    /// field for the duration of the returned reference.59    #[allow(clippy::mut_from_ref)]60    pub unsafe fn assert_mut(&self) -> &mut T {61        // SAFETY: The caller has exclusive access to the `ListArc`, so they also have exclusive62        // access to this field.63        unsafe { &mut *self.value.get() }64    }65}66 67/// Defines getters for a [`ListArcField`].68#[macro_export]69macro_rules! define_list_arc_field_getter {70    ($pub:vis fn $name:ident(&self $(<$id:tt>)?) -> &$typ:ty { $field:ident }71     $($rest:tt)*72    ) => {73        $pub fn $name<'a>(self: &'a $crate::list::ListArc<Self $(, $id)?>) -> &'a $typ {74            let field = &(&**self).$field;75            // SAFETY: We have a shared reference to the `ListArc`.76            unsafe { $crate::list::ListArcField::<$typ $(, $id)?>::assert_ref(field) }77        }78 79        $crate::list::define_list_arc_field_getter!($($rest)*);80    };81 82    ($pub:vis fn $name:ident(&mut self $(<$id:tt>)?) -> &mut $typ:ty { $field:ident }83     $($rest:tt)*84    ) => {85        $pub fn $name<'a>(self: &'a mut $crate::list::ListArc<Self $(, $id)?>) -> &'a mut $typ {86            let field = &(&**self).$field;87            // SAFETY: We have a mutable reference to the `ListArc`.88            unsafe { $crate::list::ListArcField::<$typ $(, $id)?>::assert_mut(field) }89        }90 91        $crate::list::define_list_arc_field_getter!($($rest)*);92    };93 94    () => {};95}96pub use define_list_arc_field_getter;97