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