arcshift/
lib.rs

1#![no_std]
2#![cfg_attr(feature = "nightly", feature(ptr_metadata))]
3#![deny(warnings)]
4#![forbid(clippy::undocumented_unsafe_blocks)]
5#![deny(missing_docs)]
6
7//! # Introduction to ArcShift
8//!
9//! [`ArcShift`] is a data type similar to `std::sync::Arc`, except that it allows updating
10//! the value pointed to. It can be used as a faster replacement for
11//! `std::sync::Arc<std::sync::RwLock<T>>`.
12//!
13//! Writing to ArcShift is significantly more expensive than for `std::sync::RwLock`, so
14//! ArcShift is most suited to use cases where updates are infrequent.
15//!
16//! ## Example
17//! ```
18//! # #[cfg(any(feature="loom",feature="shuttle"))]
19//! # pub fn main() {}
20//! # #[cfg(not(any(feature="loom",feature="shuttle")))]
21//! # pub fn main() {
22//! # extern crate arcshift;
23//! # use arcshift::ArcShift;
24//! use std::thread;
25//!
26//!
27//! let mut arc = ArcShift::new("Hello".to_string());
28//! let mut arc2 = arc.clone();
29//!
30//!
31//! let j1 = thread::spawn(move||{
32//!     println!("Value in thread 1: '{}'", arc.get()); //Prints 'Hello'
33//!     arc.update("New value".to_string());
34//!     println!("Updated value in thread 1: '{}'", arc.get()); //Prints 'New value'
35//! });
36//!
37//! let j2 = thread::spawn(move||{
38//!     // Prints either 'Hello' or 'New value', depending on scheduling:
39//!     println!("Value in thread 2: '{}'", arc2.get());
40//! });
41//!
42//! j1.join().unwrap();
43//! j2.join().unwrap();
44//! # }
45//! ```
46//!
47//! # Strong points
48//! * Easy to use (similar to Arc)
49//! * All functions are lock free (see <https://en.wikipedia.org/wiki/Non-blocking_algorithm> )
50//! * For use cases where no modification of values occurs, performance is very good (much
51//!   better than RwLock or Mutex).
52//! * Modifying values is reasonably fast (think, 50-150 nanoseconds), but much slower than Mutex or
53//!   RwLock.
54//! * The function [`ArcShift::shared_get`] allows access without any overhead
55//!   at compared to regular Arc (benchmarks show identical performance to Arc).
56//! * ArcShift does not rely on thread-local variables.
57//! * ArcShift is no_std compatible (though 'alloc' is required, since ArcShift is a heap
58//!   allocating data structure). Compile with "default-features=false" to enable no_std compatibility.
59//!
60//! # Limitations
61//!
62//! ArcShift achieves its performance at the expense of the following disadvantages:
63//!
64//! * When modifying the value, the old version of the value lingers in memory until
65//!   the last ArcShift that uses it has updated. Such an update only happens when the ArcShift
66//!   is accessed using a unique (`&mut`) access (like [`ArcShift::get`] or [`ArcShift::reload`]).
67//!   This can be partially mitigated by using the [`ArcShiftWeak`]-type for long-lived
68//!   never-reloaded instances.
69//! * Modifying the value is approximately 10x more expensive than modifying an `Arc<Mutex<T>>`.
70//!   That said, if you're storing anything significantly more complex than an integer, the overhead
71//!   of ArcShift may be insignificant.
72//! * When the value is modified, the next subsequent reload is slower than an `Arc<RwLock<T>>`
73//!   access.
74//! * ArcShift is its own datatype. It is in no way compatible with `Arc<T>`.
75//! * At most usize::MAX/8 instances of ArcShift or ArcShiftWeak can be created for each value.
76//!   (this is because it uses some bits of its weak refcount to store metadata).
77//! * ArcShift instances should ideally be owned (or be mutably accessible). This is because
78//!   reloading ArcShift requires mutable access to the ArcShift object itself.
79//!
80//! The last limitation might seem unacceptable, but for many applications it is not
81//! hard to make sure each thread/scope has its own instance of ArcShift pointing to
82//! the resource. Cloning ArcShift instances is reasonably fast.
83//!
84//! # Implementation
85//!
86//! When ArcShift values are updated, a linked list of all updates is formed. Whenever
87//! an ArcShift-instance is reloaded (using [`ArcShift::reload`], [`ArcShift::get`],
88//! that instance advances along the linked list to the last
89//! node in the list. When no instance exists pointing at a node in the list, it is dropped.
90//! It is thus important to periodically call [`ArcShift::reload`] or [`ArcShift::get`] to avoid retaining unneeded values.
91//!
92//! # Motivation
93//!
94//! The primary raison d'ĂȘtre for [`ArcShift`] is to be a version of Arc which allows
95//! modifying the stored value, with very little overhead over regular Arc for read heavy
96//! loads.
97//!
98//! The motivating use-case for ArcShift is hot-reloadable assets in computer games.
99//! During normal usage, assets do not change. All benchmarks and play experience will
100//! be dependent only on this baseline performance. Ideally, we therefore want to have
101//! a very small performance penalty for the case when assets are *not* updated, comparable
102//! to using regular `std::sync::Arc`.
103//!
104//! During game development, artists may update assets, and hot-reload is a very
105//! time-saving feature. A performance hit during asset-reload is acceptable though.
106//! ArcShift prioritizes base performance, while accepting a penalty when updates are made.
107//!
108//! ArcShift can, of course, be useful in other domains than computer games.
109//!
110//! # Performance properties
111//!
112//! Accessing the value stored in an ArcShift instance only requires a regular memory access,
113//! not any form of atomic operation. Checking for new values requires a single
114//! atomic operation, of the least expensive kind (Ordering::Relaxed). On x86_64,
115//! this is the exact same machine operation as a regular memory access, and also
116//! on arm it is not an expensive operation.
117//! The cost of such access is much smaller than a mutex access, even an uncontended one.
118//! In the case where a reload is actually necessary, there is a significant performance impact
119//! (but still typically below 150ns for modern machines (2025)).
120//!
121//! # Panicking drop methods
122//! If a drop implementation panics, ArcShift will make sure that the internal data structures
123//! remain uncorrupted. When run without the std-library, some memory leakage will occur every
124//! time a drop method panics. With the std-library, only memory owned by the payload type
125//! might leak.
126//!
127//! # No_std
128//! By default, arcshift uses the rust standard library. This is enabled by the 'std' feature, which
129//! is enabled by default. ArcShift can work without the full rust std library. However, this
130//! comes at a slight performance cost. When the 'std' feature is enabled (which it is by default),
131//! `catch_unwind` is used to guard drop functions, to make sure memory structures are not corrupted
132//! if a user supplied drop method panics. However, to ensure the same guarantee when running
133//! without std, arcshift presently moves allocations to temporary boxes to be able to run drop
134//! after all memory traversal is finished. This requires multiple allocations, which makes
135//! operation without 'std' slightly slower. Panicking drop methods can also lead to memory leaks
136//! without the std. The memory structures remain intact, and no undefined behavior occurs.
137//!
138//! If the overhead mentioned in the previous paragraph is unacceptable, and if the final binary
139//! is compiled with panic=abort, this extra cost can be mitigated. Enable the feature
140//! "nostd_unchecked_panics" to do this. This must never be done if the process will ever continue
141//! executing after a panic, since it can lead to memory reclamation essentially being disabled
142//! for any ArcShift-chain that has had a panicking drop. However, no UB will result, in any case.
143//!
144//! # Implementation
145//!
146//! The basic idea of ArcShift is that each ArcShift instance points to a small heap block,
147//! that contains the pointee value of type T, three reference counts, and 'prev'/'next'-pointers.
148//! The 'next'-pointer starts out as null, but when the value in an ArcShift is updated, the
149//! 'next'-pointer is set to point to the updated value.
150//!
151//! This means that each ArcShift-instance always points at valid value of type T. No locking
152//! or synchronization is required to get at this value. This is why ArcShift instances are fast
153//! to use. There is the drawback that as long as an ArcShift-instance exists, whatever value
154//! it points to must be kept alive. Each time an ArcShift instance is accessed mutably, we have
155//! an opportunity to update its pointer to the 'next' value. The operation to update the pointer
156//! is called a 'reload'.
157//!
158//! When the last ArcShift-instance releases a particular value, it will be dropped.
159//!
160//! ArcShiftWeak-instances also keep pointers to the heap blocks mentioned above, but value T
161//! in the block can be dropped while being held by an ArcShiftWeak. This means that an ArcShiftWeak-
162//! instance only consumes `std::mem::size_of::<T>()` bytes plus 5 words of memory, when the value
163//! it points to has been dropped. When the ArcShiftWeak-instance is reloaded, or dropped, that memory
164//! is also released.
165//!
166//!
167//! # Pitfall #1 - lingering memory usage
168//!
169//! Be aware that ArcShift instances that are just "lying around" without ever being reloaded,
170//! will keep old values around, taking up memory. This is a fundamental drawback of the approach
171//! taken by ArcShift. One workaround is to replace any long-lived infrequently reloaded instances of
172//! [`ArcShift`] with [`ArcShiftWeak`]. This alleviates the problem, though heap storage of approx
173//! `size_of<T>` + 5 words is still expended.
174//!
175//! # Pitfall #2 - reference count limitations
176//!
177//! ArcShift uses usize data type for the reference counts. However, it reserves two bits for
178//! tracking some metadata. This leaves usize::MAX/4 as the maximum usable reference count. To
179//! avoid having to check the refcount twice (once before increasing the count), we set the limit
180//! at usize::MAX/8, and check the count after the atomic operation. This has the effect that if more
181//! than usize::MAX/8 threads clone the same ArcShift instance concurrently, the unsoundness will occur.
182//! However, this is considered acceptable, because this exceeds the possible number
183//! of concurrent threads by a huge safety margin. Also note that usize::MAX/8 ArcShift instances would
184//! take up usize::MAX bytes of memory, which is very much impossible in practice. By leaking
185//! ArcShift instances in a tight loop it is still possible to achieve a weak count of usize::MAX/8,
186//! in which case ArcShift will panic.
187//!
188//! # A larger example
189//!
190//! ```no_run
191//! # extern crate arcshift;
192//! # use arcshift::ArcShift;
193//!
194//! struct CharacterModel {
195//!     /* 3D model, textures, etc*/
196//! }
197//!
198//! struct World {
199//!     models: Vec<ArcShift<CharacterModel>>
200//! }
201//!
202//! /// Loads models. Regularly scans filesystem,
203//! /// updates models when their files change on disk.
204//! fn load_models() -> Vec<ArcShift<CharacterModel>> {
205//!     let models: Vec<ArcShift<CharacterModel>> = vec![];
206//!
207//!     /* Somehow load models */
208//!
209//!     let mut models_for_reloader = models.clone();
210//!     std::thread::spawn(move||{
211//!         loop {
212//!             /* detect file system changes*/
213//!             let changed_model = 0usize;
214//!
215//!             models_for_reloader[changed_model].update(CharacterModel{/* newly loaded*/});
216//!         }
217//!
218//!     });
219//!
220//!     models
221//! }
222//!
223//! fn run_game() {
224//!     let mut world = World {
225//!         models: load_models()
226//!     };
227//!     loop {
228//!         run_game_logic(&mut world);
229//!     }
230//! }
231//!
232//! fn run_game_logic(world: &mut World) {
233//!     /*
234//!         Do game logic, possibly in multiple threads, accessing different parts of World,
235//!         possibly cloning 'ArcShift' instances for use by other threads
236//!     */
237//!
238//!     for model in world.models.iter_mut() {
239//!         // Accessing ArcShift using 'get' ensures
240//!         // old versions do not linger in RAM.
241//!         let model_ref : &CharacterModel = model.get();
242//!         // Do stuff with 'model_ref'
243//!     }
244//! }
245//!
246//!
247//! ```
248//!
249
250#[cfg(feature = "std")]
251extern crate std;
252
253extern crate alloc;
254
255use alloc::boxed::Box;
256
257use core::alloc::Layout;
258
259use crate::deferred_panics_helper::DropHandler;
260use crate::deferred_panics_helper::IDropHandler;
261use core::cell::UnsafeCell;
262use core::fmt::{Debug, Formatter};
263use core::marker::PhantomData;
264#[allow(unused)]
265use core::mem::align_of_val;
266use core::mem::size_of;
267#[allow(unused)]
268use core::mem::size_of_val;
269use core::mem::{transmute, ManuallyDrop};
270use core::panic::UnwindSafe;
271use core::ptr::{addr_of_mut, null, null_mut, NonNull};
272use core::sync::atomic::Ordering;
273// About unsafe code in this crate:
274// Some private functions contain unsafe code, and place limitations on their
275// callers, without these private functions being marked unsafe.
276// The rationale is that there are lots of operations that simply aren't unsafe, like
277// assigning null to a pointer, that could cause UB in unsafe code in this crate.
278// This crate is inherently dependent on all the code in it being correct. Therefore,
279// marking more functions unsafe buys us very little.
280// Note! The API of this crate is 100% safe and UB should be impossible to trigger by using it.
281// All public methods are 100% sound, this argument only concerns private methods.
282
283// All atomic primitives are reexported from a
284// local module called 'atomic', so we can easily change between using
285// types from 'std' (normal case) and types from shuttle/loom testing libraries.
286
287mod deferred_panics_helper;
288
289/// Declarations of atomic ops for using Arcshift in production
290#[cfg(all(not(loom), not(feature = "shuttle")))]
291mod atomic {
292    pub use core::sync::atomic::{fence, AtomicPtr, AtomicUsize, Ordering};
293    #[allow(unused)]
294    #[cfg(feature = "std")]
295    pub use std::sync::{Arc, Mutex};
296    #[allow(unused)]
297    #[cfg(feature = "std")]
298    pub use std::thread;
299}
300
301/// Declarations for verifying Arcshift using 'shuttle'
302#[cfg(feature = "shuttle")]
303mod atomic {
304    #[allow(unused)]
305    pub use shuttle::sync::atomic::{fence, AtomicPtr, AtomicUsize, Ordering};
306    #[allow(unused)]
307    pub use shuttle::sync::{Arc, Mutex};
308    #[allow(unused)]
309    pub use shuttle::thread;
310}
311
312/// Declarations for verifying Arcshift using 'loom'
313#[cfg(loom)]
314mod atomic {
315    pub use loom::sync::atomic::{fence, AtomicPtr, AtomicUsize, Ordering};
316    #[allow(unused)]
317    pub use loom::sync::{Arc, Mutex};
318    #[allow(unused)]
319    pub use loom::thread;
320}
321
322#[doc(hidden)]
323#[cfg(all(feature = "std", feature = "debug", not(loom)))]
324#[macro_export]
325macro_rules! debug_println {
326    ($($x:tt)*) => {
327        std::println!("{:?}: {}", $crate::atomic::thread::current().id(), std::format!($($x)*))
328    }
329}
330
331#[doc(hidden)]
332#[cfg(all(feature = "std", feature = "debug", loom))]
333#[macro_export]
334macro_rules! debug_println {
335    ($($x:tt)*) => { std::println!($($x)*) }
336}
337
338#[doc(hidden)]
339#[cfg(any(not(feature = "std"), not(feature = "debug")))]
340#[macro_export]
341macro_rules! debug_println {
342    ($($x:tt)*) => {{}};
343}
344
345/// Smart pointer with similar use case as std::sync::Arc, but with
346/// the added ability to atomically replace the contents of the Arc.
347/// See `crate` documentation for more information.
348///
349/// ```rust
350/// # extern crate arcshift;
351/// # #[cfg(any(feature="loom",feature="shuttle"))]
352/// # fn main() {}
353/// # #[cfg(not(any(feature="loom",feature="shuttle")))]
354/// # pub fn main() {
355/// # use arcshift::ArcShift;
356/// let mut instance = ArcShift::new("test");
357/// println!("Value: {:?}", instance.get());
358/// # }
359/// ```
360pub struct ArcShift<T: ?Sized> {
361    item: NonNull<ItemHolderDummy<T>>,
362
363    // Make sure ArcShift is invariant.
364    // ArcShift instances with different lifetimes of T should not be compatible,
365    // since could lead to a short-lived value T being insert into a chain which
366    // also has long-lived ArcShift instances with long-lived T.
367    pd: PhantomData<*mut T>,
368}
369impl<T> UnwindSafe for ArcShift<T> {}
370
371impl<T: ?Sized> Debug for ArcShift<T>
372where
373    T: Debug,
374{
375    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
376        write!(f, "ArcShift({:?})", self.shared_get())
377    }
378}
379
380impl<T: ?Sized> Debug for ArcShiftWeak<T>
381where
382    T: Debug,
383{
384    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
385        write!(f, "ArcShiftWeak(..)")
386    }
387}
388
389/// ArcShiftWeak is a way to keep a pointer to an object without preventing said object
390/// from being deallocated. This can be useful when creating cyclic data structure, to avoid
391/// memory leaks.
392///
393/// ```no_run
394/// # use arcshift::ArcShift;
395/// # #[cfg(any(feature="loom",feature="shuttle"))]
396/// # fn main() {}
397/// # #[cfg(not(any(feature="loom",feature="shuttle")))]
398/// # fn main() {
399/// # extern crate arcshift;
400/// # use arcshift::ArcShiftWeak;
401/// let original_instance = ArcShift::new("test");
402/// let light_instance = ArcShift::downgrade(&original_instance);
403/// let mut instance = light_instance.upgrade().unwrap();
404/// println!("Value: {:?}", instance.get());
405/// # }
406/// ```
407///
408/// WARNING! Because of implementation reasons, each instance of ArcShiftWeak will claim
409/// a memory equal to `size_of::<T>` (plus 5 words), even if the value inside it has freed,
410/// and even if all other instances of ArcShift/ArcShiftWeak have been dropped.
411/// If this limitation is unacceptable, consider using `ArcShiftWeak<Box<T>>` as your datatype,
412/// or possibly using a different crate.
413pub struct ArcShiftWeak<T: ?Sized> {
414    item: NonNull<ItemHolderDummy<T>>,
415}
416
417/// A handle that allows reloading an ArcShift instance without having 'mut' access.
418/// However, it does not implement `Sync`.
419pub mod cell;
420
421const fn is_sized<T: ?Sized>() -> bool {
422    size_of::<&T>() == size_of::<&()>()
423}
424
425/// SAFETY:
426/// If `T` is `Sync` and `Send`, `ArcShift<T>` can also be `Sync`
427unsafe impl<T: Sync + Send + ?Sized> Sync for ArcShift<T> {}
428
429/// SAFETY:
430/// If `T` is `Sync` and `Send`, `ArcShift<T>` can also be `Send`
431unsafe impl<T: Sync + Send + ?Sized> Send for ArcShift<T> {}
432
433/// SAFETY:
434/// If `T` is `Sync` and `Send`, `ArcShiftWeak<T>` can also be `Sync`
435unsafe impl<T: Sync + Send + ?Sized> Sync for ArcShiftWeak<T> {}
436
437/// SAFETY:
438/// If `T` is `Sync` and `Send`, `ArcShiftWeak<T>` can also be `Send`
439unsafe impl<T: Sync + Send + ?Sized> Send for ArcShiftWeak<T> {}
440
441#[repr(transparent)]
442struct UnsizedMetadata<T: ?Sized> {
443    #[cfg(feature = "nightly")]
444    meta: <T as std::ptr::Pointee>::Metadata,
445    #[cfg(not(feature = "nightly"))]
446    meta: *const (),
447    phantom: PhantomData<T>,
448}
449impl<T: ?Sized> Clone for UnsizedMetadata<T> {
450    fn clone(&self) -> Self {
451        *self
452    }
453}
454impl<T: ?Sized> Copy for UnsizedMetadata<T> {}
455impl<T: ?Sized> core::fmt::Debug for UnsizedMetadata<T> {
456    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
457        write!(f, "Metadata({:?})", self.meta)
458    }
459}
460
461#[allow(dead_code)]
462#[repr(C)]
463struct FatPtr<T: ?Sized> {
464    ptr: *mut u8,
465    meta: UnsizedMetadata<T>,
466}
467
468#[inline]
469fn arc_from_raw_parts_mut<T: ?Sized, M: IMetadata>(
470    data_ptr: *mut u8,
471    metadata: UnsizedMetadata<T>,
472) -> *mut ItemHolder<T, M> {
473    // SAFETY:
474    // This is the best I managed without using nightly-only features (August 2024).
475    // It is sound as long as the actual internal representation of fat pointers doesn't change.
476    #[cfg(not(feature = "nightly"))]
477    unsafe {
478        core::mem::transmute_copy(&FatPtr {
479            ptr: data_ptr,
480            meta: metadata,
481        })
482    }
483    #[cfg(feature = "nightly")]
484    {
485        std::ptr::from_raw_parts_mut(data_ptr, metadata.meta)
486    }
487}
488
489#[inline]
490#[cfg(not(any(feature = "std", feature = "nostd_unchecked_panics")))]
491#[cfg_attr(test, mutants::skip)]
492pub(crate) fn ptr_from_raw_parts_mut<T: ?Sized>(
493    data_ptr: *mut u8,
494    metadata: UnsizedMetadata<T>,
495) -> *mut T {
496    // SAFETY:
497    // This is the best I managed without using nightly-only features (August 2024).
498    // It is sound as long as the actual internal representation of fat pointers doesn't change.
499    #[cfg(not(feature = "nightly"))]
500    unsafe {
501        core::mem::transmute_copy(&FatPtr {
502            ptr: data_ptr,
503            meta: metadata,
504        })
505    }
506    #[cfg(feature = "nightly")]
507    {
508        std::ptr::from_raw_parts_mut(data_ptr, metadata.meta)
509    }
510}
511
512impl<T: ?Sized> UnsizedMetadata<T> {
513    #[inline]
514    #[cfg(not(feature = "nightly"))]
515    fn polyfill_metadata(cur_ptr: *const T) -> *const () {
516        if is_sized::<T>() {
517            unreachable!() //We're never using this function for sized data
518        } else {
519            let ptrptr = &cur_ptr as *const *const T as *const *const ();
520            // SAFETY:
521            // This is a trick to get at the 'metadata'-part of the fat-ptr 'cur_ptr'.
522            // It works in practice, as long as the internal representation of fat pointers doesn't
523            // change.
524            unsafe { *ptrptr.wrapping_offset(1) }
525        }
526    }
527
528    #[inline]
529    pub fn new(cur_ptr: *const T) -> UnsizedMetadata<T> {
530        UnsizedMetadata {
531            #[cfg(feature = "nightly")]
532            meta: std::ptr::metadata(cur_ptr),
533            #[cfg(not(feature = "nightly"))]
534            meta: Self::polyfill_metadata(cur_ptr),
535            phantom: PhantomData,
536        }
537    }
538}
539
540fn get_holder_layout<T: ?Sized>(ptr: *const T) -> Layout {
541    // SAFETY:
542    // The pointer 'ptr' is a valid pointer
543    let payload_layout = Layout::for_value(unsafe { &*ptr });
544    if is_sized::<T>() {
545        let layout = Layout::new::<ItemHolder<(), SizedMetadata>>();
546        let (layout, _) = layout.extend(payload_layout).unwrap();
547        layout.pad_to_align()
548    } else {
549        let layout = Layout::new::<UnsizedMetadata<T>>();
550        let (layout, _) = layout
551            .extend(Layout::new::<ItemHolder<(), UnsizedMetadata<T>>>())
552            .unwrap();
553        let (layout, _) = layout.extend(payload_layout).unwrap();
554        layout.pad_to_align()
555    }
556}
557
558fn to_dummy<T: ?Sized, M: IMetadata>(ptr: *const ItemHolder<T, M>) -> *const ItemHolderDummy<T> {
559    ptr as *mut ItemHolderDummy<T>
560}
561fn from_dummy<T: ?Sized, M: IMetadata>(ptr: *const ItemHolderDummy<T>) -> *const ItemHolder<T, M> {
562    get_full_ptr_raw::<T, M>(ptr)
563}
564
565macro_rules! with_holder {
566    ($p: expr, $t: ty, $item: ident, $f:expr) => {
567        if is_sized::<$t>() {
568            let $item = from_dummy::<$t, SizedMetadata>($p.as_ptr());
569            $f
570        } else {
571            let $item = from_dummy::<$t, UnsizedMetadata<$t>>($p.as_ptr());
572            $f
573        }
574    };
575}
576
577fn make_sized_or_unsized_holder_from_box<T: ?Sized>(
578    item: Box<T>,
579    prev: *mut ItemHolderDummy<T>,
580) -> *const ItemHolderDummy<T> {
581    if is_sized::<T>() {
582        to_dummy(make_sized_holder_from_box(item, prev))
583    } else {
584        to_dummy(make_unsized_holder_from_box(item, prev))
585    }
586}
587
588#[allow(clippy::let_and_return)]
589fn get_weak_count(count: usize) -> usize {
590    let count = count & ((1 << (usize::BITS - 2)) - 1);
591    #[cfg(feature = "validate")]
592    assert!(count < MAX_REF_COUNT / 2);
593    count
594}
595
596/// Node has next, or will soon have next. Note! It may seem this is unnecessary,
597/// since if there's a "next", then that next node will hold a weak ref, so a lonely
598/// reference could detect that there was a 'next' anyway.
599///
600/// Consider the following sequence:
601/// * Instance A and B point to Node N1
602/// * A starts dropping. It loads weak count '2'.
603/// * B updates, creating N2, and advanced to N2, and is then dropped.
604/// * Weak count of N1 is now still 2, so the compare_exchange for A *succeeds*
605///
606/// Having this flag makes it impossible for N1 to succeed
607const WEAK_HAVE_NEXT: usize = 1 << (usize::BITS - 1);
608const WEAK_HAVE_PREV: usize = 1 << (usize::BITS - 2);
609
610/// To avoid potential unsafety if refcounts overflow and wrap around,
611/// we have a maximum limit for ref count values. This limit is set with a large margin relative
612/// to the actual wraparound value. Note that this
613/// limit is enforced post fact, meaning that if there are more than usize::MAX/8 or so
614/// simultaneous threads, unsoundness can occur. This is deemed acceptable, because it is
615/// impossible to achieve in practice. Especially since it basically requires an extremely long
616/// running program with memory leaks, or leaking memory very fast in a tight loop. Without leaking,
617/// is impractical to achieve such high refcounts, since having usize::MAX/8 ArcShift instances
618/// alive on a 64-bit machine is impossible, since this would require usize::MAX/2 bytes of memory,
619/// orders of magnitude larger than any existing machine (in 2025).
620const MAX_REF_COUNT: usize = usize::MAX / 8;
621
622fn get_weak_prev(count: usize) -> bool {
623    (count & WEAK_HAVE_PREV) != 0
624}
625
626#[allow(unused)]
627fn get_weak_next(count: usize) -> bool {
628    (count & WEAK_HAVE_NEXT) != 0
629}
630
631#[cfg_attr(test, mutants::skip)]
632fn initial_weak_count<T: ?Sized>(prev: *const ItemHolderDummy<T>) -> usize {
633    if prev.is_null() {
634        1
635    } else {
636        1 | WEAK_HAVE_PREV
637    }
638}
639
640#[allow(unused)]
641#[cfg(all(feature = "std", feature = "debug"))]
642#[cfg_attr(test, mutants::skip)]
643fn format_weak(weak: usize) -> std::string::String {
644    let count = weak & ((1 << (usize::BITS - 2)) - 1);
645    let have_next = (weak & WEAK_HAVE_NEXT) != 0;
646    let have_prev = (weak & WEAK_HAVE_PREV) != 0;
647    std::format!("(weak: {} prev: {} next: {})", count, have_prev, have_next)
648}
649
650#[allow(unused)]
651fn make_unsized_holder_from_box<T: ?Sized>(
652    item: Box<T>,
653    prev: *mut ItemHolderDummy<T>,
654) -> *const ItemHolder<T, UnsizedMetadata<T>> {
655    let cur_ptr = Box::into_raw(item);
656
657    debug_println!("thesize: {:?}", cur_ptr);
658    let item_holder_ptr: *mut ItemHolder<T, UnsizedMetadata<T>>;
659
660    // SAFETY:
661    // The pointer 'cur_ptr' is a valid pointer (it's just been created by 'Box::into_raw'
662    let payload_layout = Layout::for_value(unsafe { &*cur_ptr });
663    let the_size = payload_layout.size();
664
665    if is_sized::<T>() {
666        unreachable!()
667    } else {
668        let layout = get_holder_layout::<T>(cur_ptr);
669
670        let metadata = UnsizedMetadata::new(cur_ptr);
671        debug_println!("Layout: {:?}, meta: {:?}", layout, metadata);
672        item_holder_ptr =
673            // SAFETY:
674            // core::alloc::alloc requires the allocated layout to have a nonzero size. This
675            // is fulfilled, since ItemHolder is non-zero sized even if T is zero-sized.
676            // The returned memory is uninitialized, but we will initialize the required parts of it
677            // below.
678            unsafe { arc_from_raw_parts_mut(alloc::alloc::alloc(layout) as *mut _, metadata) };
679        debug_println!("Sized result ptr: {:?}", item_holder_ptr);
680        // SAFETY:
681        // result_ptr is a valid pointer
682        unsafe {
683            addr_of_mut!((*item_holder_ptr).the_meta).write(metadata);
684        }
685    }
686
687    // SAFETY:
688    // The copy is safe because MaybeUninit<ItemHolder<T>> is guaranteed to have the same
689    // memory layout as ItemHolder<T>, so we're just copying a value of T to a new location.
690    unsafe {
691        (addr_of_mut!((*item_holder_ptr).payload) as *mut u8)
692            .copy_from(cur_ptr as *mut u8, the_size);
693    }
694    // SAFETY:
695    // next is just an AtomicPtr-type, for which all bit patterns are valid.
696    unsafe {
697        addr_of_mut!((*item_holder_ptr).prev).write(atomic::AtomicPtr::new(prev as *mut _));
698    }
699    // SAFETY:
700    // refcount is just an AtomicPtr-type, for which all bit patterns are valid.
701    unsafe {
702        addr_of_mut!((*item_holder_ptr).next).write(atomic::AtomicPtr::default());
703    }
704    // SAFETY:
705    // strong_count is just an AtomicUsize-type, for which all bit patterns are valid.
706    unsafe {
707        addr_of_mut!((*item_holder_ptr).strong_count).write(atomic::AtomicUsize::new(1));
708    }
709    // SAFETY:
710    // weak_count is just an AtomicUsize-type, for which all bit patterns are valid.
711    unsafe {
712        addr_of_mut!((*item_holder_ptr).weak_count)
713            .write(atomic::AtomicUsize::new(initial_weak_count(prev)));
714    }
715    // SAFETY:
716    // advance_count is just an AtomicUsize-type, for which all bit patterns are valid.
717    unsafe {
718        addr_of_mut!((*item_holder_ptr).advance_count).write(atomic::AtomicUsize::new(0));
719    }
720
721    // SAFETY:
722    // result_ptr is a valid pointer
723    #[cfg(feature = "validate")]
724    unsafe {
725        addr_of_mut!((*item_holder_ptr).magic1)
726            .write(std::sync::atomic::AtomicU64::new(0xbeefbeefbeef8111));
727    }
728
729    // SAFETY:
730    // result_ptr is a valid pointer
731    #[cfg(feature = "validate")]
732    unsafe {
733        addr_of_mut!((*item_holder_ptr).magic2)
734            .write(std::sync::atomic::AtomicU64::new(0x1234123412348111));
735    }
736
737    // SAFETY:
738    // input_ptr is a *mut T that has been created from a Box<T>.
739    // Converting it to a Box<MaybeUninit<T>> is safe, and will make sure that any drop-method
740    // of T is not run. We must not drop T here, since we've moved it to the 'result_ptr'.
741    let _t: Box<ManuallyDrop<T>> = unsafe { Box::from_raw(cur_ptr as *mut ManuallyDrop<T>) }; //Free the memory, but don't drop 'input'
742
743    item_holder_ptr
744}
745
746#[allow(unused)]
747fn make_sized_holder<T>(
748    payload: T,
749    prev: *const ItemHolderDummy<T>,
750) -> *mut ItemHolder<T, SizedMetadata> {
751    let holder = ItemHolder {
752        the_meta: SizedMetadata,
753        #[cfg(feature = "validate")]
754        magic1: std::sync::atomic::AtomicU64::new(0xbeefbeefbeef8111),
755        next: Default::default(),
756        prev: atomic::AtomicPtr::new(prev as *mut _),
757        strong_count: atomic::AtomicUsize::new(1),
758        weak_count: atomic::AtomicUsize::new(initial_weak_count::<T>(prev)),
759        advance_count: atomic::AtomicUsize::new(0),
760        #[cfg(feature = "validate")]
761        magic2: std::sync::atomic::AtomicU64::new(0x1234123412348111),
762        payload: UnsafeCell::new(ManuallyDrop::new(payload)),
763    };
764
765    Box::into_raw(Box::new(holder))
766}
767
768#[allow(unused)]
769fn make_sized_holder_from_box<T: ?Sized>(
770    item: Box<T>,
771    prev: *mut ItemHolderDummy<T>,
772) -> *mut ItemHolder<T, SizedMetadata> {
773    let cur_ptr = Box::into_raw(item);
774
775    debug_println!("thesize: {:?}", cur_ptr);
776
777    // SAFETY:
778    // 'cur_ptr' is a valid pointer, it's just been created by Box::into_raw
779    let payload_layout = Layout::for_value(unsafe { &*cur_ptr });
780    let the_size = payload_layout.size();
781
782    let layout = get_holder_layout::<T>(cur_ptr);
783
784    // SAFETY:
785    // The type '*mut ItemHolder<T, NoMeta>' is not actually a fat pointer. But since T:?Sized,
786    // the compiler treats it like a fat pointer with a zero-size metadata, which is not
787    // the exact same thing as a thin pointer (is my guess).
788    // Using transmute_copy to trim off the metadata is sound.
789    let item_holder_ptr: *mut ItemHolder<T, SizedMetadata> =
790        unsafe { core::mem::transmute_copy(&alloc::alloc::alloc(layout)) };
791
792    // SAFETY:
793    // The copy is safe because MaybeUninit<ItemHolder<T>> is guaranteed to have the same
794    // memory layout as ItemHolder<T>, so we're just copying a value of T to a new location.
795    unsafe {
796        (addr_of_mut!((*item_holder_ptr).payload) as *mut u8)
797            .copy_from(cur_ptr as *mut u8, the_size);
798    }
799    // SAFETY:
800    // next is just an AtomicPtr-type, for which all bit patterns are valid.
801    unsafe {
802        addr_of_mut!((*item_holder_ptr).prev).write(atomic::AtomicPtr::new(prev as *mut _));
803    }
804    // SAFETY:
805    // refcount is just an AtomicPtr-type, for which all bit patterns are valid.
806    unsafe {
807        addr_of_mut!((*item_holder_ptr).next).write(atomic::AtomicPtr::default());
808    }
809    // SAFETY:
810    // strong_count is just an AtomicUsize-type, for which all bit patterns are valid.
811    unsafe {
812        addr_of_mut!((*item_holder_ptr).strong_count).write(atomic::AtomicUsize::new(1));
813    }
814    // SAFETY:
815    // weak_count is just an AtomicUsize-type, for which all bit patterns are valid.
816    unsafe {
817        addr_of_mut!((*item_holder_ptr).weak_count)
818            .write(atomic::AtomicUsize::new(initial_weak_count(prev)));
819    }
820    // SAFETY:
821    // advance_count is just an AtomicUsize-type, for which all bit patterns are valid.
822    unsafe {
823        addr_of_mut!((*item_holder_ptr).advance_count).write(atomic::AtomicUsize::new(0));
824    }
825
826    // SAFETY:
827    // result_ptr is a valid pointer
828    #[cfg(feature = "validate")]
829    unsafe {
830        addr_of_mut!((*item_holder_ptr).magic1)
831            .write(std::sync::atomic::AtomicU64::new(0xbeefbeefbeef8111));
832    }
833
834    // SAFETY:
835    // result_ptr is a valid pointer
836    #[cfg(feature = "validate")]
837    unsafe {
838        addr_of_mut!((*item_holder_ptr).magic2)
839            .write(std::sync::atomic::AtomicU64::new(0x1234123412348111));
840    }
841
842    // SAFETY:
843    // input_ptr is a *mut T that has been created from a Box<T>.
844    // Converting it to a Box<MaybeUninit<T>> is safe, and will make sure that any drop-method
845    // of T is not run. We must not drop T here, since we've moved it to the 'result_ptr'.
846    let _t: Box<ManuallyDrop<T>> = unsafe { Box::from_raw(cur_ptr as *mut ManuallyDrop<T>) }; //Free the memory, but don't drop 'input'
847
848    item_holder_ptr
849}
850fn get_full_ptr_raw<T: ?Sized, M: IMetadata>(
851    dummy: *const ItemHolderDummy<T>,
852) -> *const ItemHolder<T, M> {
853    if is_sized::<T>() {
854        assert_eq!(
855            size_of::<*const ItemHolder<T, M>>(),
856            size_of::<*const ItemHolderDummy<T>>()
857        ); //<- Verify that *const T is not a fat ptr
858
859        // SAFETY:
860        // '*const ItemHolder<T, M>' is not _actually_ a fat pointer (it is just pointer sized),
861        // so transmuting from dummy to it is correct.
862        unsafe { core::mem::transmute_copy(&dummy) }
863    } else {
864        assert_eq!(size_of::<M>(), size_of::<usize>()); //<- Verify that *const ItemHolder<T> is a fat ptr
865
866        let ptr_data = dummy as *mut _;
867        debug_println!("Dummy data: {:?}", ptr_data);
868        let metadata_ptr = dummy as *const UnsizedMetadata<T>;
869        debug_println!(
870            "Unsized, meta: {:?}, val: {:?}",
871            metadata_ptr,
872            // SAFETY:
873            // metadata_ptr is a valid pointer
874            unsafe { *metadata_ptr }
875        );
876        // SAFETY:
877        // metadata_ptr is a valid pointer
878        let metadata = unsafe { *metadata_ptr };
879        arc_from_raw_parts_mut(ptr_data, metadata)
880    }
881}
882
883pub(crate) struct SizedMetadata;
884trait IMetadata {}
885impl IMetadata for SizedMetadata {}
886impl<T: ?Sized> IMetadata for UnsizedMetadata<T> {}
887
888#[repr(transparent)]
889struct ItemHolderDummy<T: ?Sized> {
890    // void pointers should point to u8
891    _dummy: u8,
892    _phantom_data: PhantomData<T>,
893}
894
895/*
896Invariants:
897 * ItemHolder cannot be deallocated if weak-count > 0
898 * When strong-count goes from 0->1, weak-count must be incremented by 1
899 * When strong-count goes from 1->0, weak-count must be decremented by 1
900 * The rightmost ItemHolder cannot be dropped if there are other items (to the left).
901   (But it may be possible to apply the janitor operation and drop them)
902 * An ItemHolder can have its strong-count increased even if it is dropped,
903   so just because strong-count is > 0 doesn't mean the item isn't dropped.
904 * If strong-count > 0, weak-count is also > 0.
905 * ItemHolder cannot be dropped if item.prev.advance_count > 0
906 * Linked list defined by prev-pointers is the nominal order of the chain
907 * ItemHolder can only be dropped when holding a lock on item,
908   and a lock on item 'item.next', after having set 'item.prev.next' to 'item.next' (or further to the right).
909   See do_advance_impl for details regarding 'advance_count'.
910 * While dropping, the janitor process must be run. If a concurrent janitor task is detected,
911   it must be marked as 'disturbed', and the disturbed task must re-run from the beginning
912   after completing.
913 * The weak-count has encoded in it 2 flags: HAVE_WEAK_NEXT and HAVE_WEAK_PREV. These decide
914   if the item has an item to the right (next) and/or to the left (prev). The HAVE_WEAK_NEXT
915   means there is, or soon will be, a neighbor to the right. HAVE_WEAK_PREV there isn't,
916   or soon won't be, a neighbor to the left. When using compare_exchange to set the weak_count
917   to 0, the code will atomically ensure no prev/next exist and that count is 0, in one operation.
918
919*/
920
921/// This structure represents the heap allocation in which ArcShift payloads reside.
922/// Align 8 is needed, since we store flags in the lower 2 bits of the ItemHolder-pointers
923/// In practice, the alignment of ItemHolder is 8 anyway, but we specify it here for clarity.
924#[repr(align(8))]
925#[repr(C)] // Just to get the 'magic' first and last in memory. Shouldn't hurt.
926struct ItemHolder<T: ?Sized, M: IMetadata> {
927    the_meta: M,
928    #[cfg(feature = "validate")]
929    magic1: std::sync::atomic::AtomicU64,
930    /// Can be incremented to keep the 'next' value alive. If 'next' is set to a new value, and
931    /// 'advance_count' is read as 0 after, then this node is definitely not going to advance to
932    /// some node *before* 'next'.
933    advance_count: atomic::AtomicUsize,
934
935    /// Pointer to the prev value, or null.
936    prev: atomic::AtomicPtr<ItemHolderDummy<T>>,
937    /// Strong count. When 0, the item is dropped.
938    /// Count must never be incremented from 0. This means increment must be done with
939    /// compare-exchange, not fetch_add.
940    strong_count: atomic::AtomicUsize,
941    /// Weak count. When reaches 0, the 'janitor' task may deallocate the node, iff
942    /// there are no previous nodes with 'advance_count' > 0.
943    /// The next node holds a weak ref to the prev. But prev nodes don't
944    /// hold weak counts on next.
945    /// MSB of 'weak_count' is a 'nonext' flag, that tells that this item is the last in the
946    /// chain. It is set to 1 *before* 'next' is assigned, so this is 0 when it is known
947    /// that this won't be the last ever.
948    weak_count: atomic::AtomicUsize,
949    #[cfg(feature = "validate")]
950    magic2: std::sync::atomic::AtomicU64,
951
952    /// Pointer to the next value or null. Possibly decorated (i.e, least significant bit set)
953    /// The decoration determines:
954    ///  * If janitor process is currently active for this node and those left of it
955    ///  * If payload has been deallocated
956    ///  * The current lock-holder (janitor) has been disturbed (i.e, some other thread couldn't
957    ///    do its job because it encountered the lock, and set the disturbed flag).
958    next: atomic::AtomicPtr<ItemHolderDummy<T>>,
959    pub(crate) payload: UnsafeCell<ManuallyDrop<T>>,
960}
961
962impl<T: ?Sized, M: IMetadata> PartialEq for ItemHolder<T, M> {
963    #[allow(clippy::ptr_eq)] //We actually want to use addr_eq, but it's not available on older rust versions. Let's just use this for now.
964    fn eq(&self, other: &ItemHolder<T, M>) -> bool {
965        self as *const _ as *const u8 == other as *const _ as *const u8
966    }
967}
968
969impl<T: ?Sized, M: IMetadata> ItemHolder<T, M> {
970    fn set_next(&self, undecorated_new_next: *const ItemHolderDummy<T>) {
971        #[cfg(feature = "validate")]
972        assert_eq!(
973            get_decoration(undecorated_new_next),
974            ItemStateEnum::UndisturbedUndecorated
975        );
976
977        // Synchronizes with:
978        // * 'has_payload' - irrelevant, has payload only cares about 'Dropped'-flag, not changed here
979        // * 'lock_node_for_gc' - irrelevant, we already own the lock, and we're not changing the lock-bit
980        // * 'do_upgrade_weak'
981        //
982        // Lock-free because we only loop if 'next' changes, which means
983        // some other node has made progress.
984        let mut prior_next = self.next.load(atomic::Ordering::Relaxed);
985        loop {
986            let new_next = decorate(undecorated_new_next, get_decoration(prior_next));
987            match self.next.compare_exchange(
988                prior_next,
989                new_next as *mut _,
990                atomic::Ordering::SeqCst, //atomic set_next
991                atomic::Ordering::SeqCst,
992            ) {
993                Ok(_) => {
994                    debug_println!(
995                        "set {:x?}.next = {:x?}",
996                        to_dummy(self as *const _),
997                        new_next
998                    );
999                    return;
1000                }
1001                Err(err) => {
1002                    prior_next = err;
1003                }
1004            }
1005        }
1006    }
1007
1008    /// Includes self
1009    #[allow(unused)]
1010    #[cfg(test)]
1011    #[cfg(feature = "std")]
1012    fn debug_all_to_left<'a>(&self) -> std::vec::Vec<&'a ItemHolder<T, M>> {
1013        let mut ret = alloc::vec::Vec::new();
1014        let mut item_ptr = self as *const ItemHolder<T, M>;
1015        // Lock-free because this loop is run in debug harness, and doesn't do any synchronization
1016        loop {
1017            // SAFETY:
1018            // item_ptr has just been created from the reference 'self', or was a non-null
1019            // 'prev' pointer of some valid reference, recursively. This method is only called
1020            // from the debug_validate machinery, that is 'unsafe' and requires the user to
1021            // make sure no concurrent access is occurring. At rest, 'prev' pointers are always
1022            // valid.
1023            ret.push(unsafe { &*item_ptr });
1024            // SAFETY:
1025            // See above. item_ptr is a valid pointer.
1026            let prev = from_dummy::<T, M>(unsafe { (*item_ptr).prev.load(Ordering::Relaxed) });
1027            if prev.is_null() {
1028                break;
1029            }
1030            item_ptr = prev;
1031        }
1032
1033        ret
1034    }
1035
1036    #[inline(always)]
1037    unsafe fn payload<'a>(&self) -> &'a T {
1038        // SAFETY:
1039        // Lifetime extension of shared references like this is permissible, as long as the object,
1040        // remains alive. Because of our refcounting, the object is kept alive as long as
1041        // the accessor (ArcShift-type) that calls this remains alive.
1042        unsafe { transmute::<&T, &'a T>(&*(self.payload.get())) }
1043    }
1044
1045    // SAFETY:
1046    // Node must be uniquely owned, and payload must never be accessed again
1047    #[cfg(not(any(feature = "std", feature = "nostd_unchecked_panics")))]
1048    unsafe fn take_boxed_payload(&self) -> Box<T> {
1049        let payload = &self.payload;
1050        debug_println!("boxing payload");
1051
1052        // SAFETY: item_ptr is now uniquely owned. We can drop it.
1053        let payload_val: &mut T = unsafe { &mut **(&mut *payload.get()) };
1054        let size = size_of_val(payload_val);
1055        let align = align_of_val(payload_val);
1056        let layout = Layout::from_size_align(size, align).unwrap();
1057        let thin_dest_ptr = if size == 0 {
1058            1 as *mut u8
1059        } else {
1060            alloc::alloc::alloc(layout)
1061        };
1062
1063        let fat_dest_ptr = if is_sized::<T>() {
1064            core::ptr::copy_nonoverlapping(payload_val as *mut _ as *mut u8, thin_dest_ptr, size);
1065            core::mem::transmute_copy(&thin_dest_ptr)
1066        } else {
1067            core::ptr::copy_nonoverlapping(payload_val as *mut _ as *mut u8, thin_dest_ptr, size);
1068            let meta = UnsizedMetadata::new(payload_val);
1069            ptr_from_raw_parts_mut(thin_dest_ptr, meta)
1070        };
1071
1072        Box::from_raw(fat_dest_ptr)
1073    }
1074
1075    /// Returns true if the node could be atomically locked
1076    fn lock_node_for_gc(&self) -> bool {
1077        // Lock free, see comment for each 'continue' statement, which are the only statements
1078        // that lead to looping.
1079        loop {
1080            // This can't be 'Relaxed', because if we read it as already locked and disturbed,
1081            // we must make sure that this is still the case at this point in the total order.
1082            // When dropping, after exiting here, we won't clean up the entire chain. Our current
1083            // thread is not going to stop this from occurring (we've advanced to the rightmost), but
1084            // if it doesn't do it itself, we must make sure some other thread does it.
1085            //
1086            // If we read a stale value here, it may have been written by some other node _before_
1087            // we advanced, in which case that node may have already retried the GC, and failed
1088            // (since we hadn't advanced). This would then lead to a memory leak.
1089            let cur_next = self.next.load(atomic::Ordering::SeqCst);
1090
1091            let decoration = get_decoration(cur_next);
1092            debug_println!(
1093                "loaded  {:x?}.next, got {:?} (decoration: {:?})",
1094                self as *const ItemHolder<T, M>,
1095                cur_next,
1096                decoration
1097            );
1098            if decoration.is_unlocked() {
1099                let decorated = decorate(undecorate(cur_next), decoration.with_gc());
1100                let success = self
1101                    .next
1102                    .compare_exchange(
1103                        cur_next,
1104                        decorated as *mut _,
1105                        Ordering::SeqCst, //atomic gc lock
1106                        atomic::Ordering::SeqCst,
1107                    )
1108                    .is_ok();
1109                debug_println!(
1110                    "Locking node {:x?}, result: {} (prior decoration: {:?}, new {:?})",
1111                    self as *const ItemHolder<T, M>,
1112                    success,
1113                    decoration,
1114                    get_decoration(decorated)
1115                );
1116                if !success {
1117                    // Lock free, because we only end up here if some other thread did one of:
1118                    // 1) added a new node, which is considered progress
1119                    // 2) has locked the node, which is not progress, but will only lead to us
1120                    //    setting the 'disturbed' flag, which is only one step, and thus lock free.
1121                    continue;
1122                }
1123                return true;
1124            } else {
1125                debug_println!(
1126                    "Locking node {:x?} failed, already decorated: {:?}",
1127                    self as *const ItemHolder<T, M>,
1128                    decoration
1129                );
1130                if !decoration.is_disturbed() {
1131                    let decorated = decorate(undecorate(cur_next), decoration.with_disturbed());
1132                    match self.next.compare_exchange(
1133                        cur_next,
1134                        decorated as *mut _,
1135                        Ordering::SeqCst, //atomic gc disturb
1136                        atomic::Ordering::SeqCst,
1137                    ) {
1138                        Ok(_) => {
1139                            debug_println!("Locking node {:x?} failed, set disturbed flag, new value: {:x?} (={:?})", self as * const ItemHolder<T, M>, decorated, get_decoration(decorated));
1140                        }
1141                        Err(prior) => {
1142                            if !get_decoration(prior).is_disturbed() {
1143                                // Lock free, because we can only end up here if some other thread did either:
1144                                // 1) Add a new node, which is considered progress
1145                                // 2) Removed the lock, which will lead to the other node advancing
1146                                //    to new things (which is progress), unless it was disturbed.
1147                                //    However, if it was disturbed, it wasn't due to us, since we
1148                                //    failed to set the disturbed flag.
1149                                continue;
1150                            }
1151                        }
1152                    }
1153                }
1154
1155                // Already decorated
1156                return false;
1157            }
1158        }
1159    }
1160
1161    /// Return true if node was disturbed
1162    #[must_use] //Not safe to leave a re-run request un-handled
1163    fn unlock_node(&self) -> bool {
1164        debug_println!("Unlocking node {:x?}", self as *const ItemHolder<T, M>);
1165        // Lock free, because we only loop if some other node modified 'next',
1166        // The only possible modifications are:
1167        // 1) Adding a new node, which is considered progress.
1168        // 2) Setting the disturbed flag, which means the other node has offloaded
1169        //    work on us, and is now proceeding to is next task, which means there is
1170        //    system progress, so algorithm remains lock free.
1171        loop {
1172            let cur_next = self.next.load(atomic::Ordering::Relaxed);
1173            let decoration = get_decoration(cur_next);
1174            let undecorated = decorate(undecorate(cur_next), decoration.without_gc_and_disturbed());
1175
1176            #[cfg(feature = "validate")]
1177            assert!(
1178                decoration.is_locked(),
1179                "node {:x?} was not actually locked, decoration: {:?}",
1180                self as *const _,
1181                decoration
1182            );
1183
1184            debug_println!("Unlocked dec {:x?}: {:x?}", self as *const Self, decoration);
1185            if self
1186                .next
1187                .compare_exchange(
1188                    cur_next,
1189                    undecorated as *mut _,
1190                    Ordering::SeqCst, //atomic gc unlock
1191                    Ordering::Relaxed,
1192                )
1193                .is_ok()
1194            {
1195                return decoration.is_disturbed();
1196            }
1197        }
1198    }
1199}
1200
1201#[cfg(all(feature = "std", any(loom, feature = "shuttle"), feature = "validate"))]
1202static MAGIC: std::sync::atomic::AtomicU16 = std::sync::atomic::AtomicU16::new(0);
1203
1204impl<T: ?Sized, M: IMetadata> ItemHolder<T, M> {
1205    #[cfg_attr(test, mutants::skip)]
1206    #[cfg(feature = "validate")]
1207    fn verify(ptr2: *const ItemHolder<T, M>) {
1208        {
1209            let ptr = ptr2 as *const ItemHolder<(), M>;
1210
1211            // SAFETY:
1212            // This function is never called with a null-ptr. Also, this is
1213            // just used for testing.
1214            let atomic_magic1 = unsafe { &*std::ptr::addr_of!((*ptr).magic1) };
1215            // SAFETY:
1216            // This function is never called with a null-ptr. Also, this is
1217            // just used for testing.
1218            let atomic_magic2 = unsafe { &*std::ptr::addr_of!((*ptr).magic2) };
1219
1220            let magic1 = atomic_magic1.load(Ordering::Relaxed);
1221            let magic2 = atomic_magic2.load(Ordering::Relaxed);
1222            if magic1 >> 16 != 0xbeefbeefbeef {
1223                debug_println!(
1224                    "Internal error - bad magic1 in {:?}: {} ({:x})",
1225                    ptr,
1226                    magic1,
1227                    magic1
1228                );
1229                debug_println!("Backtrace: {}", std::backtrace::Backtrace::capture());
1230                std::process::abort();
1231            }
1232            if magic2 >> 16 != 0x123412341234 {
1233                debug_println!(
1234                    "Internal error - bad magic2 in {:?}: {} ({:x})",
1235                    ptr,
1236                    magic2,
1237                    magic2
1238                );
1239                debug_println!("Backtrace: {}", std::backtrace::Backtrace::capture());
1240                std::process::abort();
1241            }
1242            #[cfg(not(any(loom, feature = "shuttle")))]
1243            {
1244                let m1 = magic1 & 0xffff;
1245                let m2 = magic2 & 0xffff;
1246                if m1 != 0x8111 || m2 != 0x8111 {
1247                    debug_println!("Internal error - bad magic in {:?} {:x} {:x}", ptr, m1, m2);
1248                }
1249            }
1250
1251            #[cfg(any(loom, feature = "shuttle"))]
1252            {
1253                let diff = (magic1 & 0xffff) as isize - (magic2 & 0xffff) as isize;
1254                if diff != 0 {
1255                    debug_println!(
1256                        "Internal error - bad magics in {:?}: {} ({:x}) and {} ({:x})",
1257                        ptr,
1258                        magic1,
1259                        magic1,
1260                        magic2,
1261                        magic2
1262                    );
1263                    debug_println!("Backtrace: {}", std::backtrace::Backtrace::capture());
1264                    panic!();
1265                }
1266                let magic = MAGIC.fetch_add(1, Ordering::Relaxed);
1267                let magic = magic as i64 as u64;
1268                atomic_magic1.fetch_and(0xffff_ffff_ffff_0000, Ordering::Relaxed);
1269                atomic_magic2.fetch_and(0xffff_ffff_ffff_0000, Ordering::Relaxed);
1270                atomic_magic1.fetch_or(magic, Ordering::Relaxed);
1271                atomic_magic2.fetch_or(magic, Ordering::Relaxed);
1272            }
1273        }
1274    }
1275}
1276
1277/// Check the magic values of the supplied pointer, validating it in a best-effort fashion
1278#[inline]
1279#[allow(unused)]
1280#[cfg_attr(test, mutants::skip)]
1281fn verify_item_impl<T: ?Sized, M: IMetadata>(_ptr: *const ItemHolderDummy<T>) {
1282    #[cfg(feature = "validate")]
1283    {
1284        assert_is_undecorated::<T, M>(_ptr);
1285
1286        let ptr = _ptr;
1287        let x = undecorate(ptr);
1288        if x != ptr {
1289            panic!("Internal error in ArcShift: Pointer given to verify was decorated, it shouldn't have been! {:?}", ptr);
1290        }
1291        if x.is_null() {
1292            return;
1293        }
1294        ItemHolder::<T, M>::verify(from_dummy::<T, M>(x))
1295    }
1296}
1297/// Check the magic values of the supplied pointer, validating it in a best-effort fashion
1298#[inline]
1299#[cfg_attr(test, mutants::skip)]
1300fn verify_item<T: ?Sized>(_ptr: *const ItemHolderDummy<T>) {
1301    #[cfg(feature = "validate")]
1302    {
1303        if is_sized::<T>() {
1304            verify_item_impl::<T, SizedMetadata>(_ptr)
1305        } else {
1306            verify_item_impl::<T, UnsizedMetadata<T>>(_ptr)
1307        }
1308    }
1309}
1310
1311const ITEM_STATE_LOCKED_FLAG: u8 = 1;
1312const ITEM_STATE_DROPPED_FLAG: u8 = 2;
1313const ITEM_STATE_DISTURBED_FLAG: u8 = 4;
1314
1315#[repr(u8)]
1316#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1317#[allow(unused)]
1318enum ItemStateEnum {
1319    /// Pointer is not decorated
1320    UndisturbedUndecorated = 0,
1321    UndisturbedGcIsActive = 1,
1322    UndisturbedPayloadDropped = 2,
1323    UndisturbedPayloadDroppedAndGcActive = 3,
1324    DisturbedUndecorated = 4,
1325    DisturbedGcIsActive = 5,
1326    DisturbedPayloadDropped = 6,
1327    DisturbedPayloadDroppedAndGcActive = 7,
1328}
1329
1330impl ItemStateEnum {
1331    #[allow(unused)]
1332    fn is_locked(self) -> bool {
1333        (self as u8 & ITEM_STATE_LOCKED_FLAG) != 0
1334    }
1335    fn is_disturbed(self) -> bool {
1336        (self as u8 & ITEM_STATE_DISTURBED_FLAG) != 0
1337    }
1338    fn is_unlocked(self) -> bool {
1339        (self as u8 & ITEM_STATE_LOCKED_FLAG) == 0
1340    }
1341    fn dropped(self) -> ItemStateEnum {
1342        // SAFETY:
1343        // All 3-bit values are legal ItemStateEnum values, so oring on 4 is ok
1344        unsafe { core::mem::transmute::<u8, ItemStateEnum>(self as u8 | ITEM_STATE_DROPPED_FLAG) }
1345    }
1346    fn with_gc(self) -> ItemStateEnum {
1347        // SAFETY:
1348        // All 3-bit values are legal ItemStateEnum values, so oring on 1 is ok
1349        unsafe { core::mem::transmute::<u8, ItemStateEnum>(self as u8 | ITEM_STATE_LOCKED_FLAG) }
1350    }
1351    fn with_disturbed(self) -> ItemStateEnum {
1352        // SAFETY:
1353        // All 3-bit values are legal ItemStateEnum values, so oring on 1 is ok
1354        unsafe { core::mem::transmute::<u8, ItemStateEnum>(self as u8 | ITEM_STATE_DISTURBED_FLAG) }
1355    }
1356    fn without_gc_and_disturbed(self) -> ItemStateEnum {
1357        // SAFETY:
1358        // All 3-bit values are legal ItemStateEnum values, so anding out 1 is ok
1359        unsafe {
1360            core::mem::transmute::<u8, ItemStateEnum>(
1361                self as u8 & (!ITEM_STATE_LOCKED_FLAG) & (!ITEM_STATE_DISTURBED_FLAG),
1362            )
1363        }
1364    }
1365    fn is_dropped(self) -> bool {
1366        (self as u8 & ITEM_STATE_DROPPED_FLAG) != 0
1367    }
1368}
1369
1370fn decorate<T: ?Sized>(
1371    ptr: *const ItemHolderDummy<T>,
1372    e: ItemStateEnum,
1373) -> *const ItemHolderDummy<T> {
1374    let curdecoration = (ptr as usize) & 7;
1375    ((ptr as *const u8).wrapping_offset((e as isize) - (curdecoration as isize)))
1376        as *const ItemHolderDummy<T>
1377}
1378
1379/// Get the state encoded in the decoration, if any.
1380/// Returns None if the pointer is undecorated null.
1381/// The pointer must be valid.
1382fn get_decoration<T: ?Sized>(ptr: *const ItemHolderDummy<T>) -> ItemStateEnum {
1383    if ptr.is_null() {
1384        return ItemStateEnum::UndisturbedUndecorated;
1385    }
1386    let raw = ((ptr as usize) & 7) as u8;
1387    // SAFETY:
1388    // All values `0..=7` are valid ItemStateEnum.
1389    // And the bitmask produces a value `0..=7`
1390    unsafe { core::mem::transmute::<u8, ItemStateEnum>(raw) }
1391}
1392
1393/// Panic if the pointer is decorated
1394#[allow(unused)]
1395#[cfg_attr(test, mutants::skip)]
1396#[inline]
1397fn assert_is_undecorated<T: ?Sized, M: IMetadata>(_ptr: *const ItemHolderDummy<T>) {
1398    #[cfg(feature = "validate")]
1399    {
1400        let raw = _ptr as usize & 7;
1401        if raw != 0 {
1402            panic!("Internal error in ArcShift - unexpected decorated pointer");
1403        }
1404    }
1405}
1406
1407/// Return an undecorated version of the given pointer.
1408/// Supplying an already undecorated pointer is not an error, and returns
1409/// the value unmodified.
1410fn undecorate<T: ?Sized>(cand: *const ItemHolderDummy<T>) -> *const ItemHolderDummy<T> {
1411    let raw = cand as usize & 7;
1412    (cand as *const u8).wrapping_offset(-(raw as isize)) as *const ItemHolderDummy<T>
1413}
1414
1415impl<T: ?Sized> Clone for ArcShift<T> {
1416    fn clone(&self) -> Self {
1417        let t = with_holder!(self.item, T, item, {
1418            let mut drop_jobs = DropHandler::default();
1419            let result = do_clone_strong(item, &mut drop_jobs);
1420            drop_jobs.resume_any_panics();
1421            result
1422        });
1423        ArcShift {
1424            // SAFETY:
1425            // The pointer returned by 'do_clone_strong' is always valid and non-null.
1426            item: unsafe { NonNull::new_unchecked(t as *mut _) },
1427            pd: PhantomData,
1428        }
1429    }
1430}
1431impl<T: ?Sized> Clone for ArcShiftWeak<T> {
1432    fn clone(&self) -> Self {
1433        let t = with_holder!(self.item, T, item, do_clone_weak(item));
1434        ArcShiftWeak {
1435            // SAFETY:
1436            // The pointer returned by 'do_clone_weak' is always valid and non-null.
1437            item: unsafe { NonNull::new_unchecked(t as *mut _) },
1438        }
1439    }
1440}
1441
1442fn do_clone_strong<T: ?Sized, M: IMetadata>(
1443    item_ptr: *const ItemHolder<T, M>,
1444    drop_job_queue: &mut impl IDropHandler<T, M>,
1445) -> *const ItemHolderDummy<T> {
1446    // SAFETY:
1447    // do_clone_strong must be called with a valid item_ptr
1448    let item = unsafe { &*item_ptr };
1449    debug_println!(
1450        "Strong clone, about to access strong count of {:x?}",
1451        item_ptr
1452    );
1453    let strong_count = item.strong_count.fetch_add(1, Ordering::Relaxed);
1454
1455    if strong_count > MAX_REF_COUNT {
1456        item.strong_count.fetch_sub(1, Ordering::Relaxed);
1457        panic!("strong ref count max limit exceeded")
1458    }
1459
1460    debug_println!(
1461        "strong-clone, new strong count: {:x?} is {}",
1462        item_ptr,
1463        strong_count + 1
1464    );
1465    #[cfg(feature = "validate")]
1466    assert!(strong_count > 0);
1467
1468    do_advance_strong::<T, M>(to_dummy::<T, M>(item_ptr), drop_job_queue)
1469}
1470
1471fn do_clone_weak<T: ?Sized, M: IMetadata>(
1472    item_ptr: *const ItemHolder<T, M>,
1473) -> *const ItemHolderDummy<T> {
1474    // SAFETY:
1475    // do_clone_weak must be called with a valid item_ptr
1476    let item = unsafe { &*item_ptr };
1477    let weak_count = item.weak_count.fetch_add(1, Ordering::Relaxed);
1478    if get_weak_count(weak_count) > MAX_REF_COUNT {
1479        item.weak_count.fetch_sub(1, Ordering::Relaxed);
1480        panic!("weak ref count max limit exceeded")
1481    }
1482    debug_println!(
1483        "==> weak-clone, fetch_add, new weak count: {:x?} is {}",
1484        item_ptr,
1485        format_weak(weak_count + 1)
1486    );
1487    #[cfg(feature = "validate")]
1488    assert!(weak_count > 0);
1489    to_dummy(item_ptr)
1490}
1491
1492fn do_upgrade_weak<T: ?Sized, M: IMetadata>(
1493    item_ptr: *const ItemHolder<T, M>,
1494    jobq: &mut DropHandler<T>,
1495) -> Option<*const ItemHolderDummy<T>> {
1496    debug_println!("executing do_upgrade_weak");
1497    // SAFETY:
1498    // do_upgrade_weak must be called with a valid item_ptr
1499    let start_item = unsafe { &*(item_ptr) };
1500    {
1501        // This is needed, since ostensibly, this method works on a weak clone of 'item_ptr'.
1502        // It is this weak clone that is converted to a strong item.
1503        // A Relaxed add is sufficient here, since we don't need to synchronize with anything.
1504        // We already have a weak link. The extra weak link added here only becomes relevant
1505        // the next time we _decrease_ weak_count, and since that will be an op on the same
1506        // atomic, it will definitely see the value written here, which is all we require.
1507        let weak_count = start_item.weak_count.fetch_add(1, Ordering::Relaxed);
1508        if get_weak_count(weak_count) > MAX_REF_COUNT {
1509            start_item.weak_count.fetch_sub(1, Ordering::Relaxed);
1510            panic!("weak ref count max limit exceeded")
1511        }
1512        debug_println!(
1513            "==> do_upgrade_weak {:x?} incr weak count to {}",
1514            item_ptr,
1515            format_weak(weak_count + 1)
1516        );
1517    }
1518    let mut item_ptr = to_dummy(item_ptr);
1519    // Lock free: See comment on each 'continue'
1520    loop {
1521        item_ptr = do_advance_weak::<T, M>(item_ptr);
1522        // We still have one weak count on 'item_ptr' at this point. do_advance_weak
1523        // decrements the weak on the original value, and gives you an advanced value with
1524        // one count on.
1525
1526        // SAFETY:
1527        // do_advance_weak always returns a valid non-null pointer
1528        let item = unsafe { &*from_dummy::<T, M>(item_ptr) };
1529        let prior_strong_count = item.strong_count.load(Ordering::SeqCst); //atomic upgrade read strong
1530        let item_next = item.next.load(Ordering::SeqCst); //atomic upgrade read next
1531        if !get_decoration(item_next).is_dropped() {
1532            if prior_strong_count == 0 {
1533                let _prior_weak_count = item.weak_count.fetch_add(1, Ordering::SeqCst); //atomic upgrade inc weak
1534                debug_println!(
1535                    "==> pre-upgrade strong=0 {:x?}, increase weak to {}",
1536                    item_ptr,
1537                    get_weak_count(_prior_weak_count) + 1
1538                );
1539            }
1540
1541            if item
1542                .strong_count
1543                .compare_exchange(
1544                    prior_strong_count,
1545                    prior_strong_count + 1,
1546                    Ordering::SeqCst, //atomic upgrade inc strong
1547                    Ordering::Relaxed,
1548                )
1549                .is_ok()
1550            {
1551                // SAFETY:
1552                // item_ptr has been advanced to, and we thus hold a weak ref.
1553                // it is a valid pointer.
1554                let item = unsafe { &*from_dummy::<T, M>(item_ptr) };
1555                let item_next = item.next.load(Ordering::SeqCst); //atomic upgrade check next drop
1556                if !undecorate(item_next).is_null() {
1557                    let new_prior_strong = item.strong_count.fetch_sub(1, Ordering::SeqCst); //atomic upgrade fail dropped
1558                    if new_prior_strong == 1 {
1559                        let _prior_weak_count = item.weak_count.fetch_sub(1, Ordering::SeqCst); //atomic upgrade fail dec last strong
1560                        #[cfg(feature = "validate")]
1561                        assert!(get_weak_count(_prior_weak_count) > 1);
1562                        debug_println!(
1563                            "==> {:x?} reduced weak to {}",
1564                            item_ptr,
1565                            get_weak_count(_prior_weak_count - 1)
1566                        );
1567                    }
1568                    // Lock free. We only get here if some other node has added a new node,
1569                    // which is considered progress.
1570                    continue;
1571                }
1572
1573                let _reduce_weak = item.weak_count.fetch_sub(1, Ordering::SeqCst); //atomic upgrade sub weak
1574                debug_println!(
1575                    "==> upgrade success, new strong_count: {}, new weak: {}",
1576                    prior_strong_count + 1,
1577                    format_weak(_reduce_weak - 1)
1578                );
1579                #[cfg(feature = "validate")]
1580                assert!(
1581                    get_weak_count(_reduce_weak) > 1,
1582                    "assertion failed: in do_upgrade_weak(1), reduced weak {:x?} to 0",
1583                    item_ptr
1584                );
1585
1586                return Some(item_ptr);
1587            } else {
1588                if prior_strong_count == 0 {
1589                    let _prior_weak_count = item.weak_count.fetch_sub(1, Ordering::SeqCst); //atomic upgrade race dec weak
1590                    debug_println!(
1591                        "==> pre-upgrade strong=0 race2 {:x?}, decrease weak to {}",
1592                        item_ptr,
1593                        get_weak_count(_prior_weak_count) - 1
1594                    );
1595                    #[cfg(feature = "validate")]
1596                    assert!(get_weak_count(_prior_weak_count) > 1);
1597                }
1598                debug_println!("Race on strong_count _increase_ - loop.");
1599                // Lcok free. We only get here if some other node has succeeded in increasing or
1600                // decreasing strong count, which only happens if there is progress, unless
1601                // the node undid a strong_count modification because of a detected race.
1602                // The possible strong_count undo operations are:
1603                // 1) If ArcShift::clone exceeds the maximum strong count limit. This is an
1604                //    error case, but we'll also consider it progress.
1605                // 2) If ArcShift::upgrade detects a race on 'next' (new node added), which
1606                //    is considered system-wide progress.
1607                // 3) In ArcShift::update, if it races with adding a new node, which is
1608                //    considered progress.
1609                continue; //Race on strong count, try again
1610            }
1611        } else {
1612            do_drop_weak::<T, M>(item_ptr, jobq);
1613            return None;
1614        }
1615    }
1616}
1617
1618/// Returns an up-to-date pointer.
1619/// The closure is called with references to the old and new items, and allows
1620/// the caller to, for instance, decrease/inrcease strong counts. If no advance could be done,
1621/// this is always because we're already at the most up-to-date value. The closure is not called
1622/// in this case.
1623/// If the update closure fails, this can only be because there's a new 'next', and the
1624/// current item has been dropped.
1625///
1626/// This function requires the caller to have some sort of reference to 'item_ptr', so that
1627/// it can't go away during execution. This method does not touch that reference count.
1628///
1629/// The 'update' closure is called with a weak-ref taken on 'b', and 'a' in its original state.
1630/// It must either keep the weak ref, or possibly convert it to a strong ref.
1631/// It must also release whatever refcount it had on the original 'item_ptr'.
1632///
1633/// Guaranteed to return a valid, non-null pointer
1634fn do_advance_impl<T: ?Sized, M: IMetadata>(
1635    mut item_ptr: *const ItemHolderDummy<T>,
1636    mut update: impl FnMut(*const ItemHolder<T, M>, *const ItemHolder<T, M>) -> bool,
1637) -> *const ItemHolderDummy<T> {
1638    let start_ptr = item_ptr;
1639    verify_item(item_ptr);
1640
1641    debug_println!("advancing from {:x?}", item_ptr);
1642    // Lock free, because we traverse the chain and eventually reach the end,
1643    // except that we may fail 'update', in which case we loop.
1644    // However, update fails only if there has been system-wide progress (see comment in
1645    // do_advance_strong).
1646    loop {
1647        debug_println!("In advance-loop, item_ptr: {:x?}", item_ptr);
1648        // SAFETY:
1649        // item_ptr is a pointer we have advanced to. Forward advance always visits only
1650        // valid pointers. This is a core algorithm of ArcShift. By the careful atomic operations
1651        // below, and by knowing how the janitor-task works, we make sure that either 'advance_count'
1652        // or 'weak_count' keep all visited references alive, such that they cannot be garbage
1653        // collected.
1654        let item: &ItemHolder<T, M> = unsafe { &*from_dummy(item_ptr as *mut _) };
1655
1656        let next_ptr = undecorate(item.next.load(Ordering::SeqCst)); //atomic advance load next
1657        debug_println!("advancing from {:x?}, next_ptr = {:x?}", item_ptr, next_ptr);
1658        if next_ptr.is_null() {
1659            #[allow(clippy::collapsible_if)]
1660            if item_ptr != start_ptr {
1661                if !update(from_dummy(start_ptr), from_dummy(item_ptr)) {
1662                    debug_println!("upgrade failed, probably no payload");
1663                    continue;
1664                }
1665            }
1666            return item_ptr;
1667        }
1668
1669        let _advanced = item.advance_count.fetch_add(1, Ordering::SeqCst); //atomic advance inc advance_count
1670        debug_println!(
1671            "advance: Increasing {:x?}.advance_count to {}",
1672            item_ptr,
1673            _advanced + 1
1674        );
1675
1676        // This fence shouldn't be necessary, but without it loom fails, because
1677        // it doesn't actually model 'SeqCst' correctly. In principle, we could
1678        // have this fence only when running under loom, but then we'd not be testing
1679        // exactly the same thing as we run in prod, which seems unfortunate.
1680        //
1681        // Specifically, without this fence, loom might reorder this load before
1682        // the 'fetch_add' above, opening up the possibility that 'item.next' may be
1683        // dropped before we can do 'advance_count', and we'd still get that 'next'
1684        // in the load below.
1685        atomic::fence(Ordering::SeqCst);
1686
1687        // We must reload next, because it's only the next that is _now_ set that is actually
1688        // protected by 'advance_count' above!
1689        let next_ptr = undecorate(item.next.load(Ordering::SeqCst)); //atomic advance reload next
1690
1691        #[cfg(feature = "validate")]
1692        assert_ne!(next_ptr, item_ptr);
1693        // SAFETY:
1694        // next_ptr is guarded by our advance_count ref that we grabbed above.
1695        let next: &ItemHolder<T, M> = unsafe { &*from_dummy(next_ptr) };
1696        debug_println!("advance: Increasing next(={:x?}).weak_count", next_ptr);
1697        let _res = next.weak_count.fetch_add(1, Ordering::SeqCst); //atomic
1698        debug_println!(
1699            "==> do_advance_impl: increment weak of {:?}, was {}, now {}",
1700            next_ptr,
1701            format_weak(_res),
1702            format_weak(_res + 1),
1703        );
1704
1705        let _advanced = item.advance_count.fetch_sub(1, Ordering::SeqCst); //atomic advance dec advance_count
1706        debug_println!(
1707            "advance: Decreasing {:x?}.advance_count to {}",
1708            item_ptr,
1709            _advanced - 1
1710        );
1711
1712        if item_ptr != start_ptr {
1713            debug_println!("do_advance_impl: decrease weak from {:x?}", item_ptr);
1714            let _res = item.weak_count.fetch_sub(1, Ordering::SeqCst); //atomic advance dec weak_count
1715            debug_println!(
1716                "==> do_advance_impl: decrease weak from {:x?} - decreased to {}",
1717                item_ptr,
1718                format_weak(_res - 1)
1719            );
1720
1721            // This should never reach 0 here. We _know_ that 'item' has a 'next'. Thus, this 'next'
1722            // must hold a reference count on this.
1723            #[cfg(feature = "validate")]
1724            assert!(
1725                get_weak_count(_res) > 1,
1726                "non rightmost node {:x?} can't be left with 0 weak count, but weak became {}",
1727                item_ptr,
1728                get_weak_count(_res) - 1
1729            );
1730        }
1731        item_ptr = next_ptr;
1732    }
1733}
1734
1735// Guaranteed to return a valid, non-null pointer
1736fn do_advance_weak<T: ?Sized, M: IMetadata>(
1737    item_ptr: *const ItemHolderDummy<T>,
1738) -> *const ItemHolderDummy<T> {
1739    do_advance_impl(
1740        item_ptr,
1741        |a: *const ItemHolder<T, M>, _b: *const ItemHolder<T, M>| {
1742            // SAFETY:
1743            // a is a valid pointer. do_advance_impl only supplies usable pointers to the callback.
1744            let _a_weak = unsafe { (*a).weak_count.fetch_sub(1, Ordering::SeqCst) }; //atomic advance weak dec weak_count a
1745
1746            // We have a weak ref count on 'b' given to use by `do_advance_impl`,
1747            // which we're fine with this and don't need to adjust b.weak_count
1748
1749            debug_println!(
1750                "==> weak advance {:x?}, decremented weak counts to a:{:x?}={}",
1751                a,
1752                a,
1753                format_weak(_a_weak.wrapping_sub(1)),
1754            );
1755            #[cfg(feature = "validate")]
1756            assert!(get_weak_count(_a_weak) > 1);
1757            true
1758        },
1759    )
1760}
1761
1762// Always returns valid, non-null, pointers
1763#[inline(never)]
1764fn do_advance_strong<T: ?Sized, M: IMetadata>(
1765    item_ptr: *const ItemHolderDummy<T>,
1766    drop_job_queue: &mut impl IDropHandler<T, M>,
1767) -> *const ItemHolderDummy<T> {
1768    do_advance_impl::<_, M>(item_ptr, move |a, b| {
1769        // SAFETY:
1770        // b is a valid pointer. do_advance_impl supplies the closure with only valid pointers.
1771        let mut b_strong = unsafe { (*b).strong_count.load(Ordering::SeqCst) }; //atomic advance strong load b strong_count
1772
1773        // Lock free, since we only loop when compare_exchange fails on 'strong_count', something
1774        // which only occurs when 'strong_count' changes, which only occurs when there is
1775        // system wide progress.
1776        //
1777        // Note, do_advance_strong_impl will loop if this returns false. See each
1778        // such return for an argument why this only happens if there's been system side
1779        // progress.
1780        loop {
1781            debug_println!(
1782                "do_advance_strong {:x?} -> {:x?} (b-count = {})",
1783                a,
1784                b,
1785                b_strong
1786            );
1787
1788            if b_strong == 0 {
1789                // a strong ref must _always_ imply a weak count, and that weak count must
1790                // always be decrementable by whoever happens to decrement the count to 0.
1791                // That might not be us (because we might race with another invocation of this code),
1792                // that might also increment the count.
1793                // SAFETY:
1794                // b is a valid pointer (see above)
1795                let _prior_weak = unsafe { (*b).weak_count.fetch_add(1, Ordering::SeqCst) }; //atomic advance strong inc b weak_count
1796                debug_println!(
1797                    "==> Prior to strong_count increment {:x?} from 0, added weak count. Weak now: {}",
1798                    b,
1799                    format_weak(_prior_weak + 1)
1800                );
1801            }
1802
1803            // SAFETY:
1804            // b is a valid pointer. See above.
1805            match unsafe {
1806                (*b).strong_count.compare_exchange(
1807                    b_strong,
1808                    b_strong + 1,
1809                    Ordering::SeqCst, //atomic advance icn b strong_count
1810                    atomic::Ordering::SeqCst,
1811                )
1812            } {
1813                Ok(_) => {
1814                    debug_println!(
1815                        "b-strong increased {:x?}: {} -> {}",
1816                        b,
1817                        b_strong,
1818                        b_strong + 1
1819                    );
1820                    // SAFETY:
1821                    // b is a valid pointer. See above.
1822                    let next_ptr = unsafe { (*b).next.load(Ordering::SeqCst) }; //atomic advance reload next
1823                    if !undecorate(next_ptr).is_null() {
1824                        // Race - even though _did_ have payload prior to us grabbing the strong count, it now might not.
1825                        // This can only happen if there's some other node to the right that _does_ have a payload.
1826
1827                        // SAFETY:
1828                        // b is a valid pointer. See above.
1829                        let prior_strong =
1830                            unsafe { (*b).strong_count.fetch_sub(1, Ordering::SeqCst) }; //atomic advance fail dec b strong_count
1831                        debug_println!("do_advance_strong:rare race, new _next_ appeared when increasing strong count: {:?} (decr strong back to {}) <|||||||||||||||||||||||||||||||||||||||||||||||||||||||>", b, prior_strong -1);
1832                        #[cfg(feature = "validate")]
1833                        assert!(
1834                            prior_strong > 0,
1835                            "strong count {:x?} must be >0, but was 0",
1836                            b
1837                        );
1838
1839                        // If b_strong was not 0, it had a weak count. Our increment of it above would have made it so that
1840                        // no other thread could observe it going to 0. After our decrement below, it might go to zero.
1841                        // If it goes to zero in our decrement, and b_strong was not 0, it falls on us to free the weak_count.
1842                        // Note, in the span from the increment to this decrement, it could be argued that the implicitly owned weak count
1843                        // is "wrong". However, this is not observable, since the weak count is definitely not 0 (this closure does own a
1844                        // weak ref).
1845                        if prior_strong == 1 {
1846                            // SAFETY:
1847                            // b is a valid pointer. See above.
1848                            let _b_weak_count =
1849                                unsafe { (*b).weak_count.fetch_sub(1, Ordering::SeqCst) }; //atomic advance fail dec weak_count
1850                            debug_println!("==> do_advance_strong:rare2 {:x?} reduced strong count back to 0, reduced weak to: {}", b, get_weak_count(_b_weak_count-1));
1851                            #[cfg(feature = "validate")]
1852                            assert!(get_weak_count(_b_weak_count) > 1);
1853                        }
1854                        debug_println!("race, other thread added new node");
1855                        // Lock free, we can only get here if another thread has added a new node.
1856                        return false;
1857                    }
1858                    #[cfg(feature = "validate")]
1859                    assert!(!get_decoration(next_ptr).is_dropped());
1860
1861                    // SAFETY:
1862                    // b is a valid pointer. See above.
1863                    let _b_weak_count = unsafe { (*b).weak_count.fetch_sub(1, Ordering::SeqCst) }; //atomic advance dec weak_count
1864                    debug_println!(
1865                        "==> strong advance {:x?}, reducing free weak b-count to {:?}",
1866                        b,
1867                        format_weak(_b_weak_count - 1)
1868                    );
1869                    #[cfg(feature = "validate")]
1870                    assert!(get_weak_count(_b_weak_count) > 1);
1871
1872                    // SAFETY:
1873                    // a is a valid pointer. See above.
1874                    let a_strong = unsafe { (*a).strong_count.fetch_sub(1, Ordering::SeqCst) }; //atomic advance dec a strong_count
1875                    #[cfg(feature = "validate")]
1876                    assert_ne!(a_strong, 0);
1877                    debug_println!(
1878                        "a-strong {:x?} decreased {} -> {}",
1879                        a,
1880                        a_strong,
1881                        a_strong - 1,
1882                    );
1883                    if a_strong == 1 {
1884                        do_drop_payload_if_possible(a, false, drop_job_queue);
1885                        // Remove the implicit weak granted by the strong
1886                        // SAFETY:
1887                        // a is a valid pointer. See above.
1888                        let _a_weak = unsafe { (*a).weak_count.fetch_sub(1, Ordering::SeqCst) }; //atomic advance drop payload a
1889                        debug_println!("==> do_advance_strong:maybe dropping payload of a {:x?} (because strong-count is now 0). Adjusted weak to {}", a, format_weak(_a_weak.wrapping_sub(1)));
1890                        #[cfg(feature = "validate")]
1891                        assert!(get_weak_count(_a_weak) > 0);
1892                    }
1893                    return true;
1894                }
1895                Err(err_value) => {
1896                    if b_strong == 0 {
1897                        // SAFETY:
1898                        // b is a valid pointer. See above.
1899                        let _prior_weak = unsafe { (*b).weak_count.fetch_sub(1, Ordering::SeqCst) }; //atomic advance race
1900                        debug_println!("==> do_advance_strong: race on strong_count for {:x?} (restore-decr weak to {})", b, get_weak_count(_prior_weak - 1));
1901                        #[cfg(feature = "validate")]
1902                        assert!(get_weak_count(_prior_weak) > 1);
1903                    }
1904                    b_strong = err_value;
1905                }
1906            }
1907        }
1908    })
1909}
1910
1911fn raw_deallocate_node<T: ?Sized, M: IMetadata>(
1912    item_ptr: *const ItemHolder<T, M>,
1913    jobq: &mut impl IDropHandler<T, M>,
1914) {
1915    verify_item(to_dummy(item_ptr));
1916    raw_do_unconditional_drop_payload_if_not_dropped(item_ptr as *mut ItemHolder<T, M>, jobq);
1917
1918    // SAFETY:
1919    // item_ptr is going to be deallocated, and the caller must make sure
1920    // that it has exclusive access.
1921    #[cfg(feature = "validate")]
1922    assert_eq!(
1923        // SAFETY:
1924        // item_ptr is guaranteed valid by caller
1925        unsafe { (*item_ptr).strong_count.load(Ordering::SeqCst) },
1926        0,
1927        "{:x?} strong count must be 0 when deallocating",
1928        item_ptr
1929    );
1930
1931    #[cfg(feature = "validate")]
1932    {
1933        // SAFETY:
1934        // item_ptr is guaranteed valid by caller
1935        let item_ref = unsafe { &*(item_ptr as *mut ItemHolder<T, M>) };
1936        item_ref.magic1.store(0xdeaddead, Ordering::Relaxed);
1937        item_ref.magic2.store(0xdeaddea2, Ordering::Relaxed);
1938    }
1939
1940    do_dealloc(item_ptr);
1941}
1942
1943#[derive(PartialEq)]
1944enum NodeStrongStatus {
1945    // We saw nodes with strong refs, that weren't the rightmost node
1946    StrongRefsFound,
1947    // We visited all nodes all the way to the leftmost one, and there were no strong refs
1948    // to the left of the rightmost one.
1949    NoStrongRefsExist,
1950    // We had to stop our leftward traverse, because nodes were locked, so we couldn't
1951    // say for sure if strong refs existed. This means that some other node is running an
1952    // old gc, and upon completion of this gc it will realize it has to advance, so this
1953    // other node will have a chance to detect that no strong refs exist.
1954    Indeterminate,
1955}
1956
1957fn do_janitor_task<T: ?Sized, M: IMetadata>(
1958    start_ptr: *const ItemHolder<T, M>,
1959    jobq: &mut impl IDropHandler<T, M>,
1960) -> (bool /*need re-run*/, NodeStrongStatus) {
1961    verify_item(to_dummy(start_ptr));
1962
1963    let mut have_seen_left_strong_refs = false;
1964    fn get_strong_status(strong: bool, leftmost: bool) -> NodeStrongStatus {
1965        if strong {
1966            NodeStrongStatus::StrongRefsFound
1967        } else if leftmost {
1968            NodeStrongStatus::NoStrongRefsExist
1969        } else {
1970            NodeStrongStatus::Indeterminate
1971        }
1972    }
1973
1974    debug_println!("Janitor task for {:x?}", start_ptr);
1975    // SAFETY:
1976    // start_ptr must be a valid pointer. This falls on the caller toensure.
1977    let start = unsafe { &*start_ptr };
1978
1979    let start_ptr = to_dummy(start_ptr);
1980
1981    if !start.lock_node_for_gc() {
1982        debug_println!("Janitor task for {:x?} - gc already active!", start_ptr);
1983        return (false, get_strong_status(have_seen_left_strong_refs, false));
1984    }
1985
1986    debug_println!("Loading prev of {:x?}", start_ptr);
1987    let mut cur_ptr: *const _ = start.prev.load(Ordering::SeqCst); //atomic janitor load prev
1988    debug_println!("Loaded prev of {:x?}, got: {:x?}", start_ptr, cur_ptr);
1989    let rightmost_candidate_ptr = cur_ptr;
1990    if cur_ptr.is_null() {
1991        debug_println!("Janitor task for {:x?} - no earlier nodes exist", start_ptr);
1992        // There are no earlier nodes to clean up
1993        let need_rerun = start.unlock_node();
1994        return (
1995            need_rerun,
1996            get_strong_status(have_seen_left_strong_refs, true),
1997        );
1998    }
1999
2000    let mut rightmost_deletable = null();
2001
2002    // It may seems that we iterate through the chain in many different ways
2003    // in this method, and that it should be possible to abstract this.
2004    // However, it turns out to be slightly tricky, since the iteration is always
2005    // done in a very careful way to maintain correctness, and exchanging the order
2006    // of two innocent looking statements can cause it to fail.
2007
2008    {
2009        let mut any_failed_locks = false;
2010        let cur_lock_start = cur_ptr;
2011        let mut cur_ptr = cur_ptr;
2012        debug_println!("Lock sweep start at {:x?}", cur_lock_start);
2013        let mut failed_lock = null();
2014        loop {
2015            // SAFETY: cur_ptr is a valid pointer It starts out equal to
2016            // 'start.prev', which is always valid or null, and we check it for null.
2017            // We then fetch 'cur.prev' pointers, which is valid, since we only do so if
2018            // we managed to take a lock. No other thread may free prev if it is locked.
2019            let cur: &ItemHolder<T, M> = unsafe { &*from_dummy(cur_ptr) };
2020
2021            if !cur.lock_node_for_gc() {
2022                failed_lock = cur_ptr;
2023                any_failed_locks = true;
2024                debug_println!(
2025                    "Janitor task for {:x?} - found node already being gced: {:x?}",
2026                    start_ptr,
2027                    cur_ptr
2028                );
2029                break;
2030            }
2031
2032            let prev_ptr: *const _ = cur.prev.load(Ordering::SeqCst); //atomic janitor load prev 2
2033            debug_println!("Janitor loop considering {:x?} -> {:x?}", cur_ptr, prev_ptr);
2034            if prev_ptr.is_null() {
2035                debug_println!(
2036                    "Janitor task for {:x?} - found leftmost node: {:x?}",
2037                    start_ptr,
2038                    cur_ptr
2039                );
2040                break;
2041            }
2042            cur_ptr = prev_ptr;
2043        }
2044        if any_failed_locks {
2045            let mut cur_ptr = cur_lock_start;
2046            debug_println!("Cleanup sweep start at {:x?}", cur_lock_start);
2047            let mut anyrerun = false;
2048            loop {
2049                debug_println!("Cleanup sweep at {:x?}", cur_ptr);
2050                if cur_ptr.is_null() {
2051                    anyrerun = true;
2052                    break;
2053                }
2054                if cur_ptr == failed_lock {
2055                    debug_println!("Cleanup sweep is at end {:x?}", cur_ptr);
2056                    break;
2057                }
2058                // SAFETY:
2059                // cur_ptr is a valid pointer. It's just the left traverse, across
2060                // a chain of locked nodes.
2061                let cur: &ItemHolder<T, M> = unsafe { &*from_dummy(cur_ptr) };
2062
2063                let prev_ptr: *const _ = cur.prev.load(Ordering::SeqCst); //atomic janitor cleanup load prev
2064                anyrerun |= cur.unlock_node();
2065                debug_println!("Cleanup sweep going to {:x?}", prev_ptr);
2066                cur_ptr = prev_ptr;
2067            }
2068            anyrerun |= start.unlock_node();
2069            debug_println!("Janitor failed to grab locks. Rerun: {:?}", anyrerun);
2070            return (
2071                anyrerun,
2072                get_strong_status(have_seen_left_strong_refs, false),
2073            );
2074        }
2075    }
2076
2077    // Lock free, since this just iterates through the chain of nodes,
2078    // which has a bounded length.
2079    loop {
2080        debug_println!("Accessing {:x?} in first janitor loop", cur_ptr);
2081        // SAFETY:
2082        // cur_ptr remains a valid pointer. Our lock on the nodes, as we traverse them backward,
2083        // ensures that no other janitor task can free them.
2084        let cur: &ItemHolder<T, M> = unsafe { &*from_dummy(cur_ptr) };
2085        debug_println!("Setting next of {:x?} to {:x?}", cur_ptr, start_ptr,);
2086        #[cfg(feature = "validate")]
2087        assert_ne!(cur_ptr, start_ptr);
2088
2089        if cur.strong_count.load(Ordering::SeqCst) > 0 {
2090            //atomic janitor check strong_count
2091            have_seen_left_strong_refs = true;
2092        }
2093
2094        let prev_ptr: *const _ = cur.prev.load(Ordering::SeqCst); //atomic janitor load prev 4
2095        debug_println!("Janitor loop considering {:x?} -> {:x?}", cur_ptr, prev_ptr);
2096        if prev_ptr.is_null() {
2097            debug_println!(
2098                "Janitor task for {:x?} - found leftmost node: {:x?}",
2099                start_ptr,
2100                cur_ptr
2101            );
2102            break;
2103        }
2104
2105        // SAFETY:
2106        // We guarded 'cur_ptr', and it is thus alive. It holds a weak-ref on its 'prev', which
2107        // means that ref must now be keeping 'prev' alive. This means 'prev' is known to be a
2108        // valid pointer. We never decorate prev-pointers, so no undecorate is needed.
2109        let prev: &ItemHolder<T, M> = unsafe { &*from_dummy(prev_ptr) };
2110        #[cfg(feature = "validate")]
2111        assert_ne!(prev_ptr, start_ptr);
2112
2113        prev.set_next(start_ptr);
2114
2115        // We need a fence here, because otherwise this load could be reordered before the
2116        // `set_next`call above, while running under loom. This could lead to a situation
2117        // where a thread reads the previous next-pointer, and we still don't see the new
2118        // 'advance_count' here. With the fence, we know that either:
2119        // 1) The other thread has seen our new 'next' value supplied above
2120        // or
2121        // 2) We see their incremented 'advance_count'.
2122        // Note, we may thus block the deletion of next unnecessarily, if the other thread
2123        // read our new 'next' value just after we wrote it, and incremented 'advance_count'
2124        // here before we loaded it. This race condition is benign however, the other thread
2125        // will also try janitoring, and will delete the node if necessary.
2126        atomic::fence(Ordering::SeqCst);
2127
2128        let adv_count = prev.advance_count.load(Ordering::SeqCst); //atomic janitor check advance_count
2129        debug_println!("advance_count of {:x?} is {}", prev_ptr, adv_count);
2130        if adv_count > 0 {
2131            debug_println!(
2132                "Janitor task for {:x?} - node {:x?} has advance in progress",
2133                start_ptr,
2134                prev_ptr
2135            );
2136            // All to the right of cur_ptr could be targets of the advance.
2137            // Because of races, we don't know that their target is actually 'start_ptr'
2138            // (though it could be).
2139            rightmost_deletable = cur_ptr;
2140        }
2141        cur_ptr = prev_ptr;
2142    }
2143
2144    fn delete_nodes_that_can_be_deleted<T: ?Sized, M: IMetadata>(
2145        mut item_ptr: *const ItemHolderDummy<T>,
2146        jobq: &mut impl IDropHandler<T, M>,
2147    ) -> Option<*const ItemHolderDummy<T>> {
2148        let mut deleted_count = 0;
2149
2150        // Lock free, since this loop at most iterates once per node in the chain.
2151        loop {
2152            if item_ptr.is_null() {
2153                debug_println!(
2154                    "Find non-deleted {:x?}, count = {}, item_ptr = {:x?}",
2155                    item_ptr,
2156                    deleted_count,
2157                    item_ptr,
2158                );
2159                return (deleted_count > 0).then_some(item_ptr);
2160            }
2161            // SAFETY:
2162            // caller must ensure item_ptr is valid, or null. And it is not null, we checked above.
2163            let item: &ItemHolder<T, M> = unsafe { &*from_dummy(item_ptr as *mut _) };
2164            // Item is *known* to have a 'next'!=null here, so
2165            // we know weak_count == 1 implies it is only referenced by its 'next'
2166            let item_weak_count = item.weak_count.load(Ordering::SeqCst); //atomic janitor load weak_count
2167            if get_weak_count(item_weak_count) > 1 {
2168                debug_println!(
2169                    "==> Find non-deleted {:x?}, count = {}, found node with weak count > 1 ({})",
2170                    item_ptr,
2171                    deleted_count,
2172                    format_weak(item_weak_count)
2173                );
2174                return (deleted_count > 0).then_some(item_ptr);
2175            }
2176            debug_println!(
2177                "==> Deallocating node in janitor task: {:x?}, dec: ?, weak count: {}",
2178                item_ptr,
2179                // SAFETY:
2180                // item_ptr is valid
2181                format_weak(item_weak_count),
2182            );
2183
2184            #[cfg(feature = "validate")]
2185            {
2186                let prior_item_weak_count = item.weak_count.load(Ordering::SeqCst);
2187                #[cfg(feature = "validate")]
2188                assert_eq!(
2189                    get_weak_count(prior_item_weak_count),
2190                    1,
2191                    "{:x?} weak_count should still be 1, and we decrement it to 0",
2192                    item_ptr
2193                );
2194            }
2195
2196            let prev_item_ptr = item.prev.load(Ordering::SeqCst); //atomic janitor deletion load prev
2197            raw_deallocate_node(from_dummy::<T, M>(item_ptr as *mut _), jobq);
2198            deleted_count += 1;
2199            item_ptr = prev_item_ptr;
2200        }
2201    }
2202
2203    let mut cur_ptr = rightmost_candidate_ptr;
2204    let mut right_ptr = start_ptr;
2205    let mut must_see_before_deletes_can_be_made = rightmost_deletable;
2206    debug_println!("Starting final janitor loop");
2207    let mut need_rerun = false;
2208    // We must retain the locks one-past the node with the lock (lock works leftward)
2209    let mut unlock_carry: Option<*const ItemHolder<T, M>> = None;
2210    let mut do_unlock = |node: Option<*const ItemHolder<T, M>>| {
2211        if let Some(unlock) = unlock_carry.take() {
2212            // SAFETY:
2213            // Caller ensures pointer is valid.
2214            need_rerun |= unsafe { (*unlock).unlock_node() };
2215        }
2216        unlock_carry = node;
2217    };
2218
2219    #[cfg(feature = "validate")]
2220    assert!(!cur_ptr.is_null());
2221
2222    // Iterate through chain, deleting nodes when possible
2223    // Lock free, since this loop just iterates through each node in the chain.
2224    while !cur_ptr.is_null() {
2225        let new_predecessor = must_see_before_deletes_can_be_made
2226            .is_null()
2227            .then(|| delete_nodes_that_can_be_deleted::<T, M>(cur_ptr, jobq))
2228            .flatten();
2229
2230        if cur_ptr == must_see_before_deletes_can_be_made {
2231            debug_println!("Found must_see node: {:x?}", cur_ptr);
2232            // cur_ptr can't be deleted itself, but nodes further to the left can
2233            must_see_before_deletes_can_be_made = null_mut();
2234        }
2235
2236        if let Some(new_predecessor_ptr) = new_predecessor {
2237            // SAFETY:
2238            // right_ptr is always the start pointer, or the previous pointer we visited.
2239            // in any case, it is non-null and valid.
2240            let right: &ItemHolder<T, M> = unsafe { &*from_dummy(right_ptr) };
2241            debug_println!(
2242                "After janitor delete, setting {:x?}.prev = {:x?}",
2243                right_ptr,
2244                new_predecessor_ptr
2245            );
2246            if new_predecessor_ptr.is_null() {
2247                right
2248                    .weak_count
2249                    .fetch_and(!WEAK_HAVE_PREV, Ordering::SeqCst); //atomic janitor clear prev
2250            }
2251            right
2252                .prev
2253                .store(new_predecessor_ptr as *mut _, Ordering::SeqCst); //atomic janitor unlink
2254
2255            if new_predecessor_ptr.is_null() {
2256                debug_println!("new_predecessor is null");
2257                break;
2258            }
2259            debug_println!("found new_predecessor: {:x?}", new_predecessor_ptr);
2260            right_ptr = new_predecessor_ptr;
2261            // SAFETY:
2262            // We only visit nodes we have managed to lock. new_predecessor is such a node
2263            // and it is not being deleted. It is safe to access.
2264            let new_predecessor = unsafe { &*from_dummy::<T, M>(new_predecessor_ptr) };
2265            cur_ptr = new_predecessor.prev.load(Ordering::SeqCst); //atomic janitor load prev 6
2266            #[cfg(feature = "validate")]
2267            assert_ne!(
2268                new_predecessor_ptr as *const _,
2269                null(),
2270                "assert failed, {:?} was endptr",
2271                new_predecessor_ptr
2272            );
2273            do_unlock(Some(new_predecessor));
2274            debug_println!("New candidate advanced to {:x?}", cur_ptr);
2275        } else {
2276            debug_println!("Advancing to left, no node to delete found {:x?}", cur_ptr);
2277            // SAFETY:
2278            // All the pointers we traverse (leftward) through the chain are valid,
2279            // since we lock them succesively as we traverse.
2280            let cur: &ItemHolder<T, M> = unsafe { &*from_dummy(cur_ptr) };
2281            right_ptr = cur_ptr;
2282            cur_ptr = cur.prev.load(Ordering::SeqCst); //atomic janitor load prev 7
2283            debug_println!("Advancing to left, advanced to {:x?}", cur_ptr);
2284            do_unlock(Some(cur));
2285        }
2286    }
2287    do_unlock(None);
2288    debug_println!("Unlock start-node {:x?}", start_ptr);
2289    need_rerun |= start.unlock_node();
2290    debug_println!("start-node unlocked: {:x?}", start_ptr);
2291    (
2292        need_rerun,
2293        get_strong_status(have_seen_left_strong_refs, true),
2294    )
2295}
2296
2297/// drop_payload should be set to drop the payload of 'original_item_ptr' iff it is
2298/// either not rightmost, or all refs to all nodes are just weak refs (i.e, no strong refs exist)
2299fn do_drop_weak<T: ?Sized, M: IMetadata>(
2300    original_item_ptr: *const ItemHolderDummy<T>,
2301    drop_job_queue: &mut impl IDropHandler<T, M>,
2302) {
2303    debug_println!("drop weak {:x?}", original_item_ptr);
2304    let mut item_ptr = original_item_ptr;
2305    // Lock free, since we only loop in these cases:
2306    // 1) If the janitor task was disturbed. If it was, some other thread has offloaded
2307    //    work on us, which means the other thread could carry on and do other stuff, which
2308    //    means there is system wide progress.
2309    // 2) If a new 'next' pointer has been set, i.e, a new node has been added. This is
2310    //    considered progress.
2311    // 3) Some other node changed the weak_count. In that case, there are two cases:
2312    //   3a) That other node was running 'do_drop_weak'. After changing the weak_count
2313    //       there are no more loop conditions, so it has definitely made progress.
2314    //   3b) That node was running some other work. It managed to change the weak count,
2315    //       and is not running 'do_drop_weak', so the system is making progress as long as
2316    //       that other thread is making progress, which it must be (see all other comments),
2317    //       and it cannot have been obstructed by this thread.
2318    loop {
2319        debug_println!("drop weak loop {:?}", item_ptr);
2320        item_ptr = do_advance_weak::<T, M>(item_ptr);
2321        let (need_rerun, strong_refs) =
2322            do_janitor_task(from_dummy::<T, M>(item_ptr), drop_job_queue);
2323        if need_rerun {
2324            debug_println!("Janitor {:?} was disturbed. Need rerun", item_ptr);
2325            continue;
2326        }
2327
2328        // When we get here, we know we are advanced to the most recent node
2329
2330        debug_println!("Accessing {:?}", item_ptr);
2331        // SAFETY:
2332        // item_ptr is a pointer that was returned by 'do_advance_weak'. The janitor task
2333        // never deallocates the pointer given to it (only prev pointers of that pointer).
2334        // do_advance_weak always returns valid non-null pointers.
2335        let item: &ItemHolder<T, M> = unsafe { &*from_dummy(item_ptr) };
2336        let prior_weak = item.weak_count.load(Ordering::SeqCst); //atomic drop_weak load weak_count
2337
2338        #[cfg(feature = "validate")]
2339        assert!(get_weak_count(prior_weak) > 0);
2340
2341        let next_ptr = item.next.load(Ordering::SeqCst); //atomic drop_weak load next
2342        let have_next = !undecorate(next_ptr).is_null();
2343        if have_next {
2344            // drop_weak raced with 'add'.
2345            debug_println!(
2346                "add race {:x?}, prior_weak: {}",
2347                item_ptr,
2348                format_weak(prior_weak)
2349            );
2350            continue;
2351        }
2352        // Note, 'next' may be set here, immediately after us loading 'next' above.
2353        // This is benign. In this case, 'prior_weak' will also have get_weak_next(prior_weak)==true
2354        // and get_weak_count(prior_weak)>1. We will not drop the entire chain, but whoever
2355        // just set 'next' definitely will.
2356
2357        #[cfg(feature = "debug")]
2358        if get_weak_next(prior_weak) {
2359            debug_println!("raced in drop weak - {:x?} was previously advanced to rightmost, but now it has a 'next' again (next is ?)", item_ptr);
2360        }
2361
2362        debug_println!("No add race, prior_weak: {}", format_weak(prior_weak));
2363
2364        // We now have enough information to know if we can drop payload, if desired
2365        {
2366            // SAFETY:
2367            // item_ptr was returned by do_advance_weak, and is thus valid.
2368            let o_item = unsafe { &*from_dummy::<T, M>(item_ptr) };
2369            let o_strong = o_item.strong_count.load(Ordering::SeqCst); //atomic drop_weak check strong_count
2370            if o_strong == 0 {
2371                let can_drop_now_despite_next_check = if strong_refs
2372                    == NodeStrongStatus::NoStrongRefsExist
2373                {
2374                    debug_println!("final drop analysis {:x?}: Can drop this payload, because no strong refs exists anywhere", item_ptr);
2375                    true
2376                } else {
2377                    debug_println!("final drop analysis {:x?}: no exemption condition found, can't drop this payload", item_ptr);
2378                    false
2379                };
2380                if can_drop_now_despite_next_check {
2381                    do_drop_payload_if_possible(
2382                        o_item,
2383                        can_drop_now_despite_next_check,
2384                        drop_job_queue,
2385                    );
2386                }
2387            }
2388        }
2389
2390        match item.weak_count.compare_exchange(
2391            prior_weak,
2392            prior_weak - 1,
2393            Ordering::SeqCst, //atomic drop_weak dec weak
2394            Ordering::SeqCst,
2395        ) {
2396            Ok(_) => {
2397                debug_println!(
2398                    "==> drop weak {:x?}, did reduce weak to {}",
2399                    item_ptr,
2400                    format_weak(prior_weak - 1)
2401                );
2402            }
2403            Err(_err_weak) => {
2404                debug_println!(
2405                    "drop weak {:x?}, raced on count decrement (was {}, expected {})",
2406                    item_ptr,
2407                    format_weak(_err_weak),
2408                    format_weak(prior_weak)
2409                );
2410
2411                // Note:
2412                // This case occurs if two threads race to drop a weak ref.
2413                // Crucially, it is also in play to distinguish between these two scenarios:
2414                // 1: Two nodes have weak refs. One of them (A) is dropped, the other (B) remains.
2415                // 2: Two nodes have weak refs. One of them (A) updates the value, and is then
2416                //    dropped. The other (B) remains.
2417                //
2418                // In both cases, when B is dropped, it will see a total weak count of 2.
2419                // However, in case 2, B must re-run 'advance', and do another janitor cycle.
2420                // This *has* to be checked during the weak_count compare_exchange, since doing
2421                // it at any point prior to that opens up the risk of a race where node A above
2422                // manages to update and drop before the compare-exchange.
2423
2424                continue;
2425            }
2426        }
2427
2428        debug_println!(
2429            "Prior weak of {:x?} is {}",
2430            item_ptr,
2431            format_weak(prior_weak)
2432        );
2433        if get_weak_count(prior_weak) == 1 {
2434            #[cfg(feature = "validate")]
2435            if get_weak_next(prior_weak) {
2436                std::eprintln!("This case should not be possible, since it implies the 'next' object didn't increase the refcount");
2437                std::process::abort();
2438            }
2439            // We know there's no next here either, since we checked 'get_weak_next' before the cmpxch, so we _KNOW_ we're the only user now.
2440            if !get_weak_prev(prior_weak) {
2441                debug_println!("drop weak {:x?}, prior count = 1, raw deallocate", item_ptr);
2442                drop_job_queue.report_sole_user();
2443                raw_deallocate_node(from_dummy::<T, M>(item_ptr), drop_job_queue);
2444            } else {
2445                debug_println!(
2446                    "drop weak {:x?}, couldn't drop node, because there are nodes to the left",
2447                    item_ptr
2448                );
2449                // These nodes will presumably realize they're holding leftwise refs, and before dropping
2450                // they must advance. And thus the whole chain _will_ be collected.
2451            }
2452        }
2453        return;
2454    }
2455}
2456
2457fn do_update<T: ?Sized, M: IMetadata>(
2458    initial_item_ptr: *const ItemHolder<T, M>,
2459    mut val_dummy_factory: impl FnMut(&ItemHolder<T, M>) -> Option<*const ItemHolderDummy<T>>,
2460    drop_job_queue: &mut impl IDropHandler<T, M>,
2461) -> *const ItemHolderDummy<T> {
2462    let mut item_ptr = to_dummy::<T, M>(initial_item_ptr);
2463    verify_item(item_ptr);
2464
2465    // Lock free. This loop only loops if another thread has changed 'next', which
2466    // means there is system wide progress.
2467    loop {
2468        item_ptr = do_advance_strong::<T, M>(item_ptr, drop_job_queue);
2469
2470        // SAFETY:
2471        // item_ptr was returned by do_advance_strong, and is thus valid.
2472        let item = unsafe { &*from_dummy::<T, M>(item_ptr) };
2473        debug_println!(
2474            "Updating {:x?} , loading next of {:x?}",
2475            initial_item_ptr,
2476            item_ptr
2477        );
2478
2479        let cur_next = item.next.load(Ordering::SeqCst); //atomic update check_next
2480        if !undecorate(cur_next).is_null() {
2481            continue;
2482        }
2483        let Some(val_dummy) = val_dummy_factory(item) else {
2484            return item_ptr;
2485        };
2486        let new_next = decorate(val_dummy, get_decoration(cur_next));
2487
2488        debug_println!("Updating {:x?} to {:x?}", item_ptr, val_dummy);
2489        let val = from_dummy::<T, M>(val_dummy) as *mut ItemHolder<T, M>;
2490        // SAFETY:
2491        // val is the new value supplied by the caller. It is always valid, and it is not
2492        // yet linked into the chain, so no other node could free it.
2493        unsafe { (*val).prev = atomic::AtomicPtr::new(item_ptr as *mut _) };
2494
2495        // We must increment weak_count here, because this is the signal that
2496        // causes the drop_weak impl to realize that it is racing with an 'update',
2497        // (in contrast to perhaps racing with another drop, in which case it might
2498        // win the race and might be required to deallocate, to avoid memory leaks).
2499        let _weak_was = item.weak_count.fetch_add(1, Ordering::SeqCst);
2500
2501        #[cfg(feature = "validate")]
2502        assert!(_weak_was > 0);
2503        debug_println!(
2504            "do_update: increment weak of {:?} (weak now: {})",
2505            item_ptr,
2506            format_weak(_weak_was + 1)
2507        );
2508
2509        debug_println!("bef item.next.compare_exchange");
2510        match item.next.compare_exchange(
2511            cur_next,
2512            new_next as *mut _,
2513            Ordering::SeqCst, //atomic update exchange next
2514            Ordering::SeqCst,
2515        ) {
2516            Ok(_) => {
2517                item.weak_count.fetch_or(WEAK_HAVE_NEXT, Ordering::SeqCst); //atomic update mark have next
2518                debug_println!("aft1 item.next.compare_exchange");
2519            }
2520            Err(_) => {
2521                debug_println!("aft2 item.next.compare_exchange");
2522                debug_println!("race, update of {:x?} to {:x?} failed", item_ptr, new_next);
2523                let _res = item.weak_count.fetch_sub(1, Ordering::SeqCst); //atomic update fail dec weak_count
2524                debug_println!(
2525                    "==> race, decreasing {:x?} weak to {}",
2526                    item_ptr,
2527                    format_weak(_res - 1)
2528                );
2529                #[cfg(feature = "validate")]
2530                assert!(get_weak_count(_res) > 1);
2531
2532                continue;
2533            }
2534        }
2535
2536        let strong_count = item.strong_count.fetch_sub(1, Ordering::SeqCst); //atomic update dec strong_count
2537        debug_println!(
2538            "do_update: strong count {:x?} is now decremented to {}",
2539            item_ptr,
2540            strong_count - 1,
2541        );
2542        if strong_count == 1 {
2543            // It's safe to drop payload here, we've just now added a new item
2544            // that has its payload un-dropped, so there exists something to advance to.
2545            do_drop_payload_if_possible(from_dummy::<T, M>(item_ptr), false, drop_job_queue);
2546            let _weak_count = item.weak_count.fetch_sub(1, Ordering::SeqCst); //atomic update dec weak_count
2547            debug_println!(
2548                "==> do_update: decrement weak of {:?}, new weak: {}",
2549                item_ptr,
2550                format_weak(_weak_count.saturating_sub(1))
2551            );
2552            #[cfg(feature = "validate")]
2553            assert!(get_weak_count(_weak_count) > 1);
2554        }
2555
2556        item_ptr = val_dummy;
2557
2558        //If the strong_count of the previous went to 0, do a janitor-cycle
2559        if strong_count == 1 {
2560            // Lock free
2561            // Only loops if another thread has set the 'disturbed' flag, meaning it has offloaded
2562            // work on us, and it has made progress, which means there is system wide progress.
2563            loop {
2564                let (need_rerun, _strong_refs) =
2565                    do_janitor_task(from_dummy::<T, M>(item_ptr), drop_job_queue);
2566                if need_rerun {
2567                    item_ptr = do_advance_strong::<T, M>(item_ptr, drop_job_queue);
2568                    debug_println!("Janitor {:?} was disturbed. Need rerun", item_ptr);
2569                    continue;
2570                }
2571                break;
2572            }
2573        }
2574        return item_ptr;
2575    }
2576}
2577
2578// Drops payload, unless either:
2579// * We're the rightmost node
2580// * The payload is already dropped
2581// the item_ptr must be valid.
2582fn do_drop_payload_if_possible<T: ?Sized, M: IMetadata>(
2583    item_ptr: *const ItemHolder<T, M>,
2584    override_rightmost_check: bool,
2585    drop_queue: &mut impl IDropHandler<T, M>,
2586) {
2587    // SAFETY:
2588    // caller must supply valid pointer.
2589    let item = unsafe { &*(item_ptr) };
2590    // Lock free. This only loops if another thread has changed next, which implies
2591    // progress.
2592    loop {
2593        let next_ptr = item.next.load(Ordering::Relaxed);
2594        let decoration = get_decoration(next_ptr);
2595        if decoration.is_dropped() || (undecorate(next_ptr).is_null() && !override_rightmost_check)
2596        {
2597            debug_println!(
2598                "Not dropping {:x?} payload, because it's rightmost",
2599                item_ptr
2600            );
2601            return;
2602        }
2603        debug_println!(
2604            "Drop if possible, {:x?}, cur dec: {:?}, dropped dec {:?}",
2605            item_ptr,
2606            decoration,
2607            decoration.dropped()
2608        );
2609        match item.next.compare_exchange(
2610            next_ptr,
2611            decorate(undecorate(next_ptr), decoration.dropped()) as *mut _,
2612            Ordering::SeqCst, //atomic mark dropped
2613            Ordering::SeqCst,
2614        ) {
2615            Ok(_) => {
2616                break;
2617            }
2618            Err(err_ptr) => {
2619                if !get_decoration(err_ptr).is_dropped() {
2620                    debug_println!("Raced, new attempt to drop {:x?} payload", item_ptr);
2621                    continue;
2622                }
2623                debug_println!("Raced, {:x?} now already dropped", item_ptr);
2624                return;
2625            }
2626        }
2627    }
2628    debug_println!("Dropping payload {:x?} (dec: ?)", item_ptr,);
2629    // SAFETY: item_ptr must be valid, guaranteed by caller.
2630    drop_queue.do_drop(item_ptr as *mut _);
2631}
2632
2633// Caller must guarantee poiner is uniquely owned
2634fn raw_do_unconditional_drop_payload_if_not_dropped<T: ?Sized, M: IMetadata>(
2635    item_ptr: *mut ItemHolder<T, M>,
2636    drop_job_queue: &mut impl IDropHandler<T, M>,
2637) {
2638    debug_println!("Unconditional drop of payload {:x?}", item_ptr);
2639    // SAFETY: Caller must guarantee pointer is uniquely owned
2640    let item = unsafe { &*(item_ptr) };
2641    let next_ptr = item.next.load(Ordering::SeqCst); //atomic drop check dropped
2642    let decoration = get_decoration(next_ptr);
2643    if !decoration.is_dropped() {
2644        debug_println!(
2645            "Actual drop of payload {:x?}, it wasn't already dropped",
2646            item_ptr
2647        );
2648        drop_job_queue.do_drop(item_ptr);
2649    }
2650}
2651fn do_dealloc<T: ?Sized, M: IMetadata>(item_ptr: *const ItemHolder<T, M>) {
2652    // SAFETY:
2653    // item_ptr is still a valid, exclusively owned pointer
2654    let layout = get_holder_layout(&unsafe { &*item_ptr }.payload);
2655    // SAFETY:
2656    // fullptr is a valid uniquely owned pointer that we must deallocate
2657    debug_println!("Calling dealloc {:x?}", item_ptr);
2658
2659    #[cfg(feature = "validate")]
2660    {
2661        // SAFETY:
2662        // item_ptr is valid
2663        let item_ref = unsafe { &*(item_ptr as *mut ItemHolder<T, M>) };
2664        item_ref.magic1.store(0xdeaddead, Ordering::Relaxed);
2665        item_ref.magic2.store(0xdeaddea2, Ordering::Relaxed);
2666    }
2667
2668    // SAFETY:
2669    // item_ptr is still a valid, exclusively owned pointer
2670    unsafe { alloc::alloc::dealloc(item_ptr as *mut _, layout) }
2671}
2672
2673fn do_drop_strong<T: ?Sized, M: IMetadata>(
2674    full_item_ptr: *const ItemHolder<T, M>,
2675    drop_job_queue: &mut impl IDropHandler<T, M>,
2676) {
2677    debug_println!("drop strong of {:x?}", full_item_ptr,);
2678    let mut item_ptr = to_dummy(full_item_ptr);
2679
2680    item_ptr = do_advance_strong::<T, M>(item_ptr, drop_job_queue);
2681    // SAFETY: do_advance_strong always returns a valid pointer
2682    let item: &ItemHolder<T, M> = unsafe { &*from_dummy(item_ptr) };
2683
2684    let prior_strong = item.strong_count.fetch_sub(1, Ordering::SeqCst); //atomic drop dec strong_count
2685    debug_println!(
2686        "drop strong of {:x?}, prev count: {}, now {}",
2687        item_ptr,
2688        prior_strong,
2689        prior_strong - 1,
2690    );
2691    if prior_strong == 1 {
2692        // This is the only case where we actually might need to drop the rightmost node's payload
2693        // (if all nodes have only weak references)
2694        do_drop_weak::<T, M>(item_ptr, drop_job_queue);
2695    }
2696}
2697
2698impl<T: ?Sized> Drop for ArcShift<T> {
2699    fn drop(&mut self) {
2700        verify_item(self.item.as_ptr());
2701        debug_println!("executing ArcShift::drop({:x?})", self.item.as_ptr());
2702        with_holder!(self.item, T, item, {
2703            let mut jobq = DropHandler::default();
2704            do_drop_strong(item, &mut jobq);
2705            jobq.resume_any_panics();
2706        })
2707    }
2708}
2709impl<T: ?Sized> Drop for ArcShiftWeak<T> {
2710    fn drop(&mut self) {
2711        verify_item(self.item.as_ptr());
2712
2713        fn drop_weak_helper<T: ?Sized, M: IMetadata>(item: *const ItemHolder<T, M>) {
2714            let mut jobq = DropHandler::default();
2715            do_drop_weak::<T, M>(to_dummy(item), &mut jobq);
2716            jobq.resume_any_panics();
2717        }
2718
2719        with_holder!(self.item, T, item, drop_weak_helper(item))
2720    }
2721}
2722
2723/// This is a marker for methods that have been removed in the
2724/// most recent version of ArcShift.
2725///
2726/// Any methods that take this type as parameters, is completely
2727/// impossible to call. This is by design. The methods have been
2728/// kept, to hopefully make migration easier.
2729pub struct NoLongerAvailableMarker {
2730    _priv: (),
2731}
2732
2733impl<T: ?Sized> ArcShiftWeak<T> {
2734    /// Upgrade this ArcShiftWeak instance to a full ArcShift.
2735    /// This is required to be able to access any stored value.
2736    /// If the ArcShift instance has no value (because the last ArcShift instance
2737    /// had been deallocated), this method returns None.
2738    pub fn upgrade(&self) -> Option<ArcShift<T>> {
2739        let t = with_holder!(self.item, T, item, {
2740            let mut drop_handler = DropHandler::default();
2741            let temp = do_upgrade_weak(item, &mut drop_handler);
2742            drop_handler.resume_any_panics();
2743            temp
2744        });
2745        Some(ArcShift {
2746            // SAFETY:
2747            // do_upgrade_weak returns a valid upgraded pointer
2748            item: unsafe { NonNull::new_unchecked(t? as *mut _) },
2749            pd: PhantomData,
2750        })
2751    }
2752}
2753impl<T> ArcShift<T> {
2754    /// Crate a new ArcShift instance with the given value.
2755    pub fn new(val: T) -> ArcShift<T> {
2756        let holder = make_sized_holder(val, null_mut());
2757        ArcShift {
2758            // SAFETY:
2759            // The newly created holder-pointer is valid and non-null
2760            item: unsafe { NonNull::new_unchecked(to_dummy(holder) as *mut _) },
2761            pd: PhantomData,
2762        }
2763    }
2764
2765    /// Drops this ArcShift instance. If this was the last instance of the entire chain,
2766    /// the payload value is returned.
2767    pub fn try_into_inner(self) -> Option<T> {
2768        let mut drop_handler =
2769            deferred_panics_helper::stealing_drop::StealingDropHandler::default();
2770        verify_item(self.item.as_ptr());
2771        debug_println!("executing ArcShift::into_inner({:x?})", self.item.as_ptr());
2772        do_drop_strong(
2773            from_dummy::<T, SizedMetadata>(self.item.as_ptr()),
2774            &mut drop_handler,
2775        );
2776        core::mem::forget(self);
2777        drop_handler.take_stolen()
2778    }
2779
2780    /// Update the value of this ArcShift instance (and all derived from it) to the given value.
2781    ///
2782    /// Note, other ArcShift instances will not see the new value until they call the
2783    /// [`ArcShift::get`] or [`ArcShift::reload`] methods.
2784    pub fn update(&mut self, val: T) {
2785        let holder = make_sized_holder(val, self.item.as_ptr() as *const ItemHolderDummy<T>);
2786
2787        with_holder!(self.item, T, item, {
2788            let mut jobq = DropHandler::default();
2789            // SAFETY:
2790            // * do_update returns non-null values.
2791            // * 'holder' is in fact a thin pointer, just what we need for T, since T is Sized.
2792            let new_item = unsafe {
2793                NonNull::new_unchecked(
2794                    do_update(item, |_| Some(holder as *const _), &mut jobq) as *mut _
2795                )
2796            };
2797            jobq.resume_any_panics();
2798            self.item = new_item;
2799        });
2800    }
2801    /// Atomically update the value.
2802    ///
2803    /// The supplied closure 'update' is called with the previous value as an argument.
2804    /// It then constructs a new, updated value. This value replaces the previous value
2805    /// of the ArcShift instance. Note, if other threads are updating the arcshift chain
2806    /// concurrently, it may take multiple retries for the update to succeed. The closure
2807    /// will be called once for every attempt, until an attempt is successful. This means that
2808    /// the final updated value will have always been calculated from the previous set value.
2809    pub fn rcu(&mut self, mut update: impl FnMut(&T) -> T) -> &T {
2810        self.rcu_maybe(|x| Some(update(x)));
2811        (*self).shared_get()
2812    }
2813
2814    /// Atomically update the value.
2815    ///
2816    /// The supplied closure 'update' is called with the previous value as an argument.
2817    /// It then constructs a new, updated value. This value replaces the previous value
2818    /// of the ArcShift instance. Note, if other threads are updating the arcshift chain
2819    /// concurrently, it may take multiple retries for the update to succeed. The closure
2820    /// will be called once for every attempt, until an attempt is successful. This means that
2821    /// the final updated value will have always been calculated from the previous set value.
2822    ///
2823    /// If the closure returns None, the update is cancelled, and this method returns false.
2824    pub fn rcu_maybe(&mut self, mut update: impl FnMut(&T) -> Option<T>) -> bool {
2825        let mut holder: Option<*const ItemHolderDummy<T>> = None;
2826
2827        let mut cancelled = false;
2828
2829        let mut jobq = DropHandler::default();
2830        // SAFETY:
2831        // do_update returns a valid non-null pointer
2832        let new_item_ptr = do_update(
2833            from_dummy::<T, SizedMetadata>(self.item.as_ptr()),
2834            |prev: &ItemHolder<T, SizedMetadata>| -> Option<*const ItemHolderDummy<T>> {
2835                // SAFETY:
2836                // we hold a strong ref on prev, so it cannot be dropped. Shared
2837                // access to 'payload' is thus sound.
2838                let prev_payload: &ManuallyDrop<T> = unsafe { &*prev.payload.get() };
2839                let prev_payload: &T = prev_payload;
2840                let new_candidate: Option<T> = update(prev_payload);
2841                let Some(new_candidate) = new_candidate else {
2842                    // Ok, the closure decided to NOT do an update after all
2843                    // We must now free any previous allocated candidate (both payload and holder).
2844                    if let Some(holder) = holder {
2845                        let mut jobq = DropHandler::default();
2846                        let full_ptr = from_dummy::<T, SizedMetadata>(holder);
2847                        raw_do_unconditional_drop_payload_if_not_dropped(
2848                            full_ptr as *mut ItemHolder<T, SizedMetadata>,
2849                            &mut jobq,
2850                        );
2851                        do_dealloc(full_ptr);
2852                        jobq.resume_any_panics();
2853                    }
2854                    cancelled = true;
2855                    return None;
2856                };
2857                if let Some(holder) = holder {
2858                    // SAFETY:
2859                    // If we get called when we already have a holder, then this is a retry
2860                    // and that holder was never visible to any other thread. We still have
2861                    // unique access to it.
2862                    let holder_mut: &mut ItemHolder<T, SizedMetadata> =
2863                        unsafe { &mut *(from_dummy::<T, SizedMetadata>(holder) as *mut _) };
2864                    // SAFETY:
2865                    // See above
2866                    unsafe {
2867                        ManuallyDrop::drop(&mut *holder_mut.payload.get());
2868                    }
2869                    holder_mut.payload = UnsafeCell::new(ManuallyDrop::new(new_candidate));
2870                    Some(holder)
2871                } else {
2872                    let new_holder = to_dummy(make_sized_holder(
2873                        new_candidate,
2874                        self.item.as_ptr() as *const ItemHolderDummy<T>,
2875                    ));
2876                    holder = Some(new_holder);
2877                    Some(new_holder)
2878                }
2879            },
2880            &mut jobq,
2881        );
2882        // SAFETY:
2883        // new_item_ptr returned by do_update is never null
2884        let new_unique_ptr = unsafe { NonNull::new_unchecked(new_item_ptr as *mut _) };
2885        jobq.resume_any_panics();
2886        self.item = new_unique_ptr;
2887        !cancelled
2888    }
2889}
2890
2891#[doc(hidden)]
2892#[deprecated = "ArcShiftLight has been removed. Please consider using ArcShiftWeak. It is similar, though not a direct replacement."]
2893pub struct ArcShiftLight {}
2894
2895impl<T: ?Sized> ArcShift<T> {
2896    #[doc(hidden)]
2897    #[cfg_attr(test, mutants::skip)]
2898    #[deprecated = "rcu_project was completely removed in ArcShift 0.2. Please use method 'rcu' instead, and just manually access the desired field."]
2899    pub fn rcu_project(&mut self, _marker: NoLongerAvailableMarker) {
2900        unreachable!("method cannot be called")
2901    }
2902    #[doc(hidden)]
2903    #[cfg_attr(test, mutants::skip)]
2904    #[deprecated = "rcu_maybe2 was completely removed in ArcShift 0.2. Please use 'rcu_maybe' instead. It has the same features."]
2905    pub fn rcu_maybe2(&mut self, _marker: NoLongerAvailableMarker) {
2906        unreachable!("method cannot be called")
2907    }
2908
2909    #[doc(hidden)]
2910    #[cfg_attr(test, mutants::skip)]
2911    #[deprecated = "update_shared_box was completely removed in ArcShift 0.2. Shared references can no longer be updated. Please file an issue if this is a blocker!"]
2912    pub fn update_shared_box(&mut self, _marker: NoLongerAvailableMarker) {
2913        unreachable!("method cannot be called")
2914    }
2915    #[doc(hidden)]
2916    #[cfg_attr(test, mutants::skip)]
2917    #[deprecated = "update_shared was completely removed in ArcShift 0.2. Shared references can no longer be updated. Please file an issue if this is a blocker!"]
2918    pub fn update_shared(&mut self, _marker: NoLongerAvailableMarker) {
2919        unreachable!("method cannot be called")
2920    }
2921    #[doc(hidden)]
2922    #[cfg_attr(test, mutants::skip)]
2923    #[deprecated = "make_light was completely removed in ArcShift 0.2. Please use ArcShift::downgrade(&item) instead."]
2924    pub fn make_light(&mut self, _marker: NoLongerAvailableMarker) {
2925        unreachable!("method cannot be called")
2926    }
2927    #[doc(hidden)]
2928    #[cfg_attr(test, mutants::skip)]
2929    #[deprecated = "shared_non_reloading_get now does the same thing as 'shared_get', please use the latter instead."]
2930    pub fn shared_non_reloading_get(&self) -> &T {
2931        self.shared_get()
2932    }
2933
2934    /// Basically the same as doing [`ArcShift::new`], but avoids copying the contents of 'input'
2935    /// to the stack, even as a temporary variable. This can be useful, if the type is too large
2936    /// to fit on the stack.
2937    pub fn from_box(input: Box<T>) -> ArcShift<T> {
2938        let holder = make_sized_or_unsized_holder_from_box(input, null_mut());
2939        ArcShift {
2940            // SAFETY:
2941            // from_box_impl never creates a null-pointer from a Box.
2942            item: unsafe { NonNull::new_unchecked(holder as *mut _) },
2943            pd: PhantomData,
2944        }
2945    }
2946
2947    /// Returns a mutable reference to the inner value.
2948    ///
2949    /// This method returns None if there are any other ArcShift or ArcShiftWeak instances
2950    /// pointing to the same object chain.
2951    pub fn try_get_mut(&mut self) -> Option<&mut T> {
2952        self.reload();
2953        with_holder!(self.item, T, item_ptr, {
2954            // SAFETY:
2955            // self.item is always a valid pointer for shared access
2956            let item = unsafe { &*item_ptr };
2957            let weak_count = item.weak_count.load(Ordering::SeqCst); //atomic try_get_mut check weak_count
2958            if get_weak_count(weak_count) == 1
2959                && !get_weak_prev(weak_count)
2960                // There can't be a 'next', since if so we wouldn't have a weak count of 1
2961                && item.strong_count.load(Ordering::SeqCst) == 1
2962            //atomic try_get_mut check strong count
2963            {
2964                // Yes, we need to check this again, see comment further down.
2965                let weak_count = item.weak_count.load(Ordering::SeqCst); //atomic try_get_mut double check weak_count
2966                if get_weak_count(weak_count) == 1 {
2967                    // SAFETY:
2968                    // The above constraints actually guarantee there can be no concurrent access.
2969                    //
2970                    // If we can prove that no such thread existed at time of 'weak_count.load' above,
2971                    // no such thread can later appear, since we hold '&mut self' to the only
2972                    // ArcShift referencing the chain. I.e, if we can prove this, we're done.
2973                    // No other weak-ref can exist, since we've checked that weak count is 1.
2974                    //
2975                    // Since the weak ref flags say there's no next and no prev, the only possible other
2976                    // ref that could exist at 'weak_count.load'-time would be a strong ref.
2977                    //
2978                    // We therefore check the strong count. If it is 1, there's only three possible cases:
2979                    // 1: We truly are the only remaining ref
2980                    // 2: There was one, and it has since gone away
2981                    // 3: There was one, and it has updated the chain and added a new value.
2982                    // 4: There was one, and it has downgraded to a weak ref.
2983                    //
2984                    // Cases 1 and 2 are benign. We guard against case 3 by loading 'weak_count'
2985                    // again. If it still shows there's no 'next', then case 3 is off the table.
2986                    // If the count is also still 1, option 4 is off the table. Meaning, we truly
2987                    // are alone.
2988                    let temp: &mut ManuallyDrop<T> = unsafe { &mut *item.payload.get() };
2989                    Some(&mut **temp)
2990                } else {
2991                    None
2992                }
2993            } else {
2994                None
2995            }
2996        })
2997    }
2998
2999    /// See [`ArcShift::update`] .
3000    ///
3001    /// This method allows converting from [`Box<T>`]. This can be useful since it means it's
3002    /// possible to use unsized types, such as [`str`] or [`[u8]`].
3003    pub fn update_box(&mut self, new_payload: Box<T>) {
3004        let holder = make_sized_or_unsized_holder_from_box(new_payload, self.item.as_ptr());
3005
3006        with_holder!(self.item, T, item, {
3007            let mut jobq = DropHandler::default();
3008            // SAFETY:
3009            // do_update returns a valid non-null pointer
3010            let new_item = unsafe {
3011                NonNull::new_unchecked(do_update(item, |_| Some(holder), &mut jobq) as *mut _)
3012            };
3013            jobq.resume_any_panics();
3014            self.item = new_item;
3015        });
3016    }
3017
3018    /// Reload this ArcShift instance, and return the latest value.
3019    #[inline(always)]
3020    pub fn get(&mut self) -> &T {
3021        if is_sized::<T>() {
3022            let ptr = from_dummy::<T, SizedMetadata>(self.item.as_ptr());
3023            // SAFETY:
3024            // self.item is always a valid pointer
3025            let item = unsafe { &*ptr };
3026            let next = item.next.load(Ordering::Relaxed);
3027            if next.is_null() {
3028                // SAFETY:
3029                // self.item is always a valid pointer
3030                return unsafe { item.payload() };
3031            }
3032            Self::advance_strong_helper2::<SizedMetadata>(&mut self.item)
3033        } else {
3034            let ptr = from_dummy::<T, UnsizedMetadata<T>>(self.item.as_ptr());
3035            // SAFETY:
3036            // self.item is always a valid pointer
3037            let item = unsafe { &*ptr };
3038            let next = item.next.load(Ordering::Relaxed);
3039            if next.is_null() {
3040                // SAFETY:
3041                // self.item is always a valid pointer
3042                return unsafe { item.payload() };
3043            }
3044            Self::advance_strong_helper2::<UnsizedMetadata<T>>(&mut self.item)
3045        }
3046    }
3047
3048    /// Get the current value of this ArcShift instance.
3049    ///
3050    /// WARNING! This does not reload the pointer. Use [`ArcShift::reload()`] to reload
3051    /// the value, or [`ArcShift::get()`] to always get the newest value.
3052    ///
3053    /// This method has the advantage that it doesn't require `&mut self` access.
3054    #[inline(always)]
3055    pub fn shared_get(&self) -> &T {
3056        with_holder!(self.item, T, item, {
3057            // SAFETY:
3058            // ArcShift has a strong ref, so payload must not have been dropped.
3059            unsafe { (*item).payload() }
3060        })
3061    }
3062
3063    /// Create an [`ArcShiftWeak<T>`] instance.
3064    ///
3065    /// Weak pointers do not prevent the inner from being dropped.
3066    ///
3067    /// The returned pointer can later be upgraded back to a regular ArcShift instance, if
3068    /// there is at least one remaining strong reference (i.e, [`ArcShift<T>`] instance).
3069    #[must_use = "this returns a new `ArcShiftWeak` pointer, \
3070                  without modifying the original `ArcShift`"]
3071    pub fn downgrade(this: &ArcShift<T>) -> ArcShiftWeak<T> {
3072        let t = with_holder!(this.item, T, item, do_clone_weak(item));
3073        ArcShiftWeak {
3074            // SAFETY:
3075            // do_clone_weak returns a valid, non-null pointer
3076            item: unsafe { NonNull::new_unchecked(t as *mut _) },
3077        }
3078    }
3079
3080    /// Note, if there is at least one strong count, these collectively hold a weak count.
3081    #[allow(unused)]
3082    pub(crate) fn weak_count(&self) -> usize {
3083        with_holder!(self.item, T, item, {
3084            // SAFETY:
3085            // self.item is a valid pointer
3086            unsafe { get_weak_count((*item).weak_count.load(Ordering::SeqCst)) }
3087        })
3088    }
3089    #[allow(unused)]
3090    pub(crate) fn strong_count(&self) -> usize {
3091        with_holder!(self.item, T, item, {
3092            // SAFETY:
3093            // self.item is a valid pointer
3094            unsafe { (*item).strong_count.load(Ordering::SeqCst) }
3095        })
3096    }
3097    #[inline(never)]
3098    #[cold]
3099    fn advance_strong_helper2<M: IMetadata>(old_item_ptr: &mut NonNull<ItemHolderDummy<T>>) -> &T {
3100        let mut jobq = DropHandler::default();
3101        let mut item_ptr = old_item_ptr.as_ptr() as *const _;
3102        // Lock free. Only loops if disturb-flag was set, meaning other thread
3103        // has offloaded work on us, and it has made progress.
3104        loop {
3105            item_ptr = do_advance_strong::<T, M>(item_ptr, &mut jobq);
3106            let (need_rerun, _strong_refs) =
3107                do_janitor_task(from_dummy::<T, M>(item_ptr), &mut jobq);
3108            if need_rerun {
3109                debug_println!("Janitor {:?} was disturbed. Need rerun", item_ptr);
3110                continue;
3111            }
3112            jobq.resume_any_panics();
3113            // SAFETY:
3114            // pointer returned by do_advance_strong is always a valid pointer
3115            *old_item_ptr = unsafe { NonNull::new_unchecked(item_ptr as *mut _) };
3116            // SAFETY:
3117            // pointer returned by do_advance_strong is always a valid pointer
3118            let item = unsafe { &*from_dummy::<T, M>(item_ptr) };
3119            // SAFETY:
3120            // pointer returned by do_advance_strong is always a valid pointer
3121            return unsafe { item.payload() };
3122        }
3123    }
3124
3125    /// Reload this instance, making it point to the most recent value.
3126    #[inline(always)]
3127    pub fn reload(&mut self) {
3128        if is_sized::<T>() {
3129            let ptr = from_dummy::<T, SizedMetadata>(self.item.as_ptr());
3130            // SAFETY:
3131            // self.item is always a valid pointer
3132            let item = unsafe { &*ptr };
3133            let next = item.next.load(Ordering::Relaxed);
3134            if next.is_null() {
3135                return;
3136            }
3137            Self::advance_strong_helper2::<SizedMetadata>(&mut self.item);
3138        } else {
3139            let ptr = from_dummy::<T, UnsizedMetadata<T>>(self.item.as_ptr());
3140            // SAFETY:
3141            // self.item is always a valid pointer
3142            let item = unsafe { &*ptr };
3143            let next = item.next.load(Ordering::Relaxed);
3144            if next.is_null() {
3145                return;
3146            }
3147            Self::advance_strong_helper2::<UnsizedMetadata<T>>(&mut self.item);
3148        }
3149    }
3150
3151    /// Check all links and refcounts.
3152    ///
3153    /// # SAFETY
3154    /// This method requires that no other threads access the chain while it is running.
3155    /// It is up to the caller to actually ensure this.
3156    #[allow(unused)]
3157    #[cfg(test)]
3158    #[cfg(feature = "std")]
3159    pub(crate) unsafe fn debug_validate(
3160        strong_handles: &[&Self],
3161        weak_handles: &[&ArcShiftWeak<T>],
3162    ) {
3163        let first = if !strong_handles.is_empty() {
3164            &strong_handles[0].item
3165        } else {
3166            &weak_handles[0].item
3167        };
3168        with_holder!(first, T, item, {
3169            Self::debug_validate_impl(strong_handles, weak_handles, item);
3170        });
3171    }
3172    #[allow(unused)]
3173    #[cfg(test)]
3174    #[cfg(feature = "std")]
3175    fn debug_validate_impl<M: IMetadata>(
3176        strong_handles: &[&ArcShift<T>],
3177        weak_handles: &[&ArcShiftWeak<T>],
3178        prototype: *const ItemHolder<T, M>,
3179    ) {
3180        let mut last = prototype;
3181
3182        debug_println!("Start traverse right at {:?}", last);
3183        // Lock free - this is a debug method not used in production.
3184        loop {
3185            debug_println!("loop traverse right at {:?}", last);
3186            // SAFETY:
3187            // Caller guarantees that initial 'last' prototype is a valid pointer.
3188            // Other pointers are found by walking right from that.
3189            // Caller guarantees there are no concurrent updates.
3190            let next = unsafe { undecorate((*last).next.load(Ordering::SeqCst)) };
3191            debug_println!("Traversed to {:?}", next);
3192            if next.is_null() {
3193                break;
3194            }
3195            last = from_dummy::<T, M>(next);
3196        }
3197
3198        let mut true_weak_refs =
3199            std::collections::HashMap::<*const ItemHolderDummy<T>, usize>::new();
3200        let mut true_strong_refs =
3201            std::collections::HashMap::<*const ItemHolderDummy<T>, usize>::new();
3202        // SAFETY:
3203        // the loop above has yielded a valid last ptr
3204        let all_nodes = unsafe { (*last).debug_all_to_left() };
3205
3206        let strong_refs_exist = all_nodes
3207            .iter()
3208            .any(|x| x.strong_count.load(Ordering::SeqCst) > 0);
3209
3210        if strong_refs_exist {
3211            debug_println!("Reading {:?}.next", to_dummy(last));
3212            // SAFETY:
3213            // the loop above has yielded a valid last ptr
3214            let last_next = unsafe { (*last).next.load(Ordering::SeqCst) };
3215            debug_println!("Reading {:?}.next gave {:?}", to_dummy(last), last_next);
3216            assert!(!get_decoration(last_next).is_dropped(), "the rightmost node must never be dropped (at least at rest, but regardless of refcount)");
3217        }
3218
3219        for _node in all_nodes.iter() {
3220            debug_println!("Node: {:?}", *_node as *const ItemHolder<T, _>);
3221        }
3222        for node in all_nodes.iter().copied() {
3223            let next = undecorate(node.next.load(Ordering::SeqCst));
3224            if !next.is_null() {
3225                // SAFETY:
3226                // next pointer is valid
3227                assert!(all_nodes.contains(unsafe { &&*from_dummy::<T, M>(next) }));
3228            }
3229            let prev: *const _ = node.prev.load(Ordering::SeqCst);
3230            if !prev.is_null() {
3231                *true_weak_refs.entry(prev).or_default() += 1;
3232                // SAFETY:
3233                // prev pointer is valid
3234                assert!(all_nodes.contains(unsafe { &&*from_dummy::<T, M>(prev) }));
3235            }
3236            let advance_count = node.advance_count.load(Ordering::SeqCst);
3237            assert_eq!(advance_count, 0, "advance_count must always be 0 at rest");
3238        }
3239
3240        for handle in weak_handles.iter() {
3241            // SAFETY:
3242            // All ArcShiftWeak instances always have valid, non-null pointers
3243            assert!(all_nodes.contains(unsafe { &&*from_dummy::<T, M>(handle.item.as_ptr()) }));
3244            let true_weak_count = true_weak_refs.entry(handle.item.as_ptr()).or_default();
3245            *true_weak_count += 1;
3246        }
3247        for handle in strong_handles.iter() {
3248            // SAFETY:
3249            // All ArcShift instances always have valid, non-null pointers
3250            assert!(all_nodes.contains(unsafe { &&*from_dummy::<T, M>(handle.item.as_ptr()) }));
3251            // SAFETY:
3252            // All ArcShift instances always have valid, non-null pointers
3253            let handle_next: *const _ = unsafe {
3254                (*from_dummy::<T, M>(handle.item.as_ptr()))
3255                    .next
3256                    .load(Ordering::SeqCst)
3257            };
3258            assert!(
3259                !get_decoration(handle_next).is_dropped(),
3260                "nodes referenced by strong handles must not be dropped, but {:?} was",
3261                handle.item.as_ptr()
3262            );
3263
3264            let true_strong_count = true_strong_refs.entry(handle.item.as_ptr()).or_default();
3265            if *true_strong_count == 0 {
3266                *true_weak_refs.entry(handle.item.as_ptr()).or_default() += 1;
3267            }
3268            *true_strong_count += 1;
3269        }
3270        for node in all_nodes.iter().copied() {
3271            let node_dummy = to_dummy(node);
3272            let strong_count = node.strong_count.load(Ordering::SeqCst);
3273            let weak_count = get_weak_count(node.weak_count.load(Ordering::SeqCst));
3274            let expected_strong_count = true_strong_refs.get(&node_dummy).unwrap_or(&0);
3275            let expected_weak_count = true_weak_refs.get(&node_dummy).unwrap_or(&0);
3276            assert_eq!(
3277                strong_count, *expected_strong_count,
3278                "strong count of {:x?} should be {}",
3279                node as *const _, *expected_strong_count
3280            );
3281            assert_eq!(
3282                weak_count, *expected_weak_count,
3283                "weak count of {:x?} should be {}",
3284                node as *const _, *expected_weak_count
3285            );
3286
3287            let next = node.next.load(Ordering::SeqCst);
3288            if strong_count > 0 {
3289                assert!(
3290                    !get_decoration(next).is_dropped(),
3291                    "as strong count is >0, node {:x?} should not be dropped",
3292                    node as *const _
3293                );
3294            }
3295        }
3296    }
3297}
3298
3299#[cfg(test)]
3300#[cfg(not(any(loom, feature = "shuttle")))]
3301pub(crate) mod no_std_tests;
3302
3303// Module for tests
3304#[cfg(all(test, feature = "std"))]
3305pub(crate) mod tests;