crossbeam_epoch/atomic.rs
1use alloc::boxed::Box;
2use core::alloc::Layout;
3use core::borrow::{Borrow, BorrowMut};
4use core::cmp;
5use core::fmt;
6use core::marker::PhantomData;
7use core::mem::{self, MaybeUninit};
8use core::ops::{Deref, DerefMut};
9use core::ptr;
10use core::slice;
11
12use crate::guard::Guard;
13use crate::primitive::sync::atomic::{AtomicUsize, Ordering};
14use crossbeam_utils::atomic::AtomicConsume;
15
16/// Given ordering for the success case in a compare-exchange operation, returns the strongest
17/// appropriate ordering for the failure case.
18#[inline]
19fn strongest_failure_ordering(ord: Ordering) -> Ordering {
20 use self::Ordering::*;
21 match ord {
22 Relaxed | Release => Relaxed,
23 Acquire | AcqRel => Acquire,
24 _ => SeqCst,
25 }
26}
27
28/// The error returned on failed compare-and-set operation.
29// TODO: remove in the next major version.
30#[deprecated(note = "Use `CompareExchangeError` instead")]
31pub type CompareAndSetError<'g, T, P> = CompareExchangeError<'g, T, P>;
32
33/// The error returned on failed compare-and-swap operation.
34pub struct CompareExchangeError<'g, T: ?Sized + Pointable, P: Pointer<T>> {
35 /// The value in the atomic pointer at the time of the failed operation.
36 pub current: Shared<'g, T>,
37
38 /// The new value, which the operation failed to store.
39 pub new: P,
40}
41
42impl<T, P: Pointer<T> + fmt::Debug> fmt::Debug for CompareExchangeError<'_, T, P> {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 f.debug_struct("CompareExchangeError")
45 .field("current", &self.current)
46 .field("new", &self.new)
47 .finish()
48 }
49}
50
51/// Memory orderings for compare-and-set operations.
52///
53/// A compare-and-set operation can have different memory orderings depending on whether it
54/// succeeds or fails. This trait generalizes different ways of specifying memory orderings.
55///
56/// The two ways of specifying orderings for compare-and-set are:
57///
58/// 1. Just one `Ordering` for the success case. In case of failure, the strongest appropriate
59/// ordering is chosen.
60/// 2. A pair of `Ordering`s. The first one is for the success case, while the second one is
61/// for the failure case.
62// TODO: remove in the next major version.
63#[deprecated(
64 note = "`compare_and_set` and `compare_and_set_weak` that use this trait are deprecated, \
65 use `compare_exchange` or `compare_exchange_weak instead`"
66)]
67pub trait CompareAndSetOrdering {
68 /// The ordering of the operation when it succeeds.
69 fn success(&self) -> Ordering;
70
71 /// The ordering of the operation when it fails.
72 ///
73 /// The failure ordering can't be `Release` or `AcqRel` and must be equivalent or weaker than
74 /// the success ordering.
75 fn failure(&self) -> Ordering;
76}
77
78#[allow(deprecated)]
79impl CompareAndSetOrdering for Ordering {
80 #[inline]
81 fn success(&self) -> Ordering {
82 *self
83 }
84
85 #[inline]
86 fn failure(&self) -> Ordering {
87 strongest_failure_ordering(*self)
88 }
89}
90
91#[allow(deprecated)]
92impl CompareAndSetOrdering for (Ordering, Ordering) {
93 #[inline]
94 fn success(&self) -> Ordering {
95 self.0
96 }
97
98 #[inline]
99 fn failure(&self) -> Ordering {
100 self.1
101 }
102}
103
104/// Returns a bitmask containing the unused least significant bits of an aligned pointer to `T`.
105#[inline]
106fn low_bits<T: ?Sized + Pointable>() -> usize {
107 (1 << T::ALIGN.trailing_zeros()) - 1
108}
109
110/// Panics if the pointer is not properly unaligned.
111#[inline]
112fn ensure_aligned<T: ?Sized + Pointable>(raw: usize) {
113 assert_eq!(raw & low_bits::<T>(), 0, "unaligned pointer");
114}
115
116/// Given a tagged pointer `data`, returns the same pointer, but tagged with `tag`.
117///
118/// `tag` is truncated to fit into the unused bits of the pointer to `T`.
119#[inline]
120fn compose_tag<T: ?Sized + Pointable>(data: usize, tag: usize) -> usize {
121 (data & !low_bits::<T>()) | (tag & low_bits::<T>())
122}
123
124/// Decomposes a tagged pointer `data` into the pointer and the tag.
125#[inline]
126fn decompose_tag<T: ?Sized + Pointable>(data: usize) -> (usize, usize) {
127 (data & !low_bits::<T>(), data & low_bits::<T>())
128}
129
130/// Types that are pointed to by a single word.
131///
132/// In concurrent programming, it is necessary to represent an object within a word because atomic
133/// operations (e.g., reads, writes, read-modify-writes) support only single words. This trait
134/// qualifies such types that are pointed to by a single word.
135///
136/// The trait generalizes `Box<T>` for a sized type `T`. In a box, an object of type `T` is
137/// allocated in heap and it is owned by a single-word pointer. This trait is also implemented for
138/// `[MaybeUninit<T>]` by storing its size along with its elements and pointing to the pair of array
139/// size and elements.
140///
141/// Pointers to `Pointable` types can be stored in [`Atomic`], [`Owned`], and [`Shared`]. In
142/// particular, Crossbeam supports dynamically sized slices as follows.
143///
144/// ```
145/// use std::mem::MaybeUninit;
146/// use crossbeam_epoch::Owned;
147///
148/// let o = Owned::<[MaybeUninit<i32>]>::init(10); // allocating [i32; 10]
149/// ```
150pub trait Pointable {
151 /// The alignment of pointer.
152 const ALIGN: usize;
153
154 /// The type for initializers.
155 type Init;
156
157 /// Initializes a with the given initializer.
158 ///
159 /// # Safety
160 ///
161 /// The result should be a multiple of `ALIGN`.
162 unsafe fn init(init: Self::Init) -> usize;
163
164 /// Dereferences the given pointer.
165 ///
166 /// # Safety
167 ///
168 /// - The given `ptr` should have been initialized with [`Pointable::init`].
169 /// - `ptr` should not have yet been dropped by [`Pointable::drop`].
170 /// - `ptr` should not be mutably dereferenced by [`Pointable::deref_mut`] concurrently.
171 unsafe fn deref<'a>(ptr: usize) -> &'a Self;
172
173 /// Mutably dereferences the given pointer.
174 ///
175 /// # Safety
176 ///
177 /// - The given `ptr` should have been initialized with [`Pointable::init`].
178 /// - `ptr` should not have yet been dropped by [`Pointable::drop`].
179 /// - `ptr` should not be dereferenced by [`Pointable::deref`] or [`Pointable::deref_mut`]
180 /// concurrently.
181 unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut Self;
182
183 /// Drops the object pointed to by the given pointer.
184 ///
185 /// # Safety
186 ///
187 /// - The given `ptr` should have been initialized with [`Pointable::init`].
188 /// - `ptr` should not have yet been dropped by [`Pointable::drop`].
189 /// - `ptr` should not be dereferenced by [`Pointable::deref`] or [`Pointable::deref_mut`]
190 /// concurrently.
191 unsafe fn drop(ptr: usize);
192}
193
194impl<T> Pointable for T {
195 const ALIGN: usize = mem::align_of::<T>();
196
197 type Init = T;
198
199 unsafe fn init(init: Self::Init) -> usize {
200 Box::into_raw(Box::new(init)) as usize
201 }
202
203 unsafe fn deref<'a>(ptr: usize) -> &'a Self {
204 &*(ptr as *const T)
205 }
206
207 unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut Self {
208 &mut *(ptr as *mut T)
209 }
210
211 unsafe fn drop(ptr: usize) {
212 drop(Box::from_raw(ptr as *mut T));
213 }
214}
215
216/// Array with size.
217///
218/// # Memory layout
219///
220/// An array consisting of size and elements:
221///
222/// ```text
223/// elements
224/// |
225/// |
226/// ------------------------------------
227/// | size | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
228/// ------------------------------------
229/// ```
230///
231/// Its memory layout is different from that of `Box<[T]>` in that size is in the allocation (not
232/// along with pointer as in `Box<[T]>`).
233///
234/// Elements are not present in the type, but they will be in the allocation.
235#[repr(C)]
236struct Array<T> {
237 /// The number of elements (not the number of bytes).
238 len: usize,
239 elements: [MaybeUninit<T>; 0],
240}
241
242impl<T> Array<T> {
243 fn layout(len: usize) -> Layout {
244 Layout::new::<Self>()
245 .extend(Layout::array::<MaybeUninit<T>>(len).unwrap())
246 .unwrap()
247 .0
248 .pad_to_align()
249 }
250}
251
252impl<T> Pointable for [MaybeUninit<T>] {
253 const ALIGN: usize = mem::align_of::<Array<T>>();
254
255 type Init = usize;
256
257 unsafe fn init(len: Self::Init) -> usize {
258 let layout = Array::<T>::layout(len);
259 let ptr = alloc::alloc::alloc(layout).cast::<Array<T>>();
260 if ptr.is_null() {
261 alloc::alloc::handle_alloc_error(layout);
262 }
263 ptr::addr_of_mut!((*ptr).len).write(len);
264 ptr as usize
265 }
266
267 unsafe fn deref<'a>(ptr: usize) -> &'a Self {
268 let array = &*(ptr as *const Array<T>);
269 slice::from_raw_parts(array.elements.as_ptr() as *const _, array.len)
270 }
271
272 unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut Self {
273 let array = &*(ptr as *mut Array<T>);
274 slice::from_raw_parts_mut(array.elements.as_ptr() as *mut _, array.len)
275 }
276
277 unsafe fn drop(ptr: usize) {
278 let len = (*(ptr as *mut Array<T>)).len;
279 let layout = Array::<T>::layout(len);
280 alloc::alloc::dealloc(ptr as *mut u8, layout);
281 }
282}
283
284/// An atomic pointer that can be safely shared between threads.
285///
286/// The pointer must be properly aligned. Since it is aligned, a tag can be stored into the unused
287/// least significant bits of the address. For example, the tag for a pointer to a sized type `T`
288/// should be less than `(1 << mem::align_of::<T>().trailing_zeros())`.
289///
290/// Any method that loads the pointer must be passed a reference to a [`Guard`].
291///
292/// Crossbeam supports dynamically sized types. See [`Pointable`] for details.
293pub struct Atomic<T: ?Sized + Pointable> {
294 data: AtomicUsize,
295 _marker: PhantomData<*mut T>,
296}
297
298unsafe impl<T: ?Sized + Pointable + Send + Sync> Send for Atomic<T> {}
299unsafe impl<T: ?Sized + Pointable + Send + Sync> Sync for Atomic<T> {}
300
301impl<T> Atomic<T> {
302 /// Allocates `value` on the heap and returns a new atomic pointer pointing to it.
303 ///
304 /// # Examples
305 ///
306 /// ```
307 /// use crossbeam_epoch::Atomic;
308 ///
309 /// let a = Atomic::new(1234);
310 /// # unsafe { drop(a.into_owned()); } // avoid leak
311 /// ```
312 pub fn new(init: T) -> Atomic<T> {
313 Self::init(init)
314 }
315}
316
317impl<T: ?Sized + Pointable> Atomic<T> {
318 /// Allocates `value` on the heap and returns a new atomic pointer pointing to it.
319 ///
320 /// # Examples
321 ///
322 /// ```
323 /// use crossbeam_epoch::Atomic;
324 ///
325 /// let a = Atomic::<i32>::init(1234);
326 /// # unsafe { drop(a.into_owned()); } // avoid leak
327 /// ```
328 pub fn init(init: T::Init) -> Atomic<T> {
329 Self::from(Owned::init(init))
330 }
331
332 /// Returns a new atomic pointer pointing to the tagged pointer `data`.
333 fn from_usize(data: usize) -> Self {
334 Self {
335 data: AtomicUsize::new(data),
336 _marker: PhantomData,
337 }
338 }
339
340 /// Returns a new null atomic pointer.
341 ///
342 /// # Examples
343 ///
344 /// ```
345 /// use crossbeam_epoch::Atomic;
346 ///
347 /// let a = Atomic::<i32>::null();
348 /// ```
349 #[cfg(not(crossbeam_loom))]
350 pub const fn null() -> Atomic<T> {
351 Self {
352 data: AtomicUsize::new(0),
353 _marker: PhantomData,
354 }
355 }
356 /// Returns a new null atomic pointer.
357 #[cfg(crossbeam_loom)]
358 pub fn null() -> Atomic<T> {
359 Self {
360 data: AtomicUsize::new(0),
361 _marker: PhantomData,
362 }
363 }
364
365 /// Loads a `Shared` from the atomic pointer.
366 ///
367 /// This method takes an [`Ordering`] argument which describes the memory ordering of this
368 /// operation.
369 ///
370 /// # Examples
371 ///
372 /// ```
373 /// use crossbeam_epoch::{self as epoch, Atomic};
374 /// use std::sync::atomic::Ordering::SeqCst;
375 ///
376 /// let a = Atomic::new(1234);
377 /// let guard = &epoch::pin();
378 /// let p = a.load(SeqCst, guard);
379 /// # unsafe { drop(a.into_owned()); } // avoid leak
380 /// ```
381 pub fn load<'g>(&self, ord: Ordering, _: &'g Guard) -> Shared<'g, T> {
382 unsafe { Shared::from_usize(self.data.load(ord)) }
383 }
384
385 /// Loads a `Shared` from the atomic pointer using a "consume" memory ordering.
386 ///
387 /// This is similar to the "acquire" ordering, except that an ordering is
388 /// only guaranteed with operations that "depend on" the result of the load.
389 /// However consume loads are usually much faster than acquire loads on
390 /// architectures with a weak memory model since they don't require memory
391 /// fence instructions.
392 ///
393 /// The exact definition of "depend on" is a bit vague, but it works as you
394 /// would expect in practice since a lot of software, especially the Linux
395 /// kernel, rely on this behavior.
396 ///
397 /// # Examples
398 ///
399 /// ```
400 /// use crossbeam_epoch::{self as epoch, Atomic};
401 ///
402 /// let a = Atomic::new(1234);
403 /// let guard = &epoch::pin();
404 /// let p = a.load_consume(guard);
405 /// # unsafe { drop(a.into_owned()); } // avoid leak
406 /// ```
407 pub fn load_consume<'g>(&self, _: &'g Guard) -> Shared<'g, T> {
408 unsafe { Shared::from_usize(self.data.load_consume()) }
409 }
410
411 /// Stores a `Shared` or `Owned` pointer into the atomic pointer.
412 ///
413 /// This method takes an [`Ordering`] argument which describes the memory ordering of this
414 /// operation.
415 ///
416 /// # Examples
417 ///
418 /// ```
419 /// use crossbeam_epoch::{Atomic, Owned, Shared};
420 /// use std::sync::atomic::Ordering::SeqCst;
421 ///
422 /// let a = Atomic::new(1234);
423 /// # unsafe { drop(a.load(SeqCst, &crossbeam_epoch::pin()).into_owned()); } // avoid leak
424 /// a.store(Shared::null(), SeqCst);
425 /// a.store(Owned::new(1234), SeqCst);
426 /// # unsafe { drop(a.into_owned()); } // avoid leak
427 /// ```
428 pub fn store<P: Pointer<T>>(&self, new: P, ord: Ordering) {
429 self.data.store(new.into_usize(), ord);
430 }
431
432 /// Stores a `Shared` or `Owned` pointer into the atomic pointer, returning the previous
433 /// `Shared`.
434 ///
435 /// This method takes an [`Ordering`] argument which describes the memory ordering of this
436 /// operation.
437 ///
438 /// # Examples
439 ///
440 /// ```
441 /// use crossbeam_epoch::{self as epoch, Atomic, Shared};
442 /// use std::sync::atomic::Ordering::SeqCst;
443 ///
444 /// let a = Atomic::new(1234);
445 /// let guard = &epoch::pin();
446 /// let p = a.swap(Shared::null(), SeqCst, guard);
447 /// # unsafe { drop(p.into_owned()); } // avoid leak
448 /// ```
449 pub fn swap<'g, P: Pointer<T>>(&self, new: P, ord: Ordering, _: &'g Guard) -> Shared<'g, T> {
450 unsafe { Shared::from_usize(self.data.swap(new.into_usize(), ord)) }
451 }
452
453 /// Stores the pointer `new` (either `Shared` or `Owned`) into the atomic pointer if the current
454 /// value is the same as `current`. The tag is also taken into account, so two pointers to the
455 /// same object, but with different tags, will not be considered equal.
456 ///
457 /// The return value is a result indicating whether the new pointer was written. On success the
458 /// pointer that was written is returned. On failure the actual current value and `new` are
459 /// returned.
460 ///
461 /// This method takes two `Ordering` arguments to describe the memory
462 /// ordering of this operation. `success` describes the required ordering for the
463 /// read-modify-write operation that takes place if the comparison with `current` succeeds.
464 /// `failure` describes the required ordering for the load operation that takes place when
465 /// the comparison fails. Using `Acquire` as success ordering makes the store part
466 /// of this operation `Relaxed`, and using `Release` makes the successful load
467 /// `Relaxed`. The failure ordering can only be `SeqCst`, `Acquire` or `Relaxed`
468 /// and must be equivalent to or weaker than the success ordering.
469 ///
470 /// # Examples
471 ///
472 /// ```
473 /// use crossbeam_epoch::{self as epoch, Atomic, Owned, Shared};
474 /// use std::sync::atomic::Ordering::SeqCst;
475 ///
476 /// let a = Atomic::new(1234);
477 ///
478 /// let guard = &epoch::pin();
479 /// let curr = a.load(SeqCst, guard);
480 /// let res1 = a.compare_exchange(curr, Shared::null(), SeqCst, SeqCst, guard);
481 /// let res2 = a.compare_exchange(curr, Owned::new(5678), SeqCst, SeqCst, guard);
482 /// # unsafe { drop(curr.into_owned()); } // avoid leak
483 /// ```
484 pub fn compare_exchange<'g, P>(
485 &self,
486 current: Shared<'_, T>,
487 new: P,
488 success: Ordering,
489 failure: Ordering,
490 _: &'g Guard,
491 ) -> Result<Shared<'g, T>, CompareExchangeError<'g, T, P>>
492 where
493 P: Pointer<T>,
494 {
495 let new = new.into_usize();
496 self.data
497 .compare_exchange(current.into_usize(), new, success, failure)
498 .map(|_| unsafe { Shared::from_usize(new) })
499 .map_err(|current| unsafe {
500 CompareExchangeError {
501 current: Shared::from_usize(current),
502 new: P::from_usize(new),
503 }
504 })
505 }
506
507 /// Stores the pointer `new` (either `Shared` or `Owned`) into the atomic pointer if the current
508 /// value is the same as `current`. The tag is also taken into account, so two pointers to the
509 /// same object, but with different tags, will not be considered equal.
510 ///
511 /// Unlike [`compare_exchange`], this method is allowed to spuriously fail even when comparison
512 /// succeeds, which can result in more efficient code on some platforms. The return value is a
513 /// result indicating whether the new pointer was written. On success the pointer that was
514 /// written is returned. On failure the actual current value and `new` are returned.
515 ///
516 /// This method takes two `Ordering` arguments to describe the memory
517 /// ordering of this operation. `success` describes the required ordering for the
518 /// read-modify-write operation that takes place if the comparison with `current` succeeds.
519 /// `failure` describes the required ordering for the load operation that takes place when
520 /// the comparison fails. Using `Acquire` as success ordering makes the store part
521 /// of this operation `Relaxed`, and using `Release` makes the successful load
522 /// `Relaxed`. The failure ordering can only be `SeqCst`, `Acquire` or `Relaxed`
523 /// and must be equivalent to or weaker than the success ordering.
524 ///
525 /// [`compare_exchange`]: Atomic::compare_exchange
526 ///
527 /// # Examples
528 ///
529 /// ```
530 /// use crossbeam_epoch::{self as epoch, Atomic, Owned, Shared};
531 /// use std::sync::atomic::Ordering::SeqCst;
532 ///
533 /// let a = Atomic::new(1234);
534 /// let guard = &epoch::pin();
535 ///
536 /// let mut new = Owned::new(5678);
537 /// let mut ptr = a.load(SeqCst, guard);
538 /// # unsafe { drop(a.load(SeqCst, guard).into_owned()); } // avoid leak
539 /// loop {
540 /// match a.compare_exchange_weak(ptr, new, SeqCst, SeqCst, guard) {
541 /// Ok(p) => {
542 /// ptr = p;
543 /// break;
544 /// }
545 /// Err(err) => {
546 /// ptr = err.current;
547 /// new = err.new;
548 /// }
549 /// }
550 /// }
551 ///
552 /// let mut curr = a.load(SeqCst, guard);
553 /// loop {
554 /// match a.compare_exchange_weak(curr, Shared::null(), SeqCst, SeqCst, guard) {
555 /// Ok(_) => break,
556 /// Err(err) => curr = err.current,
557 /// }
558 /// }
559 /// # unsafe { drop(curr.into_owned()); } // avoid leak
560 /// ```
561 pub fn compare_exchange_weak<'g, P>(
562 &self,
563 current: Shared<'_, T>,
564 new: P,
565 success: Ordering,
566 failure: Ordering,
567 _: &'g Guard,
568 ) -> Result<Shared<'g, T>, CompareExchangeError<'g, T, P>>
569 where
570 P: Pointer<T>,
571 {
572 let new = new.into_usize();
573 self.data
574 .compare_exchange_weak(current.into_usize(), new, success, failure)
575 .map(|_| unsafe { Shared::from_usize(new) })
576 .map_err(|current| unsafe {
577 CompareExchangeError {
578 current: Shared::from_usize(current),
579 new: P::from_usize(new),
580 }
581 })
582 }
583
584 /// Fetches the pointer, and then applies a function to it that returns a new value.
585 /// Returns a `Result` of `Ok(previous_value)` if the function returned `Some`, else `Err(_)`.
586 ///
587 /// Note that the given function may be called multiple times if the value has been changed by
588 /// other threads in the meantime, as long as the function returns `Some(_)`, but the function
589 /// will have been applied only once to the stored value.
590 ///
591 /// `fetch_update` takes two [`Ordering`] arguments to describe the memory
592 /// ordering of this operation. The first describes the required ordering for
593 /// when the operation finally succeeds while the second describes the
594 /// required ordering for loads. These correspond to the success and failure
595 /// orderings of [`Atomic::compare_exchange`] respectively.
596 ///
597 /// Using [`Acquire`] as success ordering makes the store part of this
598 /// operation [`Relaxed`], and using [`Release`] makes the final successful
599 /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`],
600 /// [`Acquire`] or [`Relaxed`] and must be equivalent to or weaker than the
601 /// success ordering.
602 ///
603 /// [`Relaxed`]: Ordering::Relaxed
604 /// [`Acquire`]: Ordering::Acquire
605 /// [`Release`]: Ordering::Release
606 /// [`SeqCst`]: Ordering::SeqCst
607 ///
608 /// # Examples
609 ///
610 /// ```
611 /// use crossbeam_epoch::{self as epoch, Atomic};
612 /// use std::sync::atomic::Ordering::SeqCst;
613 ///
614 /// let a = Atomic::new(1234);
615 /// let guard = &epoch::pin();
616 ///
617 /// let res1 = a.fetch_update(SeqCst, SeqCst, guard, |x| Some(x.with_tag(1)));
618 /// assert!(res1.is_ok());
619 ///
620 /// let res2 = a.fetch_update(SeqCst, SeqCst, guard, |x| None);
621 /// assert!(res2.is_err());
622 /// # unsafe { drop(a.into_owned()); } // avoid leak
623 /// ```
624 pub fn fetch_update<'g, F>(
625 &self,
626 set_order: Ordering,
627 fail_order: Ordering,
628 guard: &'g Guard,
629 mut func: F,
630 ) -> Result<Shared<'g, T>, Shared<'g, T>>
631 where
632 F: FnMut(Shared<'g, T>) -> Option<Shared<'g, T>>,
633 {
634 let mut prev = self.load(fail_order, guard);
635 while let Some(next) = func(prev) {
636 match self.compare_exchange_weak(prev, next, set_order, fail_order, guard) {
637 Ok(_result) => return Ok(prev),
638 Err(next_prev) => prev = next_prev.current,
639 }
640 }
641 Err(prev)
642 }
643
644 /// Stores the pointer `new` (either `Shared` or `Owned`) into the atomic pointer if the current
645 /// value is the same as `current`. The tag is also taken into account, so two pointers to the
646 /// same object, but with different tags, will not be considered equal.
647 ///
648 /// The return value is a result indicating whether the new pointer was written. On success the
649 /// pointer that was written is returned. On failure the actual current value and `new` are
650 /// returned.
651 ///
652 /// This method takes a [`CompareAndSetOrdering`] argument which describes the memory
653 /// ordering of this operation.
654 ///
655 /// # Migrating to `compare_exchange`
656 ///
657 /// `compare_and_set` is equivalent to `compare_exchange` with the following mapping for
658 /// memory orderings:
659 ///
660 /// Original | Success | Failure
661 /// -------- | ------- | -------
662 /// Relaxed | Relaxed | Relaxed
663 /// Acquire | Acquire | Acquire
664 /// Release | Release | Relaxed
665 /// AcqRel | AcqRel | Acquire
666 /// SeqCst | SeqCst | SeqCst
667 ///
668 /// # Examples
669 ///
670 /// ```
671 /// # #![allow(deprecated)]
672 /// use crossbeam_epoch::{self as epoch, Atomic, Owned, Shared};
673 /// use std::sync::atomic::Ordering::SeqCst;
674 ///
675 /// let a = Atomic::new(1234);
676 ///
677 /// let guard = &epoch::pin();
678 /// let curr = a.load(SeqCst, guard);
679 /// let res1 = a.compare_and_set(curr, Shared::null(), SeqCst, guard);
680 /// let res2 = a.compare_and_set(curr, Owned::new(5678), SeqCst, guard);
681 /// # unsafe { drop(curr.into_owned()); } // avoid leak
682 /// ```
683 // TODO: remove in the next major version.
684 #[allow(deprecated)]
685 #[deprecated(note = "Use `compare_exchange` instead")]
686 pub fn compare_and_set<'g, O, P>(
687 &self,
688 current: Shared<'_, T>,
689 new: P,
690 ord: O,
691 guard: &'g Guard,
692 ) -> Result<Shared<'g, T>, CompareAndSetError<'g, T, P>>
693 where
694 O: CompareAndSetOrdering,
695 P: Pointer<T>,
696 {
697 self.compare_exchange(current, new, ord.success(), ord.failure(), guard)
698 }
699
700 /// Stores the pointer `new` (either `Shared` or `Owned`) into the atomic pointer if the current
701 /// value is the same as `current`. The tag is also taken into account, so two pointers to the
702 /// same object, but with different tags, will not be considered equal.
703 ///
704 /// Unlike [`compare_and_set`], this method is allowed to spuriously fail even when comparison
705 /// succeeds, which can result in more efficient code on some platforms. The return value is a
706 /// result indicating whether the new pointer was written. On success the pointer that was
707 /// written is returned. On failure the actual current value and `new` are returned.
708 ///
709 /// This method takes a [`CompareAndSetOrdering`] argument which describes the memory
710 /// ordering of this operation.
711 ///
712 /// [`compare_and_set`]: Atomic::compare_and_set
713 ///
714 /// # Migrating to `compare_exchange_weak`
715 ///
716 /// `compare_and_set_weak` is equivalent to `compare_exchange_weak` with the following mapping for
717 /// memory orderings:
718 ///
719 /// Original | Success | Failure
720 /// -------- | ------- | -------
721 /// Relaxed | Relaxed | Relaxed
722 /// Acquire | Acquire | Acquire
723 /// Release | Release | Relaxed
724 /// AcqRel | AcqRel | Acquire
725 /// SeqCst | SeqCst | SeqCst
726 ///
727 /// # Examples
728 ///
729 /// ```
730 /// # #![allow(deprecated)]
731 /// use crossbeam_epoch::{self as epoch, Atomic, Owned, Shared};
732 /// use std::sync::atomic::Ordering::SeqCst;
733 ///
734 /// let a = Atomic::new(1234);
735 /// let guard = &epoch::pin();
736 ///
737 /// let mut new = Owned::new(5678);
738 /// let mut ptr = a.load(SeqCst, guard);
739 /// # unsafe { drop(a.load(SeqCst, guard).into_owned()); } // avoid leak
740 /// loop {
741 /// match a.compare_and_set_weak(ptr, new, SeqCst, guard) {
742 /// Ok(p) => {
743 /// ptr = p;
744 /// break;
745 /// }
746 /// Err(err) => {
747 /// ptr = err.current;
748 /// new = err.new;
749 /// }
750 /// }
751 /// }
752 ///
753 /// let mut curr = a.load(SeqCst, guard);
754 /// loop {
755 /// match a.compare_and_set_weak(curr, Shared::null(), SeqCst, guard) {
756 /// Ok(_) => break,
757 /// Err(err) => curr = err.current,
758 /// }
759 /// }
760 /// # unsafe { drop(curr.into_owned()); } // avoid leak
761 /// ```
762 // TODO: remove in the next major version.
763 #[allow(deprecated)]
764 #[deprecated(note = "Use `compare_exchange_weak` instead")]
765 pub fn compare_and_set_weak<'g, O, P>(
766 &self,
767 current: Shared<'_, T>,
768 new: P,
769 ord: O,
770 guard: &'g Guard,
771 ) -> Result<Shared<'g, T>, CompareAndSetError<'g, T, P>>
772 where
773 O: CompareAndSetOrdering,
774 P: Pointer<T>,
775 {
776 self.compare_exchange_weak(current, new, ord.success(), ord.failure(), guard)
777 }
778
779 /// Bitwise "and" with the current tag.
780 ///
781 /// Performs a bitwise "and" operation on the current tag and the argument `val`, and sets the
782 /// new tag to the result. Returns the previous pointer.
783 ///
784 /// This method takes an [`Ordering`] argument which describes the memory ordering of this
785 /// operation.
786 ///
787 /// # Examples
788 ///
789 /// ```
790 /// use crossbeam_epoch::{self as epoch, Atomic, Shared};
791 /// use std::sync::atomic::Ordering::SeqCst;
792 ///
793 /// let a = Atomic::<i32>::from(Shared::null().with_tag(3));
794 /// let guard = &epoch::pin();
795 /// assert_eq!(a.fetch_and(2, SeqCst, guard).tag(), 3);
796 /// assert_eq!(a.load(SeqCst, guard).tag(), 2);
797 /// ```
798 pub fn fetch_and<'g>(&self, val: usize, ord: Ordering, _: &'g Guard) -> Shared<'g, T> {
799 unsafe { Shared::from_usize(self.data.fetch_and(val | !low_bits::<T>(), ord)) }
800 }
801
802 /// Bitwise "or" with the current tag.
803 ///
804 /// Performs a bitwise "or" operation on the current tag and the argument `val`, and sets the
805 /// new tag to the result. Returns the previous pointer.
806 ///
807 /// This method takes an [`Ordering`] argument which describes the memory ordering of this
808 /// operation.
809 ///
810 /// # Examples
811 ///
812 /// ```
813 /// use crossbeam_epoch::{self as epoch, Atomic, Shared};
814 /// use std::sync::atomic::Ordering::SeqCst;
815 ///
816 /// let a = Atomic::<i32>::from(Shared::null().with_tag(1));
817 /// let guard = &epoch::pin();
818 /// assert_eq!(a.fetch_or(2, SeqCst, guard).tag(), 1);
819 /// assert_eq!(a.load(SeqCst, guard).tag(), 3);
820 /// ```
821 pub fn fetch_or<'g>(&self, val: usize, ord: Ordering, _: &'g Guard) -> Shared<'g, T> {
822 unsafe { Shared::from_usize(self.data.fetch_or(val & low_bits::<T>(), ord)) }
823 }
824
825 /// Bitwise "xor" with the current tag.
826 ///
827 /// Performs a bitwise "xor" operation on the current tag and the argument `val`, and sets the
828 /// new tag to the result. Returns the previous pointer.
829 ///
830 /// This method takes an [`Ordering`] argument which describes the memory ordering of this
831 /// operation.
832 ///
833 /// # Examples
834 ///
835 /// ```
836 /// use crossbeam_epoch::{self as epoch, Atomic, Shared};
837 /// use std::sync::atomic::Ordering::SeqCst;
838 ///
839 /// let a = Atomic::<i32>::from(Shared::null().with_tag(1));
840 /// let guard = &epoch::pin();
841 /// assert_eq!(a.fetch_xor(3, SeqCst, guard).tag(), 1);
842 /// assert_eq!(a.load(SeqCst, guard).tag(), 2);
843 /// ```
844 pub fn fetch_xor<'g>(&self, val: usize, ord: Ordering, _: &'g Guard) -> Shared<'g, T> {
845 unsafe { Shared::from_usize(self.data.fetch_xor(val & low_bits::<T>(), ord)) }
846 }
847
848 /// Takes ownership of the pointee.
849 ///
850 /// This consumes the atomic and converts it into [`Owned`]. As [`Atomic`] doesn't have a
851 /// destructor and doesn't drop the pointee while [`Owned`] does, this is suitable for
852 /// destructors of data structures.
853 ///
854 /// # Panics
855 ///
856 /// Panics if this pointer is null, but only in debug mode.
857 ///
858 /// # Safety
859 ///
860 /// This method may be called only if the pointer is valid and nobody else is holding a
861 /// reference to the same object.
862 ///
863 /// # Examples
864 ///
865 /// ```rust
866 /// # use std::mem;
867 /// # use crossbeam_epoch::Atomic;
868 /// struct DataStructure {
869 /// ptr: Atomic<usize>,
870 /// }
871 ///
872 /// impl Drop for DataStructure {
873 /// fn drop(&mut self) {
874 /// // By now the DataStructure lives only in our thread and we are sure we don't hold
875 /// // any Shared or & to it ourselves.
876 /// unsafe {
877 /// drop(mem::replace(&mut self.ptr, Atomic::null()).into_owned());
878 /// }
879 /// }
880 /// }
881 /// ```
882 pub unsafe fn into_owned(self) -> Owned<T> {
883 Owned::from_usize(self.data.into_inner())
884 }
885
886 /// Takes ownership of the pointee if it is non-null.
887 ///
888 /// This consumes the atomic and converts it into [`Owned`]. As [`Atomic`] doesn't have a
889 /// destructor and doesn't drop the pointee while [`Owned`] does, this is suitable for
890 /// destructors of data structures.
891 ///
892 /// # Safety
893 ///
894 /// This method may be called only if the pointer is valid and nobody else is holding a
895 /// reference to the same object, or the pointer is null.
896 ///
897 /// # Examples
898 ///
899 /// ```rust
900 /// # use std::mem;
901 /// # use crossbeam_epoch::Atomic;
902 /// struct DataStructure {
903 /// ptr: Atomic<usize>,
904 /// }
905 ///
906 /// impl Drop for DataStructure {
907 /// fn drop(&mut self) {
908 /// // By now the DataStructure lives only in our thread and we are sure we don't hold
909 /// // any Shared or & to it ourselves, but it may be null, so we have to be careful.
910 /// let old = mem::replace(&mut self.ptr, Atomic::null());
911 /// unsafe {
912 /// if let Some(x) = old.try_into_owned() {
913 /// drop(x)
914 /// }
915 /// }
916 /// }
917 /// }
918 /// ```
919 pub unsafe fn try_into_owned(self) -> Option<Owned<T>> {
920 let data = self.data.into_inner();
921 if decompose_tag::<T>(data).0 == 0 {
922 None
923 } else {
924 Some(Owned::from_usize(data))
925 }
926 }
927}
928
929impl<T: ?Sized + Pointable> fmt::Debug for Atomic<T> {
930 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
931 let data = self.data.load(Ordering::SeqCst);
932 let (raw, tag) = decompose_tag::<T>(data);
933
934 f.debug_struct("Atomic")
935 .field("raw", &raw)
936 .field("tag", &tag)
937 .finish()
938 }
939}
940
941impl<T: ?Sized + Pointable> fmt::Pointer for Atomic<T> {
942 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
943 let data = self.data.load(Ordering::SeqCst);
944 let (raw, _) = decompose_tag::<T>(data);
945 let ptr = if raw == 0 {
946 raw as *const ()
947 } else {
948 unsafe { T::deref(raw) as *const T as *const () }
949 };
950 fmt::Pointer::fmt(&ptr, f)
951 }
952}
953
954impl<T: ?Sized + Pointable> Clone for Atomic<T> {
955 /// Returns a copy of the atomic value.
956 ///
957 /// Note that a `Relaxed` load is used here. If you need synchronization, use it with other
958 /// atomics or fences.
959 fn clone(&self) -> Self {
960 let data = self.data.load(Ordering::Relaxed);
961 Atomic::from_usize(data)
962 }
963}
964
965impl<T: ?Sized + Pointable> Default for Atomic<T> {
966 fn default() -> Self {
967 Atomic::null()
968 }
969}
970
971impl<T: ?Sized + Pointable> From<Owned<T>> for Atomic<T> {
972 /// Returns a new atomic pointer pointing to `owned`.
973 ///
974 /// # Examples
975 ///
976 /// ```
977 /// use crossbeam_epoch::{Atomic, Owned};
978 ///
979 /// let a = Atomic::<i32>::from(Owned::new(1234));
980 /// # unsafe { drop(a.into_owned()); } // avoid leak
981 /// ```
982 fn from(owned: Owned<T>) -> Self {
983 let data = owned.data;
984 mem::forget(owned);
985 Self::from_usize(data)
986 }
987}
988
989impl<T> From<Box<T>> for Atomic<T> {
990 fn from(b: Box<T>) -> Self {
991 Self::from(Owned::from(b))
992 }
993}
994
995impl<T> From<T> for Atomic<T> {
996 fn from(t: T) -> Self {
997 Self::new(t)
998 }
999}
1000
1001impl<'g, T: ?Sized + Pointable> From<Shared<'g, T>> for Atomic<T> {
1002 /// Returns a new atomic pointer pointing to `ptr`.
1003 ///
1004 /// # Examples
1005 ///
1006 /// ```
1007 /// use crossbeam_epoch::{Atomic, Shared};
1008 ///
1009 /// let a = Atomic::<i32>::from(Shared::<i32>::null());
1010 /// ```
1011 fn from(ptr: Shared<'g, T>) -> Self {
1012 Self::from_usize(ptr.data)
1013 }
1014}
1015
1016impl<T> From<*const T> for Atomic<T> {
1017 /// Returns a new atomic pointer pointing to `raw`.
1018 ///
1019 /// # Examples
1020 ///
1021 /// ```
1022 /// use std::ptr;
1023 /// use crossbeam_epoch::Atomic;
1024 ///
1025 /// let a = Atomic::<i32>::from(ptr::null::<i32>());
1026 /// ```
1027 fn from(raw: *const T) -> Self {
1028 Self::from_usize(raw as usize)
1029 }
1030}
1031
1032/// A trait for either `Owned` or `Shared` pointers.
1033pub trait Pointer<T: ?Sized + Pointable> {
1034 /// Returns the machine representation of the pointer.
1035 fn into_usize(self) -> usize;
1036
1037 /// Returns a new pointer pointing to the tagged pointer `data`.
1038 ///
1039 /// # Safety
1040 ///
1041 /// The given `data` should have been created by `Pointer::into_usize()`, and one `data` should
1042 /// not be converted back by `Pointer::from_usize()` multiple times.
1043 unsafe fn from_usize(data: usize) -> Self;
1044}
1045
1046/// An owned heap-allocated object.
1047///
1048/// This type is very similar to `Box<T>`.
1049///
1050/// The pointer must be properly aligned. Since it is aligned, a tag can be stored into the unused
1051/// least significant bits of the address.
1052pub struct Owned<T: ?Sized + Pointable> {
1053 data: usize,
1054 _marker: PhantomData<Box<T>>,
1055}
1056
1057impl<T: ?Sized + Pointable> Pointer<T> for Owned<T> {
1058 #[inline]
1059 fn into_usize(self) -> usize {
1060 let data = self.data;
1061 mem::forget(self);
1062 data
1063 }
1064
1065 /// Returns a new pointer pointing to the tagged pointer `data`.
1066 ///
1067 /// # Panics
1068 ///
1069 /// Panics if the data is zero in debug mode.
1070 #[inline]
1071 unsafe fn from_usize(data: usize) -> Self {
1072 debug_assert!(data != 0, "converting zero into `Owned`");
1073 Owned {
1074 data,
1075 _marker: PhantomData,
1076 }
1077 }
1078}
1079
1080impl<T> Owned<T> {
1081 /// Returns a new owned pointer pointing to `raw`.
1082 ///
1083 /// This function is unsafe because improper use may lead to memory problems. Argument `raw`
1084 /// must be a valid pointer. Also, a double-free may occur if the function is called twice on
1085 /// the same raw pointer.
1086 ///
1087 /// # Panics
1088 ///
1089 /// Panics if `raw` is not properly aligned.
1090 ///
1091 /// # Safety
1092 ///
1093 /// The given `raw` should have been derived from `Owned`, and one `raw` should not be converted
1094 /// back by `Owned::from_raw()` multiple times.
1095 ///
1096 /// # Examples
1097 ///
1098 /// ```
1099 /// use crossbeam_epoch::Owned;
1100 ///
1101 /// let o = unsafe { Owned::from_raw(Box::into_raw(Box::new(1234))) };
1102 /// ```
1103 pub unsafe fn from_raw(raw: *mut T) -> Owned<T> {
1104 let raw = raw as usize;
1105 ensure_aligned::<T>(raw);
1106 Self::from_usize(raw)
1107 }
1108
1109 /// Converts the owned pointer into a `Box`.
1110 ///
1111 /// # Examples
1112 ///
1113 /// ```
1114 /// use crossbeam_epoch::Owned;
1115 ///
1116 /// let o = Owned::new(1234);
1117 /// let b: Box<i32> = o.into_box();
1118 /// assert_eq!(*b, 1234);
1119 /// ```
1120 pub fn into_box(self) -> Box<T> {
1121 let (raw, _) = decompose_tag::<T>(self.data);
1122 mem::forget(self);
1123 unsafe { Box::from_raw(raw as *mut _) }
1124 }
1125
1126 /// Allocates `value` on the heap and returns a new owned pointer pointing to it.
1127 ///
1128 /// # Examples
1129 ///
1130 /// ```
1131 /// use crossbeam_epoch::Owned;
1132 ///
1133 /// let o = Owned::new(1234);
1134 /// ```
1135 pub fn new(init: T) -> Owned<T> {
1136 Self::init(init)
1137 }
1138}
1139
1140impl<T: ?Sized + Pointable> Owned<T> {
1141 /// Allocates `value` on the heap and returns a new owned pointer pointing to it.
1142 ///
1143 /// # Examples
1144 ///
1145 /// ```
1146 /// use crossbeam_epoch::Owned;
1147 ///
1148 /// let o = Owned::<i32>::init(1234);
1149 /// ```
1150 pub fn init(init: T::Init) -> Owned<T> {
1151 unsafe { Self::from_usize(T::init(init)) }
1152 }
1153
1154 /// Converts the owned pointer into a [`Shared`].
1155 ///
1156 /// # Examples
1157 ///
1158 /// ```
1159 /// use crossbeam_epoch::{self as epoch, Owned};
1160 ///
1161 /// let o = Owned::new(1234);
1162 /// let guard = &epoch::pin();
1163 /// let p = o.into_shared(guard);
1164 /// # unsafe { drop(p.into_owned()); } // avoid leak
1165 /// ```
1166 #[allow(clippy::needless_lifetimes)]
1167 pub fn into_shared<'g>(self, _: &'g Guard) -> Shared<'g, T> {
1168 unsafe { Shared::from_usize(self.into_usize()) }
1169 }
1170
1171 /// Returns the tag stored within the pointer.
1172 ///
1173 /// # Examples
1174 ///
1175 /// ```
1176 /// use crossbeam_epoch::Owned;
1177 ///
1178 /// assert_eq!(Owned::new(1234).tag(), 0);
1179 /// ```
1180 pub fn tag(&self) -> usize {
1181 let (_, tag) = decompose_tag::<T>(self.data);
1182 tag
1183 }
1184
1185 /// Returns the same pointer, but tagged with `tag`. `tag` is truncated to be fit into the
1186 /// unused bits of the pointer to `T`.
1187 ///
1188 /// # Examples
1189 ///
1190 /// ```
1191 /// use crossbeam_epoch::Owned;
1192 ///
1193 /// let o = Owned::new(0u64);
1194 /// assert_eq!(o.tag(), 0);
1195 /// let o = o.with_tag(2);
1196 /// assert_eq!(o.tag(), 2);
1197 /// ```
1198 pub fn with_tag(self, tag: usize) -> Owned<T> {
1199 let data = self.into_usize();
1200 unsafe { Self::from_usize(compose_tag::<T>(data, tag)) }
1201 }
1202}
1203
1204impl<T: ?Sized + Pointable> Drop for Owned<T> {
1205 fn drop(&mut self) {
1206 let (raw, _) = decompose_tag::<T>(self.data);
1207 unsafe {
1208 T::drop(raw);
1209 }
1210 }
1211}
1212
1213impl<T: ?Sized + Pointable> fmt::Debug for Owned<T> {
1214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1215 let (raw, tag) = decompose_tag::<T>(self.data);
1216
1217 f.debug_struct("Owned")
1218 .field("raw", &raw)
1219 .field("tag", &tag)
1220 .finish()
1221 }
1222}
1223
1224impl<T: Clone> Clone for Owned<T> {
1225 fn clone(&self) -> Self {
1226 Owned::new((**self).clone()).with_tag(self.tag())
1227 }
1228}
1229
1230impl<T: ?Sized + Pointable> Deref for Owned<T> {
1231 type Target = T;
1232
1233 fn deref(&self) -> &T {
1234 let (raw, _) = decompose_tag::<T>(self.data);
1235 unsafe { T::deref(raw) }
1236 }
1237}
1238
1239impl<T: ?Sized + Pointable> DerefMut for Owned<T> {
1240 fn deref_mut(&mut self) -> &mut T {
1241 let (raw, _) = decompose_tag::<T>(self.data);
1242 unsafe { T::deref_mut(raw) }
1243 }
1244}
1245
1246impl<T> From<T> for Owned<T> {
1247 fn from(t: T) -> Self {
1248 Owned::new(t)
1249 }
1250}
1251
1252impl<T> From<Box<T>> for Owned<T> {
1253 /// Returns a new owned pointer pointing to `b`.
1254 ///
1255 /// # Panics
1256 ///
1257 /// Panics if the pointer (the `Box`) is not properly aligned.
1258 ///
1259 /// # Examples
1260 ///
1261 /// ```
1262 /// use crossbeam_epoch::Owned;
1263 ///
1264 /// let o = unsafe { Owned::from_raw(Box::into_raw(Box::new(1234))) };
1265 /// ```
1266 fn from(b: Box<T>) -> Self {
1267 unsafe { Self::from_raw(Box::into_raw(b)) }
1268 }
1269}
1270
1271impl<T: ?Sized + Pointable> Borrow<T> for Owned<T> {
1272 fn borrow(&self) -> &T {
1273 self.deref()
1274 }
1275}
1276
1277impl<T: ?Sized + Pointable> BorrowMut<T> for Owned<T> {
1278 fn borrow_mut(&mut self) -> &mut T {
1279 self.deref_mut()
1280 }
1281}
1282
1283impl<T: ?Sized + Pointable> AsRef<T> for Owned<T> {
1284 fn as_ref(&self) -> &T {
1285 self.deref()
1286 }
1287}
1288
1289impl<T: ?Sized + Pointable> AsMut<T> for Owned<T> {
1290 fn as_mut(&mut self) -> &mut T {
1291 self.deref_mut()
1292 }
1293}
1294
1295/// A pointer to an object protected by the epoch GC.
1296///
1297/// The pointer is valid for use only during the lifetime `'g`.
1298///
1299/// The pointer must be properly aligned. Since it is aligned, a tag can be stored into the unused
1300/// least significant bits of the address.
1301pub struct Shared<'g, T: 'g + ?Sized + Pointable> {
1302 data: usize,
1303 _marker: PhantomData<(&'g (), *const T)>,
1304}
1305
1306impl<T: ?Sized + Pointable> Clone for Shared<'_, T> {
1307 fn clone(&self) -> Self {
1308 *self
1309 }
1310}
1311
1312impl<T: ?Sized + Pointable> Copy for Shared<'_, T> {}
1313
1314impl<T: ?Sized + Pointable> Pointer<T> for Shared<'_, T> {
1315 #[inline]
1316 fn into_usize(self) -> usize {
1317 self.data
1318 }
1319
1320 #[inline]
1321 unsafe fn from_usize(data: usize) -> Self {
1322 Shared {
1323 data,
1324 _marker: PhantomData,
1325 }
1326 }
1327}
1328
1329impl<'g, T> Shared<'g, T> {
1330 /// Converts the pointer to a raw pointer (without the tag).
1331 ///
1332 /// # Examples
1333 ///
1334 /// ```
1335 /// use crossbeam_epoch::{self as epoch, Atomic, Owned};
1336 /// use std::sync::atomic::Ordering::SeqCst;
1337 ///
1338 /// let o = Owned::new(1234);
1339 /// let raw = &*o as *const _;
1340 /// let a = Atomic::from(o);
1341 ///
1342 /// let guard = &epoch::pin();
1343 /// let p = a.load(SeqCst, guard);
1344 /// assert_eq!(p.as_raw(), raw);
1345 /// # unsafe { drop(a.into_owned()); } // avoid leak
1346 /// ```
1347 pub fn as_raw(&self) -> *const T {
1348 let (raw, _) = decompose_tag::<T>(self.data);
1349 raw as *const _
1350 }
1351}
1352
1353impl<'g, T: ?Sized + Pointable> Shared<'g, T> {
1354 /// Returns a new null pointer.
1355 ///
1356 /// # Examples
1357 ///
1358 /// ```
1359 /// use crossbeam_epoch::Shared;
1360 ///
1361 /// let p = Shared::<i32>::null();
1362 /// assert!(p.is_null());
1363 /// ```
1364 pub fn null() -> Shared<'g, T> {
1365 Shared {
1366 data: 0,
1367 _marker: PhantomData,
1368 }
1369 }
1370
1371 /// Returns `true` if the pointer is null.
1372 ///
1373 /// # Examples
1374 ///
1375 /// ```
1376 /// use crossbeam_epoch::{self as epoch, Atomic, Owned};
1377 /// use std::sync::atomic::Ordering::SeqCst;
1378 ///
1379 /// let a = Atomic::null();
1380 /// let guard = &epoch::pin();
1381 /// assert!(a.load(SeqCst, guard).is_null());
1382 /// a.store(Owned::new(1234), SeqCst);
1383 /// assert!(!a.load(SeqCst, guard).is_null());
1384 /// # unsafe { drop(a.into_owned()); } // avoid leak
1385 /// ```
1386 pub fn is_null(&self) -> bool {
1387 let (raw, _) = decompose_tag::<T>(self.data);
1388 raw == 0
1389 }
1390
1391 /// Dereferences the pointer.
1392 ///
1393 /// Returns a reference to the pointee that is valid during the lifetime `'g`.
1394 ///
1395 /// # Safety
1396 ///
1397 /// Dereferencing a pointer is unsafe because it could be pointing to invalid memory.
1398 ///
1399 /// Another concern is the possibility of data races due to lack of proper synchronization.
1400 /// For example, consider the following scenario:
1401 ///
1402 /// 1. A thread creates a new object: `a.store(Owned::new(10), Relaxed)`
1403 /// 2. Another thread reads it: `*a.load(Relaxed, guard).as_ref().unwrap()`
1404 ///
1405 /// The problem is that relaxed orderings don't synchronize initialization of the object with
1406 /// the read from the second thread. This is a data race. A possible solution would be to use
1407 /// `Release` and `Acquire` orderings.
1408 ///
1409 /// # Examples
1410 ///
1411 /// ```
1412 /// use crossbeam_epoch::{self as epoch, Atomic};
1413 /// use std::sync::atomic::Ordering::SeqCst;
1414 ///
1415 /// let a = Atomic::new(1234);
1416 /// let guard = &epoch::pin();
1417 /// let p = a.load(SeqCst, guard);
1418 /// unsafe {
1419 /// assert_eq!(p.deref(), &1234);
1420 /// }
1421 /// # unsafe { drop(a.into_owned()); } // avoid leak
1422 /// ```
1423 pub unsafe fn deref(&self) -> &'g T {
1424 let (raw, _) = decompose_tag::<T>(self.data);
1425 T::deref(raw)
1426 }
1427
1428 /// Dereferences the pointer.
1429 ///
1430 /// Returns a mutable reference to the pointee that is valid during the lifetime `'g`.
1431 ///
1432 /// # Safety
1433 ///
1434 /// * There is no guarantee that there are no more threads attempting to read/write from/to the
1435 /// actual object at the same time.
1436 ///
1437 /// The user must know that there are no concurrent accesses towards the object itself.
1438 ///
1439 /// * Other than the above, all safety concerns of `deref()` applies here.
1440 ///
1441 /// # Examples
1442 ///
1443 /// ```
1444 /// use crossbeam_epoch::{self as epoch, Atomic};
1445 /// use std::sync::atomic::Ordering::SeqCst;
1446 ///
1447 /// let a = Atomic::new(vec![1, 2, 3, 4]);
1448 /// let guard = &epoch::pin();
1449 ///
1450 /// let mut p = a.load(SeqCst, guard);
1451 /// unsafe {
1452 /// assert!(!p.is_null());
1453 /// let b = p.deref_mut();
1454 /// assert_eq!(b, &vec![1, 2, 3, 4]);
1455 /// b.push(5);
1456 /// assert_eq!(b, &vec![1, 2, 3, 4, 5]);
1457 /// }
1458 ///
1459 /// let p = a.load(SeqCst, guard);
1460 /// unsafe {
1461 /// assert_eq!(p.deref(), &vec![1, 2, 3, 4, 5]);
1462 /// }
1463 /// # unsafe { drop(a.into_owned()); } // avoid leak
1464 /// ```
1465 pub unsafe fn deref_mut(&mut self) -> &'g mut T {
1466 let (raw, _) = decompose_tag::<T>(self.data);
1467 T::deref_mut(raw)
1468 }
1469
1470 /// Converts the pointer to a reference.
1471 ///
1472 /// Returns `None` if the pointer is null, or else a reference to the object wrapped in `Some`.
1473 ///
1474 /// # Safety
1475 ///
1476 /// Dereferencing a pointer is unsafe because it could be pointing to invalid memory.
1477 ///
1478 /// Another concern is the possibility of data races due to lack of proper synchronization.
1479 /// For example, consider the following scenario:
1480 ///
1481 /// 1. A thread creates a new object: `a.store(Owned::new(10), Relaxed)`
1482 /// 2. Another thread reads it: `*a.load(Relaxed, guard).as_ref().unwrap()`
1483 ///
1484 /// The problem is that relaxed orderings don't synchronize initialization of the object with
1485 /// the read from the second thread. This is a data race. A possible solution would be to use
1486 /// `Release` and `Acquire` orderings.
1487 ///
1488 /// # Examples
1489 ///
1490 /// ```
1491 /// use crossbeam_epoch::{self as epoch, Atomic};
1492 /// use std::sync::atomic::Ordering::SeqCst;
1493 ///
1494 /// let a = Atomic::new(1234);
1495 /// let guard = &epoch::pin();
1496 /// let p = a.load(SeqCst, guard);
1497 /// unsafe {
1498 /// assert_eq!(p.as_ref(), Some(&1234));
1499 /// }
1500 /// # unsafe { drop(a.into_owned()); } // avoid leak
1501 /// ```
1502 pub unsafe fn as_ref(&self) -> Option<&'g T> {
1503 let (raw, _) = decompose_tag::<T>(self.data);
1504 if raw == 0 {
1505 None
1506 } else {
1507 Some(T::deref(raw))
1508 }
1509 }
1510
1511 /// Takes ownership of the pointee.
1512 ///
1513 /// # Panics
1514 ///
1515 /// Panics if this pointer is null, but only in debug mode.
1516 ///
1517 /// # Safety
1518 ///
1519 /// This method may be called only if the pointer is valid and nobody else is holding a
1520 /// reference to the same object.
1521 ///
1522 /// # Examples
1523 ///
1524 /// ```
1525 /// use crossbeam_epoch::{self as epoch, Atomic};
1526 /// use std::sync::atomic::Ordering::SeqCst;
1527 ///
1528 /// let a = Atomic::new(1234);
1529 /// unsafe {
1530 /// let guard = &epoch::unprotected();
1531 /// let p = a.load(SeqCst, guard);
1532 /// drop(p.into_owned());
1533 /// }
1534 /// ```
1535 pub unsafe fn into_owned(self) -> Owned<T> {
1536 debug_assert!(!self.is_null(), "converting a null `Shared` into `Owned`");
1537 Owned::from_usize(self.data)
1538 }
1539
1540 /// Takes ownership of the pointee if it is not null.
1541 ///
1542 /// # Safety
1543 ///
1544 /// This method may be called only if the pointer is valid and nobody else is holding a
1545 /// reference to the same object, or if the pointer is null.
1546 ///
1547 /// # Examples
1548 ///
1549 /// ```
1550 /// use crossbeam_epoch::{self as epoch, Atomic};
1551 /// use std::sync::atomic::Ordering::SeqCst;
1552 ///
1553 /// let a = Atomic::new(1234);
1554 /// unsafe {
1555 /// let guard = &epoch::unprotected();
1556 /// let p = a.load(SeqCst, guard);
1557 /// if let Some(x) = p.try_into_owned() {
1558 /// drop(x);
1559 /// }
1560 /// }
1561 /// ```
1562 pub unsafe fn try_into_owned(self) -> Option<Owned<T>> {
1563 if self.is_null() {
1564 None
1565 } else {
1566 Some(Owned::from_usize(self.data))
1567 }
1568 }
1569
1570 /// Returns the tag stored within the pointer.
1571 ///
1572 /// # Examples
1573 ///
1574 /// ```
1575 /// use crossbeam_epoch::{self as epoch, Atomic, Owned};
1576 /// use std::sync::atomic::Ordering::SeqCst;
1577 ///
1578 /// let a = Atomic::<u64>::from(Owned::new(0u64).with_tag(2));
1579 /// let guard = &epoch::pin();
1580 /// let p = a.load(SeqCst, guard);
1581 /// assert_eq!(p.tag(), 2);
1582 /// # unsafe { drop(a.into_owned()); } // avoid leak
1583 /// ```
1584 pub fn tag(&self) -> usize {
1585 let (_, tag) = decompose_tag::<T>(self.data);
1586 tag
1587 }
1588
1589 /// Returns the same pointer, but tagged with `tag`. `tag` is truncated to be fit into the
1590 /// unused bits of the pointer to `T`.
1591 ///
1592 /// # Examples
1593 ///
1594 /// ```
1595 /// use crossbeam_epoch::{self as epoch, Atomic};
1596 /// use std::sync::atomic::Ordering::SeqCst;
1597 ///
1598 /// let a = Atomic::new(0u64);
1599 /// let guard = &epoch::pin();
1600 /// let p1 = a.load(SeqCst, guard);
1601 /// let p2 = p1.with_tag(2);
1602 ///
1603 /// assert_eq!(p1.tag(), 0);
1604 /// assert_eq!(p2.tag(), 2);
1605 /// assert_eq!(p1.as_raw(), p2.as_raw());
1606 /// # unsafe { drop(a.into_owned()); } // avoid leak
1607 /// ```
1608 pub fn with_tag(&self, tag: usize) -> Shared<'g, T> {
1609 unsafe { Self::from_usize(compose_tag::<T>(self.data, tag)) }
1610 }
1611}
1612
1613impl<T> From<*const T> for Shared<'_, T> {
1614 /// Returns a new pointer pointing to `raw`.
1615 ///
1616 /// # Panics
1617 ///
1618 /// Panics if `raw` is not properly aligned.
1619 ///
1620 /// # Examples
1621 ///
1622 /// ```
1623 /// use crossbeam_epoch::Shared;
1624 ///
1625 /// let p = Shared::from(Box::into_raw(Box::new(1234)) as *const _);
1626 /// assert!(!p.is_null());
1627 /// # unsafe { drop(p.into_owned()); } // avoid leak
1628 /// ```
1629 fn from(raw: *const T) -> Self {
1630 let raw = raw as usize;
1631 ensure_aligned::<T>(raw);
1632 unsafe { Self::from_usize(raw) }
1633 }
1634}
1635
1636impl<'g, T: ?Sized + Pointable> PartialEq<Shared<'g, T>> for Shared<'g, T> {
1637 fn eq(&self, other: &Self) -> bool {
1638 self.data == other.data
1639 }
1640}
1641
1642impl<T: ?Sized + Pointable> Eq for Shared<'_, T> {}
1643
1644impl<'g, T: ?Sized + Pointable> PartialOrd<Shared<'g, T>> for Shared<'g, T> {
1645 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
1646 self.data.partial_cmp(&other.data)
1647 }
1648}
1649
1650impl<T: ?Sized + Pointable> Ord for Shared<'_, T> {
1651 fn cmp(&self, other: &Self) -> cmp::Ordering {
1652 self.data.cmp(&other.data)
1653 }
1654}
1655
1656impl<T: ?Sized + Pointable> fmt::Debug for Shared<'_, T> {
1657 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1658 let (raw, tag) = decompose_tag::<T>(self.data);
1659
1660 f.debug_struct("Shared")
1661 .field("raw", &raw)
1662 .field("tag", &tag)
1663 .finish()
1664 }
1665}
1666
1667impl<T: ?Sized + Pointable> fmt::Pointer for Shared<'_, T> {
1668 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1669 let (raw, _) = decompose_tag::<T>(self.data);
1670 let ptr = if raw == 0 {
1671 raw as *const ()
1672 } else {
1673 unsafe { T::deref(raw) as *const T as *const () }
1674 };
1675 fmt::Pointer::fmt(&ptr, f)
1676 }
1677}
1678
1679impl<T: ?Sized + Pointable> Default for Shared<'_, T> {
1680 fn default() -> Self {
1681 Shared::null()
1682 }
1683}
1684
1685#[cfg(all(test, not(crossbeam_loom)))]
1686mod tests {
1687 use super::{Atomic, Owned, Shared};
1688 use std::{format, mem::MaybeUninit};
1689
1690 #[test]
1691 fn valid_tag_i8() {
1692 Shared::<i8>::null().with_tag(0);
1693 }
1694
1695 #[test]
1696 fn valid_tag_i64() {
1697 Shared::<i64>::null().with_tag(7);
1698 }
1699
1700 #[test]
1701 fn const_atomic_null() {
1702 use super::Atomic;
1703 static _U: Atomic<u8> = Atomic::<u8>::null();
1704 }
1705
1706 #[test]
1707 fn array_init() {
1708 let mut owned = Owned::<[MaybeUninit<usize>]>::init(10);
1709 let arr: &mut [MaybeUninit<usize>] = &mut owned;
1710 arr[arr.len() - 1].write(20);
1711 assert_eq!(arr.len(), 10);
1712 }
1713
1714 #[test]
1715 fn format_null() {
1716 let atomic = Atomic::<usize>::null();
1717 assert_eq!(format!("{atomic:p}"), "0x0");
1718 let atomic = Atomic::<[MaybeUninit<usize>]>::null();
1719 assert_eq!(format!("{atomic:p}"), "0x0");
1720
1721 let shared = Shared::<usize>::null();
1722 assert_eq!(format!("{shared:p}"), "0x0");
1723 let shared = Shared::<[MaybeUninit<usize>]>::null();
1724 assert_eq!(format!("{shared:p}"), "0x0");
1725 }
1726}