]> git.proxmox.com Git - cargo.git/blob - vendor/crossbeam-0.3.0/src/epoch/atomic.rs
New upstream version 0.23.0
[cargo.git] / vendor / crossbeam-0.3.0 / src / epoch / atomic.rs
1 use std::marker::PhantomData;
2 use std::mem;
3 use std::ptr;
4 use std::sync::atomic::{self, Ordering};
5
6 use super::{Owned, Shared, Guard};
7
8 /// Like `std::sync::atomic::AtomicPtr`.
9 ///
10 /// Provides atomic access to a (nullable) pointer of type `T`, interfacing with
11 /// the `Owned` and `Shared` types.
12 #[derive(Debug)]
13 pub struct Atomic<T> {
14 ptr: atomic::AtomicPtr<T>,
15 _marker: PhantomData<*const ()>,
16 }
17
18 unsafe impl<T: Sync> Send for Atomic<T> {}
19 unsafe impl<T: Sync> Sync for Atomic<T> {}
20
21 fn opt_shared_into_raw<T>(val: Option<Shared<T>>) -> *mut T {
22 val.map(|p| p.as_raw()).unwrap_or(ptr::null_mut())
23 }
24
25 fn opt_owned_as_raw<T>(val: &Option<Owned<T>>) -> *mut T {
26 val.as_ref().map(Owned::as_raw).unwrap_or(ptr::null_mut())
27 }
28
29 fn opt_owned_into_raw<T>(val: Option<Owned<T>>) -> *mut T {
30 let ptr = val.as_ref().map(Owned::as_raw).unwrap_or(ptr::null_mut());
31 mem::forget(val);
32 ptr
33 }
34
35 impl<T> Atomic<T> {
36 /// Create a new, null atomic pointer.
37 #[cfg(feature = "nightly")]
38 pub const fn null() -> Atomic<T> {
39 Atomic {
40 ptr: atomic::AtomicPtr::new(0 as *mut _),
41 _marker: PhantomData
42 }
43 }
44
45 #[cfg(not(feature = "nightly"))]
46 pub fn null() -> Atomic<T> {
47 Atomic {
48 ptr: atomic::AtomicPtr::new(0 as *mut _),
49 _marker: PhantomData
50 }
51 }
52
53 /// Create a new atomic pointer
54 pub fn new(data: T) -> Atomic<T> {
55 Atomic {
56 ptr: atomic::AtomicPtr::new(Box::into_raw(Box::new(data))),
57 _marker: PhantomData
58 }
59 }
60
61 /// Do an atomic load with the given memory ordering.
62 ///
63 /// In order to perform the load, we must pass in a borrow of a
64 /// `Guard`. This is a way of guaranteeing that the thread has pinned the
65 /// epoch for the entire lifetime `'a`. In return, you get an optional
66 /// `Shared` pointer back (`None` if the `Atomic` is currently null), with
67 /// lifetime tied to the guard.
68 ///
69 /// # Panics
70 ///
71 /// Panics if `ord` is `Release` or `AcqRel`.
72 pub fn load<'a>(&self, ord: Ordering, _: &'a Guard) -> Option<Shared<'a, T>> {
73 unsafe { Shared::from_raw(self.ptr.load(ord)) }
74 }
75
76 /// Do an atomic store with the given memory ordering.
77 ///
78 /// Transfers ownership of the given `Owned` pointer, if any. Since no
79 /// lifetime information is acquired, no `Guard` value is needed.
80 ///
81 /// # Panics
82 ///
83 /// Panics if `ord` is `Acquire` or `AcqRel`.
84 pub fn store(&self, val: Option<Owned<T>>, ord: Ordering) {
85 self.ptr.store(opt_owned_into_raw(val), ord)
86 }
87
88 /// Do an atomic store with the given memory ordering, immediately yielding
89 /// a shared reference to the pointer that was stored.
90 ///
91 /// Transfers ownership of the given `Owned` pointer, yielding a `Shared`
92 /// reference to it. Since the reference is valid only for the curent epoch,
93 /// it's lifetime is tied to a `Guard` value.
94 ///
95 /// # Panics
96 ///
97 /// Panics if `ord` is `Acquire` or `AcqRel`.
98 pub fn store_and_ref<'a>(&self, val: Owned<T>, ord: Ordering, _: &'a Guard)
99 -> Shared<'a, T>
100 {
101 unsafe {
102 let shared = Shared::from_owned(val);
103 self.store_shared(Some(shared), ord);
104 shared
105 }
106 }
107
108 /// Do an atomic store of a `Shared` pointer with the given memory ordering.
109 ///
110 /// This operation does not require a guard, because it does not yield any
111 /// new information about the lifetime of a pointer.
112 ///
113 /// # Panics
114 ///
115 /// Panics if `ord` is `Acquire` or `AcqRel`.
116 pub fn store_shared(&self, val: Option<Shared<T>>, ord: Ordering) {
117 self.ptr.store(opt_shared_into_raw(val), ord)
118 }
119
120 /// Do a compare-and-set from a `Shared` to an `Owned` pointer with the
121 /// given memory ordering.
122 ///
123 /// As with `store`, this operation does not require a guard; it produces no new
124 /// lifetime information. The `Result` indicates whether the CAS succeeded; if
125 /// not, ownership of the `new` pointer is returned to the caller.
126 pub fn cas(&self, old: Option<Shared<T>>, new: Option<Owned<T>>, ord: Ordering)
127 -> Result<(), Option<Owned<T>>>
128 {
129 if self.ptr.compare_and_swap(opt_shared_into_raw(old),
130 opt_owned_as_raw(&new),
131 ord) == opt_shared_into_raw(old)
132 {
133 mem::forget(new);
134 Ok(())
135 } else {
136 Err(new)
137 }
138 }
139
140 /// Do a compare-and-set from a `Shared` to an `Owned` pointer with the
141 /// given memory ordering, immediatley acquiring a new `Shared` reference to
142 /// the previously-owned pointer if successful.
143 ///
144 /// This operation is analogous to `store_and_ref`.
145 pub fn cas_and_ref<'a>(&self, old: Option<Shared<T>>, new: Owned<T>,
146 ord: Ordering, _: &'a Guard)
147 -> Result<Shared<'a, T>, Owned<T>>
148 {
149 if self.ptr.compare_and_swap(opt_shared_into_raw(old), new.as_raw(), ord)
150 == opt_shared_into_raw(old)
151 {
152 Ok(unsafe { Shared::from_owned(new) })
153 } else {
154 Err(new)
155 }
156 }
157
158 /// Do a compare-and-set from a `Shared` to another `Shared` pointer with
159 /// the given memory ordering.
160 ///
161 /// The boolean return value is `true` when the CAS is successful.
162 pub fn cas_shared(&self, old: Option<Shared<T>>, new: Option<Shared<T>>, ord: Ordering)
163 -> bool
164 {
165 self.ptr.compare_and_swap(opt_shared_into_raw(old),
166 opt_shared_into_raw(new),
167 ord) == opt_shared_into_raw(old)
168 }
169
170 /// Do an atomic swap with an `Owned` pointer with the given memory ordering.
171 pub fn swap<'a>(&self, new: Option<Owned<T>>, ord: Ordering, _: &'a Guard)
172 -> Option<Shared<'a, T>> {
173 unsafe { Shared::from_raw(self.ptr.swap(opt_owned_into_raw(new), ord)) }
174 }
175
176 /// Do an atomic swap with a `Shared` pointer with the given memory ordering.
177 pub fn swap_shared<'a>(&self, new: Option<Shared<T>>, ord: Ordering, _: &'a Guard)
178 -> Option<Shared<'a, T>> {
179 unsafe { Shared::from_raw(self.ptr.swap(opt_shared_into_raw(new), ord)) }
180 }
181 }