|
3 | 3 |
|
4 | 4 | use crate::primitive::sync::atomic::{self, AtomicBool};
|
5 | 5 | use core::cell::UnsafeCell;
|
| 6 | +use core::cmp; |
6 | 7 | use core::fmt;
|
7 | 8 | use core::mem;
|
8 | 9 | use core::sync::atomic::Ordering;
|
@@ -387,6 +388,35 @@ macro_rules! impl_arithmetic {
|
387 | 388 | }
|
388 | 389 | }
|
389 | 390 |
|
| 391 | + /// Applies bitwise "nand" to the current value and returns the previous value. |
| 392 | + /// |
| 393 | + /// # Examples |
| 394 | + /// |
| 395 | + /// ``` |
| 396 | + /// use crossbeam_utils::atomic::AtomicCell; |
| 397 | + /// |
| 398 | + #[doc = $example] |
| 399 | + /// |
| 400 | + /// assert_eq!(a.fetch_nand(3), 7); |
| 401 | + /// assert_eq!(a.load(), !(7 & 3)); |
| 402 | + /// ``` |
| 403 | + #[inline] |
| 404 | + pub fn fetch_nand(&self, val: $t) -> $t { |
| 405 | + #[cfg(crossbeam_loom)] |
| 406 | + { |
| 407 | + let _ = val; |
| 408 | + unimplemented!("loom does not support non-atomic atomic ops"); |
| 409 | + } |
| 410 | + #[cfg(not(crossbeam_loom))] |
| 411 | + { |
| 412 | + let _guard = lock(self.value.get() as usize).write(); |
| 413 | + let value = unsafe { &mut *(self.value.get()) }; |
| 414 | + let old = *value; |
| 415 | + *value = !(old & val); |
| 416 | + old |
| 417 | + } |
| 418 | + } |
| 419 | + |
390 | 420 | /// Applies bitwise "or" to the current value and returns the previous value.
|
391 | 421 | ///
|
392 | 422 | /// # Examples
|
@@ -444,6 +474,66 @@ macro_rules! impl_arithmetic {
|
444 | 474 | old
|
445 | 475 | }
|
446 | 476 | }
|
| 477 | + |
| 478 | + /// Compares and sets the maximum of the current value and `val`, |
| 479 | + /// and returns the previous value. |
| 480 | + /// |
| 481 | + /// # Examples |
| 482 | + /// |
| 483 | + /// ``` |
| 484 | + /// use crossbeam_utils::atomic::AtomicCell; |
| 485 | + /// |
| 486 | + #[doc = $example] |
| 487 | + /// |
| 488 | + /// assert_eq!(a.fetch_max(2), 7); |
| 489 | + /// assert_eq!(a.load(), 7); |
| 490 | + /// ``` |
| 491 | + #[inline] |
| 492 | + pub fn fetch_max(&self, val: $t) -> $t { |
| 493 | + #[cfg(crossbeam_loom)] |
| 494 | + { |
| 495 | + let _ = val; |
| 496 | + unimplemented!("loom does not support non-atomic atomic ops"); |
| 497 | + } |
| 498 | + #[cfg(not(crossbeam_loom))] |
| 499 | + { |
| 500 | + let _guard = lock(self.value.get() as usize).write(); |
| 501 | + let value = unsafe { &mut *(self.value.get()) }; |
| 502 | + let old = *value; |
| 503 | + *value = cmp::max(old, val); |
| 504 | + old |
| 505 | + } |
| 506 | + } |
| 507 | + |
| 508 | + /// Compares and sets the minimum of the current value and `val`, |
| 509 | + /// and returns the previous value. |
| 510 | + /// |
| 511 | + /// # Examples |
| 512 | + /// |
| 513 | + /// ``` |
| 514 | + /// use crossbeam_utils::atomic::AtomicCell; |
| 515 | + /// |
| 516 | + #[doc = $example] |
| 517 | + /// |
| 518 | + /// assert_eq!(a.fetch_min(2), 7); |
| 519 | + /// assert_eq!(a.load(), 2); |
| 520 | + /// ``` |
| 521 | + #[inline] |
| 522 | + pub fn fetch_min(&self, val: $t) -> $t { |
| 523 | + #[cfg(crossbeam_loom)] |
| 524 | + { |
| 525 | + let _ = val; |
| 526 | + unimplemented!("loom does not support non-atomic atomic ops"); |
| 527 | + } |
| 528 | + #[cfg(not(crossbeam_loom))] |
| 529 | + { |
| 530 | + let _guard = lock(self.value.get() as usize).write(); |
| 531 | + let value = unsafe { &mut *(self.value.get()) }; |
| 532 | + let old = *value; |
| 533 | + *value = cmp::min(old, val); |
| 534 | + old |
| 535 | + } |
| 536 | + } |
447 | 537 | }
|
448 | 538 | };
|
449 | 539 | ($t:ty, $atomic:ty, $example:tt) => {
|
@@ -554,6 +644,40 @@ macro_rules! impl_arithmetic {
|
554 | 644 | }
|
555 | 645 | }
|
556 | 646 |
|
| 647 | + /// Applies bitwise "nand" to the current value and returns the previous value. |
| 648 | + /// |
| 649 | + /// # Examples |
| 650 | + /// |
| 651 | + /// ``` |
| 652 | + /// use crossbeam_utils::atomic::AtomicCell; |
| 653 | + /// |
| 654 | + #[doc = $example] |
| 655 | + /// |
| 656 | + /// assert_eq!(a.fetch_nand(3), 7); |
| 657 | + /// assert_eq!(a.load(), !(7 & 3)); |
| 658 | + /// ``` |
| 659 | + #[inline] |
| 660 | + pub fn fetch_nand(&self, val: $t) -> $t { |
| 661 | + if can_transmute::<$t, $atomic>() { |
| 662 | + let a = unsafe { &*(self.value.get() as *const $atomic) }; |
| 663 | + a.fetch_nand(val, Ordering::AcqRel) |
| 664 | + } else { |
| 665 | + #[cfg(crossbeam_loom)] |
| 666 | + { |
| 667 | + let _ = val; |
| 668 | + unimplemented!("loom does not support non-atomic atomic ops"); |
| 669 | + } |
| 670 | + #[cfg(not(crossbeam_loom))] |
| 671 | + { |
| 672 | + let _guard = lock(self.value.get() as usize).write(); |
| 673 | + let value = unsafe { &mut *(self.value.get()) }; |
| 674 | + let old = *value; |
| 675 | + *value = !(old & val); |
| 676 | + old |
| 677 | + } |
| 678 | + } |
| 679 | + } |
| 680 | + |
557 | 681 | /// Applies bitwise "or" to the current value and returns the previous value.
|
558 | 682 | ///
|
559 | 683 | /// # Examples
|
@@ -621,6 +745,76 @@ macro_rules! impl_arithmetic {
|
621 | 745 | }
|
622 | 746 | }
|
623 | 747 | }
|
| 748 | + |
| 749 | + /// Compares and sets the maximum of the current value and `val`, |
| 750 | + /// and returns the previous value. |
| 751 | + /// |
| 752 | + /// # Examples |
| 753 | + /// |
| 754 | + /// ``` |
| 755 | + /// use crossbeam_utils::atomic::AtomicCell; |
| 756 | + /// |
| 757 | + #[doc = $example] |
| 758 | + /// |
| 759 | + /// assert_eq!(a.fetch_max(9), 7); |
| 760 | + /// assert_eq!(a.load(), 9); |
| 761 | + /// ``` |
| 762 | + #[inline] |
| 763 | + pub fn fetch_max(&self, val: $t) -> $t { |
| 764 | + if can_transmute::<$t, $atomic>() { |
| 765 | + // TODO: Atomic*::fetch_max requires Rust 1.45. |
| 766 | + self.fetch_update(|old| Some(cmp::max(old, val))).unwrap() |
| 767 | + } else { |
| 768 | + #[cfg(crossbeam_loom)] |
| 769 | + { |
| 770 | + let _ = val; |
| 771 | + unimplemented!("loom does not support non-atomic atomic ops"); |
| 772 | + } |
| 773 | + #[cfg(not(crossbeam_loom))] |
| 774 | + { |
| 775 | + let _guard = lock(self.value.get() as usize).write(); |
| 776 | + let value = unsafe { &mut *(self.value.get()) }; |
| 777 | + let old = *value; |
| 778 | + *value = cmp::max(old, val); |
| 779 | + old |
| 780 | + } |
| 781 | + } |
| 782 | + } |
| 783 | + |
| 784 | + /// Compares and sets the minimum of the current value and `val`, |
| 785 | + /// and returns the previous value. |
| 786 | + /// |
| 787 | + /// # Examples |
| 788 | + /// |
| 789 | + /// ``` |
| 790 | + /// use crossbeam_utils::atomic::AtomicCell; |
| 791 | + /// |
| 792 | + #[doc = $example] |
| 793 | + /// |
| 794 | + /// assert_eq!(a.fetch_min(2), 7); |
| 795 | + /// assert_eq!(a.load(), 2); |
| 796 | + /// ``` |
| 797 | + #[inline] |
| 798 | + pub fn fetch_min(&self, val: $t) -> $t { |
| 799 | + if can_transmute::<$t, $atomic>() { |
| 800 | + // TODO: Atomic*::fetch_min requires Rust 1.45. |
| 801 | + self.fetch_update(|old| Some(cmp::min(old, val))).unwrap() |
| 802 | + } else { |
| 803 | + #[cfg(crossbeam_loom)] |
| 804 | + { |
| 805 | + let _ = val; |
| 806 | + unimplemented!("loom does not support non-atomic atomic ops"); |
| 807 | + } |
| 808 | + #[cfg(not(crossbeam_loom))] |
| 809 | + { |
| 810 | + let _guard = lock(self.value.get() as usize).write(); |
| 811 | + let value = unsafe { &mut *(self.value.get()) }; |
| 812 | + let old = *value; |
| 813 | + *value = cmp::min(old, val); |
| 814 | + old |
| 815 | + } |
| 816 | + } |
| 817 | + } |
624 | 818 | }
|
625 | 819 | };
|
626 | 820 | }
|
@@ -678,6 +872,30 @@ impl AtomicCell<bool> {
|
678 | 872 | a.fetch_and(val, Ordering::AcqRel)
|
679 | 873 | }
|
680 | 874 |
|
| 875 | + /// Applies logical "nand" to the current value and returns the previous value. |
| 876 | + /// |
| 877 | + /// # Examples |
| 878 | + /// |
| 879 | + /// ``` |
| 880 | + /// use crossbeam_utils::atomic::AtomicCell; |
| 881 | + /// |
| 882 | + /// let a = AtomicCell::new(true); |
| 883 | + /// |
| 884 | + /// assert_eq!(a.fetch_nand(false), true); |
| 885 | + /// assert_eq!(a.load(), true); |
| 886 | + /// |
| 887 | + /// assert_eq!(a.fetch_nand(true), true); |
| 888 | + /// assert_eq!(a.load(), false); |
| 889 | + /// |
| 890 | + /// assert_eq!(a.fetch_nand(false), false); |
| 891 | + /// assert_eq!(a.load(), true); |
| 892 | + /// ``` |
| 893 | + #[inline] |
| 894 | + pub fn fetch_nand(&self, val: bool) -> bool { |
| 895 | + let a = unsafe { &*(self.value.get() as *const AtomicBool) }; |
| 896 | + a.fetch_nand(val, Ordering::AcqRel) |
| 897 | + } |
| 898 | + |
681 | 899 | /// Applies logical "or" to the current value and returns the previous value.
|
682 | 900 | ///
|
683 | 901 | /// # Examples
|
|
0 commit comments