1 //! These code are bring from redox-os, and I think it's a good idea to use it in our project. 2 //! 3 //! Helpers used to define types that are backed by integers (typically `usize`), 4 //! without compromising safety. 5 //! 6 //! # Example 7 //! 8 //! ``` 9 //! /// Define an opaque type `Pid` backed by a `usize`. 10 //! int_like!(Pid, usize); 11 //! 12 //! const ZERO: Pid = Pid::from(0); 13 //! ``` 14 //! 15 //! # Example 16 //! 17 //! ``` 18 //! /// Define opaque types `Pid` and `AtomicPid`, backed respectively by a `usize` 19 //! /// and a `AtomicUsize`. 20 //! 21 //! int_like!(Pid, AtomicPid, usize, AtomicUsize); 22 //! 23 //! const ZERO: Pid = Pid::from(0); 24 //! let ATOMIC_PID: AtomicPid = AtomicPid::default(); 25 //! ``` 26 27 #[macro_export] 28 macro_rules! int_like { 29 ($new_type_name:ident, $backing_type: ident) => { 30 #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)] 31 pub struct $new_type_name($backing_type); 32 33 impl $new_type_name { 34 #[allow(dead_code)] 35 pub const fn into(self) -> $backing_type { 36 self.0 37 } 38 #[allow(dead_code)] 39 pub const fn from(x: $backing_type) -> Self { 40 $new_type_name(x) 41 } 42 43 #[allow(dead_code)] 44 pub const fn new(x: $backing_type) -> Self { 45 Self::from(x) 46 } 47 } 48 }; 49 50 ($new_type_name:ident, $new_atomic_type_name: ident, $backing_type:ident, $backing_atomic_type:ident) => { 51 int_like!($new_type_name, $backing_type); 52 53 /// A mutable holder for T that can safely be shared among threads. 54 /// Runtime equivalent to using `AtomicUsize`, just type-safer. 55 #[derive(Debug)] 56 pub struct $new_atomic_type_name { 57 container: $backing_atomic_type, 58 } 59 60 impl $new_atomic_type_name { 61 #[allow(dead_code)] 62 pub const fn new(x: $new_type_name) -> Self { 63 $new_atomic_type_name { 64 container: $backing_atomic_type::new(x.into()), 65 } 66 } 67 #[allow(dead_code)] 68 pub const fn default() -> Self { 69 Self::new($new_type_name::from(0)) 70 } 71 #[allow(dead_code)] 72 pub fn load(&self, order: ::core::sync::atomic::Ordering) -> $new_type_name { 73 $new_type_name::from(self.container.load(order)) 74 } 75 #[allow(dead_code)] 76 pub fn store(&self, val: $new_type_name, order: ::core::sync::atomic::Ordering) { 77 self.container.store(val.into(), order) 78 } 79 #[allow(dead_code)] 80 pub fn swap( 81 &self, 82 val: $new_type_name, 83 order: ::core::sync::atomic::Ordering, 84 ) -> $new_type_name { 85 $new_type_name::from(self.container.swap(val.into(), order)) 86 } 87 #[allow(dead_code)] 88 pub fn compare_exchange( 89 &self, 90 current: $new_type_name, 91 new: $new_type_name, 92 success: ::core::sync::atomic::Ordering, 93 failure: ::core::sync::atomic::Ordering, 94 ) -> ::core::result::Result<$new_type_name, $new_type_name> { 95 match self 96 .container 97 .compare_exchange(current.into(), new.into(), success, failure) 98 { 99 Ok(result) => Ok($new_type_name::from(result)), 100 Err(result) => Err($new_type_name::from(result)), 101 } 102 } 103 #[allow(dead_code)] 104 pub fn compare_exchange_weak( 105 &self, 106 current: $new_type_name, 107 new: $new_type_name, 108 success: ::core::sync::atomic::Ordering, 109 failure: ::core::sync::atomic::Ordering, 110 ) -> ::core::result::Result<$new_type_name, $new_type_name> { 111 match self.container.compare_exchange_weak( 112 current.into(), 113 new.into(), 114 success, 115 failure, 116 ) { 117 Ok(result) => Ok($new_type_name::from(result)), 118 Err(result) => Err($new_type_name::from(result)), 119 } 120 } 121 #[allow(dead_code)] 122 pub fn fetch_add( 123 &self, 124 val: $new_type_name, 125 order: ::core::sync::atomic::Ordering, 126 ) -> $new_type_name { 127 $new_type_name::from(self.container.fetch_add(val.into(), order)) 128 } 129 } 130 }; 131 } 132 133 #[test] 134 fn test() { 135 use ::core::sync::atomic::AtomicUsize; 136 use core::mem::size_of; 137 138 // Generate type `usize_like`. 139 int_like!(UsizeLike, usize); 140 assert_eq!(size_of::<UsizeLike>(), size_of::<usize>()); 141 142 // Generate types `usize_like` and `AtomicUsize`. 143 int_like!(UsizeLike2, AtomicUsizeLike, usize, AtomicUsize); 144 assert_eq!(size_of::<UsizeLike2>(), size_of::<usize>()); 145 assert_eq!(size_of::<AtomicUsizeLike>(), size_of::<AtomicUsize>()); 146 } 147