@@ -68,6 +68,49 @@ macro_rules! impl_has_list_links {
6868}
6969pub use impl_has_list_links;
7070
71+ /// Declares that the `ListLinks<ID>` field in this struct is inside a `ListLinksSelfPtr<T, ID>`.
72+ ///
73+ /// # Safety
74+ ///
75+ /// The `ListLinks<ID>` field of this struct at the offset `HasListLinks<ID>::OFFSET` must be
76+ /// inside a `ListLinksSelfPtr<T, ID>`.
77+ pub unsafe trait HasSelfPtr < T : ?Sized , const ID : u64 = 0 >
78+ where
79+ Self : HasListLinks < ID > ,
80+ {
81+ }
82+
83+ /// Implements the [`HasListLinks`] and [`HasSelfPtr`] traits for the given type.
84+ #[ macro_export]
85+ macro_rules! impl_has_list_links_self_ptr {
86+ ( $( impl $( { $( $implarg: tt) * } ) ?
87+ HasSelfPtr <$item_type: ty $( , $id: tt) ?>
88+ for $self: ident $( <$( $selfarg: ty) ,* >) ?
89+ { self . $field: ident }
90+ ) * ) => { $(
91+ // SAFETY: The implementation of `raw_get_list_links` only compiles if the field has the
92+ // right type.
93+ unsafe impl $( <$( $implarg) * >) ? $crate:: list:: HasSelfPtr <$item_type $( , $id) ?> for
94+ $self $( <$( $selfarg) ,* >) ?
95+ { }
96+
97+ unsafe impl $( <$( $implarg) * >) ? $crate:: list:: HasListLinks $( <$id>) ? for
98+ $self $( <$( $selfarg) ,* >) ?
99+ {
100+ const OFFSET : usize = :: core:: mem:: offset_of!( Self , $field) as usize ;
101+
102+ #[ inline]
103+ unsafe fn raw_get_list_links( ptr: * mut Self ) -> * mut $crate:: list:: ListLinks $( <$id>) ? {
104+ // SAFETY: The caller promises that the pointer is not dangling.
105+ let ptr: * mut $crate:: list:: ListLinksSelfPtr <$item_type $( , $id) ?> =
106+ unsafe { :: core:: ptr:: addr_of_mut!( ( * ptr) . $field) } ;
107+ ptr. cast( )
108+ }
109+ }
110+ ) * } ;
111+ }
112+ pub use impl_has_list_links_self_ptr;
113+
71114/// Implements the [`ListItem`] trait for the given type.
72115///
73116/// Requires that the type implements [`HasListLinks`]. Use the [`impl_has_list_links!`] macro to
@@ -139,5 +182,93 @@ macro_rules! impl_list_item {
139182 }
140183 }
141184 ) * } ;
185+
186+ (
187+ $( impl $( { $( $generics: tt) * } ) ? ListItem <$num: tt> for $t: ty {
188+ using ListLinksSelfPtr ;
189+ } ) *
190+ ) => { $(
191+ // SAFETY: See GUARANTEES comment on each method.
192+ unsafe impl $( <$( $generics) * >) ? $crate:: list:: ListItem <$num> for $t {
193+ // GUARANTEES:
194+ // This implementation of `ListItem` will not give out exclusive access to the same
195+ // `ListLinks` several times because calls to `prepare_to_insert` and `post_remove`
196+ // must alternate and exclusive access is given up when `post_remove` is called.
197+ //
198+ // Other invocations of `impl_list_item!` also cannot give out exclusive access to the
199+ // same `ListLinks` because you can only implement `ListItem` once for each value of
200+ // `ID`, and the `ListLinks` fields only work with the specified `ID`.
201+ unsafe fn prepare_to_insert( me: * const Self ) -> * mut $crate:: list:: ListLinks <$num> {
202+ // SAFETY: The caller promises that `me` points at a valid value of type `Self`.
203+ let links_field = unsafe { <Self as $crate:: list:: ListItem <$num>>:: view_links( me) } ;
204+
205+ let spoff = $crate:: list:: ListLinksSelfPtr :: <Self , $num>:: LIST_LINKS_SELF_PTR_OFFSET ;
206+ // Goes via the offset as the field is private.
207+ //
208+ // SAFETY: The constant is equal to `offset_of!(ListLinksSelfPtr, self_ptr)`, so
209+ // the pointer stays in bounds of the allocation.
210+ let self_ptr = unsafe { ( links_field as * const u8 ) . add( spoff) }
211+ as * const $crate:: types:: Opaque <* const Self >;
212+ let cell_inner = $crate:: types:: Opaque :: raw_get( self_ptr) ;
213+
214+ // SAFETY: This value is not accessed in any other places than `prepare_to_insert`,
215+ // `post_remove`, or `view_value`. By the safety requirements of those methods,
216+ // none of these three methods may be called in parallel with this call to
217+ // `prepare_to_insert`, so this write will not race with any other access to the
218+ // value.
219+ unsafe { :: core:: ptr:: write( cell_inner, me) } ;
220+
221+ links_field
222+ }
223+
224+ // GUARANTEES:
225+ // * This returns the same pointer as `prepare_to_insert` because `prepare_to_insert`
226+ // returns the return value of `view_links`.
227+ // * By the type invariants of `ListLinks`, the `ListLinks` has two null pointers when
228+ // this value is not in a list.
229+ unsafe fn view_links( me: * const Self ) -> * mut $crate:: list:: ListLinks <$num> {
230+ // SAFETY: The caller promises that `me` points at a valid value of type `Self`.
231+ unsafe { <Self as HasListLinks <$num>>:: raw_get_list_links( me. cast_mut( ) ) }
232+ }
233+
234+ // This function is also used as the implementation of `post_remove`, so the caller
235+ // may choose to satisfy the safety requirements of `post_remove` instead of the safety
236+ // requirements for `view_value`.
237+ //
238+ // GUARANTEES: (always)
239+ // * This returns the same pointer as the one passed to the most recent call to
240+ // `prepare_to_insert` since that call wrote that pointer to this location. The value
241+ // is only modified in `prepare_to_insert`, so it has not been modified since the
242+ // most recent call.
243+ //
244+ // GUARANTEES: (only when using the `view_value` safety requirements)
245+ // * The pointer remains valid until the next call to `post_remove` because the caller
246+ // of the most recent call to `prepare_to_insert` promised to retain ownership of the
247+ // `ListArc` containing `Self` until the next call to `post_remove`. The value cannot
248+ // be destroyed while a `ListArc` reference exists.
249+ unsafe fn view_value( links_field: * mut $crate:: list:: ListLinks <$num>) -> * const Self {
250+ let spoff = $crate:: list:: ListLinksSelfPtr :: <Self , $num>:: LIST_LINKS_SELF_PTR_OFFSET ;
251+ // SAFETY: The constant is equal to `offset_of!(ListLinksSelfPtr, self_ptr)`, so
252+ // the pointer stays in bounds of the allocation.
253+ let self_ptr = unsafe { ( links_field as * const u8 ) . add( spoff) }
254+ as * const :: core:: cell:: UnsafeCell <* const Self >;
255+ let cell_inner = :: core:: cell:: UnsafeCell :: raw_get( self_ptr) ;
256+ // SAFETY: This is not a data race, because the only function that writes to this
257+ // value is `prepare_to_insert`, but by the safety requirements the
258+ // `prepare_to_insert` method may not be called in parallel with `view_value` or
259+ // `post_remove`.
260+ unsafe { :: core:: ptr:: read( cell_inner) }
261+ }
262+
263+ // GUARANTEES:
264+ // The first guarantee of `view_value` is exactly what `post_remove` guarantees.
265+ unsafe fn post_remove( me: * mut $crate:: list:: ListLinks <$num>) -> * const Self {
266+ // SAFETY: This specific implementation of `view_value` allows the caller to
267+ // promise the safety requirements of `post_remove` instead of the safety
268+ // requirements for `view_value`.
269+ unsafe { <Self as $crate:: list:: ListItem <$num>>:: view_value( me) }
270+ }
271+ }
272+ ) * } ;
142273}
143274pub use impl_list_item;
0 commit comments