keos/sync/atomic.rs
1//! A wrapper around the core::sync::atomic.
2//!
3//! # Atomic types
4//!
5//! Atomic types provide primitive shared-memory communication between
6//! threads, and are the building blocks of other concurrent
7//! types.
8//!
9//! This module defines a wrapper to the atomic types defined in
10//! [`core::sync::atomic`], including [`AtomicBool`], [`AtomicIsize`],
11//! [`AtomicUsize`], [`AtomicI8`], [`AtomicU16`], etc.
12//! Atomic types present operations that, when used correctly, synchronize
13//! updates between threads.
14//!
15//! Atomic variables are safe to share between threads (they implement [`Sync`])
16//! but they do not themselves provide the mechanism for sharing and follow the
17//! [threading model](https://doc.rust-lang.org/std/thread/#the-threading-model) of
18//! Rust. The most common way to share an atomic variable is to put it into an
19//! [`Arc`][arc] (an atomically-reference-counted shared pointer).
20//!
21//! [arc]: https://doc.rust-lang.org/beta/std/sync/struct.Arc.html
22//! [`core::sync::atomic`]: https://doc.rust-lang.org/core/sync/atomic/
23//! [`Sync`]: https://doc.rust-lang.org/beta/core/marker/trait.Sync.html
24
25use core::sync::atomic::Ordering;
26
27/// A boolean type which can be safely shared between threads.
28///
29/// This type has the same size, alignment, and bit validity as a [`bool`].
30#[derive(Default)]
31pub struct AtomicBool(core::sync::atomic::AtomicBool);
32
33/// A raw pointer type which can be safely shared between threads.
34///
35/// This type has the same size and bit validity as a `*mut T`.
36///
37/// **Note**: This type is only available on platforms that support atomic
38/// loads and stores of pointers. Its size depends on the target pointer's size.
39#[derive(Default)]
40pub struct AtomicPtr<T>(core::sync::atomic::AtomicPtr<T>);
41
42impl AtomicBool {
43 /// Creates a new `AtomicBool`.
44 ///
45 /// # Examples
46 ///
47 /// ```
48 /// use KeOS::sync::atomic::AtomicBool;
49 ///
50 /// let atomic_true = AtomicBool::new(true);
51 /// let atomic_false = AtomicBool::new(false);
52 /// ```
53 #[inline]
54 #[must_use]
55 pub const fn new(v: bool) -> AtomicBool {
56 Self(core::sync::atomic::AtomicBool::new(v))
57 }
58
59 /// Returns a mutable reference to the underlying [`bool`].
60 ///
61 /// This is safe because the mutable reference guarantees that no other
62 /// threads are concurrently accessing the atomic data.
63 ///
64 /// # Examples
65 ///
66 /// ```
67 /// use keos::atomic::AtomicBool;
68 ///
69 /// let mut some_bool = AtomicBool::new(true);
70 /// assert_eq!(*some_bool.get_mut(), true);
71 /// *some_bool.get_mut() = false;
72 /// assert_eq!(some_bool.load(), false);
73 /// ```
74 #[inline]
75 pub fn get_mut(&mut self) -> &mut bool {
76 self.0.get_mut()
77 }
78
79 /// Consumes the atomic and returns the contained value.
80 ///
81 /// This is safe because passing `self` by value guarantees that no other
82 /// threads are concurrently accessing the atomic data.
83 ///
84 /// # Examples
85 ///
86 /// ```
87 /// use keos::atomic::AtomicBool;
88 ///
89 /// let some_bool = AtomicBool::new(true);
90 /// assert_eq!(some_bool.into_inner(), true);
91 /// ```
92 #[inline]
93 pub const fn into_inner(self) -> bool {
94 self.0.into_inner()
95 }
96
97 /// Loads a value from the bool.
98 ///
99 /// # Examples
100 ///
101 /// ```
102 /// use keos::atomic::AtomicBool;
103 ///
104 /// let some_bool = AtomicBool::new(true);
105 ///
106 /// assert_eq!(some_bool.load(), true);
107 /// ```
108 #[inline]
109 pub fn load(&self) -> bool {
110 self.0.load(Ordering::SeqCst)
111 }
112
113 /// Stores a value into the bool.
114 ///
115 ///
116 /// # Examples
117 ///
118 /// ```
119 /// use keos::atomic::AtomicBool;
120 ///
121 /// let some_bool = AtomicBool::new(true);
122 ///
123 /// some_bool.store(false);
124 /// assert_eq!(some_bool.load(), false);
125 /// ```
126 #[inline]
127 pub fn store(&self, val: bool) {
128 self.0.store(val, Ordering::SeqCst)
129 }
130
131 /// Stores a value into the bool, returning the previous value.
132 ///
133 /// # Examples
134 ///
135 /// ```
136 /// use keos::atomic::AtomicBool;
137 ///
138 /// let some_bool = AtomicBool::new(true);
139 ///
140 /// assert_eq!(some_bool.swap(false), true);
141 /// assert_eq!(some_bool.load(), false);
142 /// ```
143 #[inline]
144 pub fn swap(&self, val: bool) -> bool {
145 self.0.swap(val, Ordering::SeqCst)
146 }
147
148 /// Stores a value into the [`bool`] if the current value is the same as the
149 /// `current` value.
150 ///
151 /// The return value is a result indicating whether the new value was
152 /// written and containing the previous value. On success this value is
153 /// guaranteed to be equal to `current`.
154 ///
155 /// # Examples
156 ///
157 /// ```
158 /// use std::sync::atomic::AtomicBool;
159 ///
160 /// let some_bool = AtomicBool::new(true);
161 ///
162 /// assert_eq!(some_bool.compare_exchange(true, false), Ok(true));
163 /// assert_eq!(some_bool.load(), false);
164 ///
165 /// assert_eq!(some_bool.compare_exchange(true, true), Err(false));
166 /// assert_eq!(some_bool.load(), false);
167 /// ```
168 #[inline]
169 pub fn compare_exchange(&self, current: bool, new: bool) -> Result<bool, bool> {
170 self.0
171 .compare_exchange(current, new, Ordering::SeqCst, Ordering::SeqCst)
172 }
173
174 /// Logical "and" with a boolean value.
175 ///
176 /// Performs a logical "and" operation on the current value and the argument
177 /// `val`, and sets the new value to the result.
178 ///
179 /// Returns the previous value.
180 ///
181 /// # Examples
182 ///
183 /// ```
184 /// use keos::atomic::AtomicBool;
185 ///
186 /// let foo = AtomicBool::new(true);
187 /// assert_eq!(foo.fetch_and(false), true);
188 /// assert_eq!(foo.load(), false);
189 ///
190 /// let foo = AtomicBool::new(true);
191 /// assert_eq!(foo.fetch_and(true), true);
192 /// assert_eq!(foo.load(), true);
193 ///
194 /// let foo = AtomicBool::new(false);
195 /// assert_eq!(foo.fetch_and(false), false);
196 /// assert_eq!(foo.load(), false);
197 /// ```
198 #[inline]
199 pub fn fetch_and(&self, val: bool) -> bool {
200 self.0.fetch_and(val, Ordering::SeqCst)
201 }
202
203 /// Logical "nand" with a boolean value.
204 ///
205 /// Performs a logical "nand" operation on the current value and the
206 /// argument `val`, and sets the new value to the result.
207 ///
208 /// Returns the previous value.
209 ///
210 /// **Note:** This method is only available on platforms that support atomic
211 /// operations on `u8`.
212 ///
213 /// # Examples
214 ///
215 /// ```
216 /// use keos::atomic::{AtomicBool, Ordering};
217 ///
218 /// let foo = AtomicBool::new(true);
219 /// assert_eq!(foo.fetch_nand(false), true);
220 /// assert_eq!(foo.load(), true);
221 ///
222 /// let foo = AtomicBool::new(true);
223 /// assert_eq!(foo.fetch_nand(true), true);
224 /// assert_eq!(foo.load() as usize, 0);
225 /// assert_eq!(foo.load(), false);
226 ///
227 /// let foo = AtomicBool::new(false);
228 /// assert_eq!(foo.fetch_nand(false), false);
229 /// assert_eq!(foo.load(), true);
230 /// ```
231 #[inline]
232 pub fn fetch_nand(&self, val: bool) -> bool {
233 self.0.fetch_nand(val, Ordering::SeqCst)
234 }
235
236 /// Logical "or" with a boolean value.
237 ///
238 /// Performs a logical "or" operation on the current value and the argument
239 /// `val`, and sets the new value to the result.
240 ///
241 /// Returns the previous value.
242 ///
243 /// **Note:** This method is only available on platforms that support atomic
244 /// operations on `u8`.
245 ///
246 /// # Examples
247 ///
248 /// ```
249 /// use keos::atomic::{AtomicBool, Ordering};
250 ///
251 /// let foo = AtomicBool::new(true);
252 /// assert_eq!(foo.fetch_or(false), true);
253 /// assert_eq!(foo.load(), true);
254 ///
255 /// let foo = AtomicBool::new(true);
256 /// assert_eq!(foo.fetch_or(true), true);
257 /// assert_eq!(foo.load(), true);
258 ///
259 /// let foo = AtomicBool::new(false);
260 /// assert_eq!(foo.fetch_or(false), false);
261 /// assert_eq!(foo.load(), false);
262 /// ```
263 #[inline]
264 pub fn fetch_or(&self, val: bool) -> bool {
265 self.0.fetch_or(val, Ordering::SeqCst)
266 }
267
268 /// Logical "xor" with a boolean value.
269 ///
270 /// Performs a logical "xor" operation on the current value and the argument
271 /// `val`, and sets the new value to the result.
272 ///
273 /// Returns the previous value.
274 ///
275 /// **Note:** This method is only available on platforms that support atomic
276 /// operations on `u8`.
277 ///
278 /// # Examples
279 ///
280 /// ```
281 /// use keos::atomic::{AtomicBool, Ordering};
282 ///
283 /// let foo = AtomicBool::new(true);
284 /// assert_eq!(foo.fetch_xor(false), true);
285 /// assert_eq!(foo.load(), true);
286 ///
287 /// let foo = AtomicBool::new(true);
288 /// assert_eq!(foo.fetch_xor(true), true);
289 /// assert_eq!(foo.load(), false);
290 ///
291 /// let foo = AtomicBool::new(false);
292 /// assert_eq!(foo.fetch_xor(false), false);
293 /// assert_eq!(foo.load(), false);
294 /// ```
295 #[inline]
296 pub fn fetch_xor(&self, val: bool) -> bool {
297 self.0.fetch_xor(val, Ordering::SeqCst)
298 }
299
300 /// Logical "not" with a boolean value.
301 ///
302 /// Performs a logical "not" operation on the current value, and sets
303 /// the new value to the result.
304 ///
305 /// Returns the previous value.
306 ///
307 /// **Note:** This method is only available on platforms that support atomic
308 /// operations on `u8`.
309 ///
310 /// # Examples
311 ///
312 /// ```
313 /// use keos::atomic::AtomicBool;
314 ///
315 /// let foo = AtomicBool::new(true);
316 /// assert_eq!(foo.fetch_not(), true);
317 /// assert_eq!(foo.load(), false);
318 ///
319 /// let foo = AtomicBool::new(false);
320 /// assert_eq!(foo.fetch_not(), false);
321 /// assert_eq!(foo.load(), true);
322 /// ```
323 #[inline]
324 pub fn fetch_not(&self) -> bool {
325 self.0.fetch_not(Ordering::SeqCst)
326 }
327
328 /// Fetches the value, and applies a function to it that returns an optional
329 /// new value. Returns a `Result` of `Ok(previous_value)` if the function
330 /// returned `Some(_)`, else `Err(previous_value)`.
331 ///
332 /// Note: This may call the function multiple times if the value has been
333 /// changed from other threads in the meantime, as long as the function
334 /// returns `Some(_)`, but the function will have been applied only once to
335 /// the stored value.
336 ///
337 /// # Examples
338 ///
339 /// ```rust
340 /// use keos::atomic::AtomicBool;
341 ///
342 /// let x = AtomicBool::new(false);
343 /// assert_eq!(x.fetch_update(|_| None), Err(false));
344 /// assert_eq!(x.fetch_update(|x| Some(!x)), Ok(false));
345 /// assert_eq!(x.fetch_update(|x| Some(!x)), Ok(true));
346 /// assert_eq!(x.load(), false);
347 /// ```
348 #[inline]
349 pub fn fetch_update<F>(&self, f: F) -> Result<bool, bool>
350 where
351 F: FnMut(bool) -> Option<bool>,
352 {
353 self.0.fetch_update(Ordering::SeqCst, Ordering::SeqCst, f)
354 }
355}
356
357impl<T> AtomicPtr<T> {
358 /// Creates a new `AtomicPtr`.
359 ///
360 /// # Examples
361 ///
362 /// ```
363 /// use keos::atomic::AtomicPtr;
364 ///
365 /// let ptr = &mut 5;
366 /// let atomic_ptr = AtomicPtr::new(ptr);
367 /// ```
368 #[inline]
369 pub const fn new(p: *mut T) -> AtomicPtr<T> {
370 Self(core::sync::atomic::AtomicPtr::new(p))
371 }
372
373 /// Returns a mutable reference to the underlying pointer.
374 ///
375 /// This is safe because the mutable reference guarantees that no other
376 /// threads are concurrently accessing the atomic data.
377 ///
378 /// # Examples
379 ///
380 /// ```
381 /// use keos::atomic::AtomicPtr;
382 ///
383 /// let mut data = 10;
384 /// let mut atomic_ptr = AtomicPtr::new(&mut data);
385 /// let mut other_data = 5;
386 /// *atomic_ptr.get_mut() = &mut other_data;
387 /// assert_eq!(unsafe { *atomic_ptr.load() }, 5);
388 /// ```
389 #[inline]
390 pub fn get_mut(&mut self) -> &mut *mut T {
391 self.0.get_mut()
392 }
393
394 /// Consumes the atomic and returns the contained value.
395 ///
396 /// This is safe because passing `self` by value guarantees that no other
397 /// threads are concurrently accessing the atomic data.
398 ///
399 /// # Examples
400 ///
401 /// ```
402 /// use keos::atomic::AtomicPtr;
403 ///
404 /// let mut data = 5;
405 /// let atomic_ptr = AtomicPtr::new(&mut data);
406 /// assert_eq!(unsafe { *atomic_ptr.into_inner() }, 5);
407 /// ```
408 #[inline]
409 pub const fn into_inner(self) -> *mut T {
410 self.0.into_inner()
411 }
412
413 /// Loads a value from the pointer.
414 ///
415 ///
416 /// # Examples
417 ///
418 /// ```
419 /// use keos::atomic::AtomicPtr;
420 ///
421 /// let ptr = &mut 5;
422 /// let some_ptr = AtomicPtr::new(ptr);
423 ///
424 /// let value = some_ptr.load();
425 /// ```
426 #[inline]
427 pub fn load(&self) -> *mut T {
428 self.0.load(Ordering::SeqCst)
429 }
430
431 /// Stores a value into the pointer.
432 ///
433 /// # Examples
434 ///
435 /// ```
436 /// use keos::atomic::AtomicPtr;
437 ///
438 /// let ptr = &mut 5;
439 /// let some_ptr = AtomicPtr::new(ptr);
440 ///
441 /// let other_ptr = &mut 10;
442 ///
443 /// some_ptr.store(other_ptr);
444 /// ```
445 #[inline]
446 pub fn store(&self, ptr: *mut T) {
447 self.0.store(ptr, Ordering::SeqCst);
448 }
449
450 /// Stores a value into the pointer, returning the previous value.
451 ///
452 /// # Examples
453 ///
454 /// ```
455 /// use keos::atomic::AtomicPtr;
456 ///
457 /// let ptr = &mut 5;
458 /// let some_ptr = AtomicPtr::new(ptr);
459 ///
460 /// let other_ptr = &mut 10;
461 ///
462 /// let value = some_ptr.swap(other_ptr);
463 /// ```
464 #[inline]
465 pub fn swap(&self, ptr: *mut T) -> *mut T {
466 self.0.swap(ptr, Ordering::SeqCst)
467 }
468
469 /// Stores a value into the pointer if the current value is the same as the
470 /// `current` value.
471 ///
472 /// The return value is a result indicating whether the new value was
473 /// written and containing the previous value. On success this value is
474 /// guaranteed to be equal to `current`.
475 ///
476 ///
477 /// # Examples
478 ///
479 /// ```
480 /// use keos::atomic::AtomicPtr;
481 ///
482 /// let ptr = &mut 5;
483 /// let some_ptr = AtomicPtr::new(ptr);
484 ///
485 /// let other_ptr = &mut 10;
486 ///
487 /// let value = some_ptr.compare_exchange(ptr, other_ptr);
488 /// ```
489 #[inline]
490 pub fn compare_exchange(&self, current: *mut T, new: *mut T) -> Result<*mut T, *mut T> {
491 self.0
492 .compare_exchange(current, new, Ordering::SeqCst, Ordering::SeqCst)
493 }
494
495 /// Fetches the value, and applies a function to it that returns an optional
496 /// new value. Returns a `Result` of `Ok(previous_value)` if the function
497 /// returned `Some(_)`, else `Err(previous_value)`.
498 ///
499 /// Note: This may call the function multiple times if the value has been
500 /// changed from other threads in the meantime, as long as the function
501 /// returns `Some(_)`, but the function will have been applied only once to
502 /// the stored value.
503 ///
504 /// # Examples
505 ///
506 /// ```rust
507 /// use keos::atomic::AtomicPtr;
508 ///
509 /// let ptr: *mut _ = &mut 5;
510 /// let some_ptr = AtomicPtr::new(ptr);
511 ///
512 /// let new: *mut _ = &mut 10;
513 /// assert_eq!(some_ptr.fetch_update(, |_| None), Err(ptr));
514 /// let result = some_ptr.fetch_update(, |x| {
515 /// if x == ptr {
516 /// Some(new)
517 /// } else {
518 /// None
519 /// }
520 /// });
521 /// assert_eq!(result, Ok(ptr));
522 /// assert_eq!(some_ptr.load(), new);
523 /// ```
524 #[inline]
525 pub fn fetch_update<F>(&self, f: F) -> Result<*mut T, *mut T>
526 where
527 F: FnMut(*mut T) -> Option<*mut T>,
528 {
529 self.0.fetch_update(Ordering::SeqCst, Ordering::SeqCst, f)
530 }
531
532 /// Returns a mutable pointer to the underlying pointer.
533 ///
534 /// Doing non-atomic reads and writes on the resulting pointer can be a data
535 /// race. This method is mostly useful for FFI, where the function
536 /// signature may use `*mut *mut T` instead of `&AtomicPtr<T>`.
537 ///
538 /// Returning an `*mut` pointer from a shared reference to this atomic is
539 /// safe because the atomic types work with interior mutability. All
540 /// modifications of an atomic change the value through a shared
541 /// reference, and can do so safely as long as they use atomic operations.
542 /// Any use of the returned raw pointer requires an `unsafe` block and
543 /// still has to uphold the same restriction: operations on it must be
544 /// atomic.
545 ///
546 /// # Examples
547 ///
548 /// ```ignore (extern-declaration)
549 /// use keos::atomic::AtomicPtr;
550 ///
551 /// extern "C" {
552 /// fn my_atomic_op(arg: *mut *mut u32);
553 /// }
554 ///
555 /// let mut value = 17;
556 /// let atomic = AtomicPtr::new(&mut value);
557 ///
558 /// // SAFETY: Safe as long as `my_atomic_op` is atomic.
559 /// unsafe {
560 /// my_atomic_op(atomic.as_ptr());
561 /// }
562 /// ```
563 #[inline]
564 pub const fn as_ptr(&self) -> *mut *mut T {
565 self.0.as_ptr()
566 }
567}
568
569impl From<bool> for AtomicBool {
570 /// Converts a `bool` into an `AtomicBool`.
571 ///
572 /// # Examples
573 ///
574 /// ```
575 /// use keos::atomic::AtomicBool;
576 /// let atomic_bool = AtomicBool::from(true);
577 /// assert_eq!(format!("{atomic_bool:?}"), "true")
578 /// ```
579 #[inline]
580 fn from(b: bool) -> Self {
581 Self::new(b)
582 }
583}
584
585impl<T> From<*mut T> for AtomicPtr<T> {
586 /// Converts a `*mut T` into an `AtomicPtr<T>`.
587 #[inline]
588 fn from(p: *mut T) -> Self {
589 Self::new(p)
590 }
591}
592
593#[allow(unused_macros)] // This macro ends up being unused on some architectures.
594macro_rules! if_8_bit {
595 (u8, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($yes)*)?) };
596 (i8, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($yes)*)?) };
597 ($_:ident, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($no)*)?) };
598}
599
600macro_rules! atomic_int {
601 ($s_int_type:literal,
602 $extra_feature:expr,
603 $int_type:ident $atomic_type:ident) => {
604 /// An integer type which can be safely shared between threads.
605 ///
606 /// This type has the same
607 #[doc = if_8_bit!(
608 $int_type,
609 yes = ["size, alignment, and bit validity"],
610 no = ["size and bit validity"],
611 )]
612 /// as the underlying integer type, [`
613 #[doc = $s_int_type]
614 /// `].
615 #[doc = if_8_bit! {
616 $int_type,
617 no = [
618 "However, the alignment of this type is always equal to its ",
619 "size, even on targets where [`", $s_int_type, "`] has a ",
620 "lesser alignment."
621 ],
622 }]
623 ///
624 /// For more about the differences between atomic types and
625 /// non-atomic types as well as information about the portability of
626 /// this type, please see the [module-level documentation].
627 ///
628 /// **Note:** This type is only available on platforms that support
629 /// atomic loads and stores of [`
630 #[doc = $s_int_type]
631 /// `].
632 ///
633 #[repr(transparent)]
634 #[derive(Default)]
635 pub struct $atomic_type(core::sync::atomic::$atomic_type);
636
637 impl From<$int_type> for $atomic_type {
638 #[doc = concat!("Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`.")]
639 #[inline]
640 fn from(v: $int_type) -> Self { Self::new(v) }
641 }
642
643 impl core::fmt::Debug for $atomic_type {
644 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
645 core::fmt::Debug::fmt(&self.load(), f)
646 }
647 }
648
649 impl $atomic_type {
650 /// Creates a new atomic integer.
651 ///
652 /// # Examples
653 ///
654 /// ```
655 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
656 ///
657 #[doc = concat!("let atomic_forty_two = ", stringify!($atomic_type), "::new(42);")]
658 /// ```
659 #[inline]
660 #[must_use]
661 pub const fn new(v: $int_type) -> Self {
662 Self(core::sync::atomic::$atomic_type::new(v))
663 }
664
665 /// Returns a mutable reference to the underlying integer.
666 ///
667 /// This is safe because the mutable reference guarantees that no other threads are
668 /// concurrently accessing the atomic data.
669 ///
670 /// # Examples
671 ///
672 /// ```
673 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
674 ///
675 #[doc = concat!("let mut some_var = ", stringify!($atomic_type), "::new(10);")]
676 /// assert_eq!(*some_var.get_mut(), 10);
677 /// *some_var.get_mut() = 5;
678 /// assert_eq!(some_var.load(), 5);
679 /// ```
680 #[inline]
681 pub fn get_mut(&mut self) -> &mut $int_type {
682 self.0.get_mut()
683 }
684
685 /// Consumes the atomic and returns the contained value.
686 ///
687 /// This is safe because passing `self` by value guarantees that no other threads are
688 /// concurrently accessing the atomic data.
689 ///
690 /// # Examples
691 ///
692 /// ```
693 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
694 ///
695 #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
696 /// assert_eq!(some_var.into_inner(), 5);
697 /// ```
698 #[inline]
699 pub const fn into_inner(self) -> $int_type {
700 self.0.into_inner()
701 }
702
703 /// Loads a value from the atomic integer.
704 ///
705 /// # Examples
706 ///
707 /// ```
708 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
709 ///
710 #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
711 ///
712 /// assert_eq!(some_var.load(d), 5);
713 /// ```
714 #[inline]
715 pub fn load(&self) -> $int_type {
716 self.0.load(Ordering::SeqCst)
717 }
718
719 /// Stores a value into the atomic integer.
720 ///
721 /// # Examples
722 ///
723 /// ```
724 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
725 ///
726 #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
727 ///
728 /// some_var.store(10d);
729 /// assert_eq!(some_var.load(d), 10);
730 /// ```
731 #[inline]
732 pub fn store(&self, val: $int_type) {
733 self.0.store(val, Ordering::SeqCst)
734 }
735
736 /// Stores a value into the atomic integer, returning the previous value.
737 ///
738 /// # Examples
739 ///
740 /// ```
741 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
742 ///
743 #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
744 ///
745 /// assert_eq!(some_var.swap(10d), 5);
746 /// ```
747 #[inline]
748 pub fn swap(&self, val: $int_type) -> $int_type {
749 self.0.swap(val, Ordering::SeqCst)
750 }
751
752 /// Stores a value into the atomic integer if the current value is the same as
753 /// the `current` value.
754 ///
755 /// The return value is a result indicating whether the new value was written and
756 /// containing the previous value. On success this value is guaranteed to be equal to
757 /// `current`.
758 ///
759 /// # Examples
760 ///
761 /// ```
762 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
763 ///
764 #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
765 ///
766 /// assert_eq!(some_var.compare_exchange(5, 10, e), Ok(5));
767 /// assert_eq!(some_var.load(d), 10);
768 ///
769 /// assert_eq!(some_var.compare_exchange(6, 12, e), Err(10));
770 /// assert_eq!(some_var.load(d), 10);
771 /// ```
772 #[inline]
773 pub fn compare_exchange(&self,
774 current: $int_type,
775 new: $int_type) -> Result<$int_type, $int_type> {
776 self.0.compare_exchange(current, new, Ordering::SeqCst, Ordering::SeqCst)
777 }
778
779
780 /// Adds to the current value, returning the previous value.
781 ///
782 /// This operation wraps around on overflow.
783 ///
784 /// # Examples
785 ///
786 /// ```
787 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
788 ///
789 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0);")]
790 /// assert_eq!(foo.fetch_add(10), 0);
791 /// assert_eq!(foo.load(), 10);
792 /// ```
793 #[inline]
794 pub fn fetch_add(&self, val: $int_type) -> $int_type {
795 self.0.fetch_add(val, Ordering::SeqCst)
796 }
797
798 /// Subtracts from the current value, returning the previous value.
799 ///
800 /// This operation wraps around on overflow.
801 ///
802 /// # Examples
803 ///
804 /// ```
805 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
806 ///
807 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(20);")]
808 /// assert_eq!(foo.fetch_sub(10), 20);
809 /// assert_eq!(foo.load(), 10);
810 /// ```
811 #[inline]
812 pub fn fetch_sub(&self, val: $int_type) -> $int_type {
813 self.0.fetch_sub(val, Ordering::SeqCst)
814 }
815
816 /// Bitwise "and" with the current value.
817 ///
818 /// Performs a bitwise "and" operation on the current value and the argument `val`, and
819 /// sets the new value to the result.
820 ///
821 /// Returns the previous value.
822 ///
823 /// # Examples
824 ///
825 /// ```
826 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
827 ///
828 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")]
829 /// assert_eq!(foo.fetch_and(0b110011), 0b101101);
830 /// assert_eq!(foo.load(), 0b100001);
831 /// ```
832 #[inline]
833 pub fn fetch_and(&self, val: $int_type) -> $int_type {
834 self.0.fetch_and(val, Ordering::SeqCst)
835 }
836
837 /// Bitwise "nand" with the current value.
838 ///
839 /// Performs a bitwise "nand" operation on the current value and the argument `val`, and
840 /// sets the new value to the result.
841 ///
842 /// Returns the previous value.
843 ///
844 /// # Examples
845 ///
846 /// ```
847 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
848 ///
849 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0x13);")]
850 /// assert_eq!(foo.fetch_nand(0x31), 0x13);
851 /// assert_eq!(foo.load(), !(0x13 & 0x31));
852 /// ```
853 #[inline]
854 pub fn fetch_nand(&self, val: $int_type) -> $int_type {
855 self.0.fetch_nand(val, Ordering::SeqCst)
856 }
857
858 /// Bitwise "or" with the current value.
859 ///
860 /// Performs a bitwise "or" operation on the current value and the argument `val`, and
861 /// sets the new value to the result.
862 ///
863 /// Returns the previous value.
864 ///
865 /// # Examples
866 ///
867 /// ```
868 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
869 ///
870 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")]
871 /// assert_eq!(foo.fetch_or(0b110011), 0b101101);
872 /// assert_eq!(foo.load(), 0b111111);
873 /// ```
874 #[inline]
875 pub fn fetch_or(&self, val: $int_type) -> $int_type {
876 self.0.fetch_or(val, Ordering::SeqCst)
877 }
878
879 /// Bitwise "xor" with the current value.
880 ///
881 /// Performs a bitwise "xor" operation on the current value and the argument `val`, and
882 /// sets the new value to the result.
883 ///
884 /// Returns the previous value.
885 ///
886 /// # Examples
887 ///
888 /// ```
889 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
890 ///
891 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")]
892 /// assert_eq!(foo.fetch_xor(0b110011), 0b101101);
893 /// assert_eq!(foo.load(), 0b011110);
894 /// ```
895 #[inline]
896 pub fn fetch_xor(&self, val: $int_type) -> $int_type {
897 self.0.fetch_xor(val, Ordering::SeqCst)
898 }
899
900 /// Fetches the value, and applies a function to it that returns an optional
901 /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
902 /// `Err(previous_value)`.
903 ///
904 /// Note: This may call the function multiple times if the value has been changed from other threads in
905 /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
906 /// only once to the stored value.
907 ///
908 /// # Examples
909 ///
910 /// ```rust
911 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
912 ///
913 #[doc = concat!("let x = ", stringify!($atomic_type), "::new(7);")]
914 /// assert_eq!(x.fetch_update(|_| None), Err(7));
915 /// assert_eq!(x.fetch_update(|x| Some(x + 1)), Ok(7));
916 /// assert_eq!(x.fetch_update(|x| Some(x + 1)), Ok(8));
917 /// assert_eq!(x.load(), 9);
918 /// ```
919 #[inline]
920 pub fn fetch_update<F>(&self, f: F) -> Result<$int_type, $int_type>
921 where F: FnMut($int_type) -> Option<$int_type> {
922 self.0.fetch_update(Ordering::SeqCst, Ordering::SeqCst, f)
923 }
924
925 /// Maximum with the current value.
926 ///
927 /// Finds the maximum of the current value and the argument `val`, and
928 /// sets the new value to the result.
929 ///
930 /// Returns the previous value.
931 ///
932 /// # Examples
933 ///
934 /// ```
935 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
936 ///
937 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
938 /// assert_eq!(foo.fetch_max(42), 23);
939 /// assert_eq!(foo.load(), 42);
940 /// ```
941 ///
942 /// If you want to obtain the maximum value in one step, you can use the following:
943 ///
944 /// ```
945 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
946 ///
947 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
948 /// let bar = 42;
949 /// let max_foo = foo.fetch_max(bar).max(bar);
950 /// assert!(max_foo == 42);
951 /// ```
952 #[inline]
953 pub fn fetch_max(&self, val: $int_type) -> $int_type {
954 self.0.fetch_max(val, Ordering::SeqCst)
955 }
956
957 /// Minimum with the current value.
958 ///
959 /// Finds the minimum of the current value and the argument `val`, and
960 /// sets the new value to the result.
961 ///
962 /// Returns the previous value.
963 ///
964 /// # Examples
965 ///
966 /// ```
967 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
968 ///
969 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
970 /// assert_eq!(foo.fetch_min(42d), 23);
971 /// assert_eq!(foo.load(d), 23);
972 /// assert_eq!(foo.fetch_min(22d), 23);
973 /// assert_eq!(foo.load(d), 22);
974 /// ```
975 ///
976 /// If you want to obtain the minimum value in one step, you can use the following:
977 ///
978 /// ```
979 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
980 ///
981 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
982 /// let bar = 12;
983 /// let min_foo = foo.fetch_min(bar).min(bar);
984 /// assert_eq!(min_foo, 12);
985 /// ```
986 #[inline]
987 pub fn fetch_min(&self, val: $int_type) -> $int_type {
988 self.0.fetch_min(val, Ordering::SeqCst)
989 }
990
991 /// Returns a mutable pointer to the underlying integer.
992 ///
993 /// Doing non-atomic reads and writes on the resulting integer can be a data race.
994 /// This method is mostly useful for FFI, where the function signature may use
995 #[doc = concat!("`*mut ", stringify!($int_type), "` instead of `&", stringify!($atomic_type), "`.")]
996 ///
997 /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
998 /// atomic types work with interior mutability. All modifications of an atomic change the value
999 /// through a shared reference, and can do so safely as long as they use atomic operations. Any
1000 /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same
1001 /// restriction: operations on it must be atomic.
1002 ///
1003 /// # Examples
1004 ///
1005 /// ```ignore (extern-declaration)
1006 /// # fn main() {
1007 #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
1008 ///
1009 /// extern "C" {
1010 #[doc = concat!(" fn my_atomic_op(arg: *mut ", stringify!($int_type), ");")]
1011 /// }
1012 ///
1013 #[doc = concat!("let atomic = ", stringify!($atomic_type), "::new(1);")]
1014 ///
1015 /// // SAFETY: Safe as long as `my_atomic_op` is atomic.
1016 /// unsafe {
1017 /// my_atomic_op(atomic.as_ptr());
1018 /// }
1019 /// # }
1020 /// ```
1021 #[inline]
1022 pub const fn as_ptr(&self) -> *mut $int_type {
1023 self.0.as_ptr()
1024 }
1025 }
1026 }
1027}
1028
1029atomic_int! {
1030 "i8",
1031 "",
1032 i8 AtomicI8
1033}
1034atomic_int! {
1035 "u8",
1036 "",
1037 u8 AtomicU8
1038}
1039atomic_int! {
1040 "i16",
1041 "",
1042 i16 AtomicI16
1043}
1044atomic_int! {
1045 "u16",
1046 "",
1047 u16 AtomicU16
1048}
1049atomic_int! {
1050 "i32",
1051 "",
1052 i32 AtomicI32
1053}
1054atomic_int! {
1055 "u32",
1056 "",
1057 u32 AtomicU32
1058}
1059atomic_int! {
1060 "i64",
1061 "",
1062 i64 AtomicI64
1063}
1064atomic_int! {
1065 "u64",
1066 "",
1067 u64 AtomicU64
1068}
1069
1070atomic_int! {
1071 "isize",
1072 "",
1073 isize AtomicIsize
1074}
1075
1076atomic_int! {
1077 "usize",
1078 "",
1079 usize AtomicUsize
1080}