xref: /DragonOS/kernel/src/libs/int_like.rs (revision aa0367d69e15989684109c5b454e85da9ecb1975)
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     };
44 
45     ($new_type_name:ident, $new_atomic_type_name: ident, $backing_type:ident, $backing_atomic_type:ident) => {
46         int_like!($new_type_name, $backing_type);
47 
48         /// A mutable holder for T that can safely be shared among threads.
49         /// Runtime equivalent to using `AtomicUsize`, just type-safer.
50         pub struct $new_atomic_type_name {
51             container: $backing_atomic_type,
52         }
53 
54         impl $new_atomic_type_name {
55             #[allow(dead_code)]
56             pub const fn new(x: $new_type_name) -> Self {
57                 $new_atomic_type_name {
58                     container: $backing_atomic_type::new(x.into()),
59                 }
60             }
61             #[allow(dead_code)]
62             pub const fn default() -> Self {
63                 Self::new($new_type_name::from(0))
64             }
65             #[allow(dead_code)]
66             pub fn load(&self, order: ::core::sync::atomic::Ordering) -> $new_type_name {
67                 $new_type_name::from(self.container.load(order))
68             }
69             #[allow(dead_code)]
70             pub fn store(&self, val: $new_type_name, order: ::core::sync::atomic::Ordering) {
71                 self.container.store(val.into(), order)
72             }
73             #[allow(dead_code)]
74             pub fn swap(
75                 &self,
76                 val: $new_type_name,
77                 order: ::core::sync::atomic::Ordering,
78             ) -> $new_type_name {
79                 $new_type_name::from(self.container.swap(val.into(), order))
80             }
81             #[allow(dead_code)]
82             pub fn compare_exchange(
83                 &self,
84                 current: $new_type_name,
85                 new: $new_type_name,
86                 success: ::core::sync::atomic::Ordering,
87                 failure: ::core::sync::atomic::Ordering,
88             ) -> ::core::result::Result<$new_type_name, $new_type_name> {
89                 match self
90                     .container
91                     .compare_exchange(current.into(), new.into(), success, failure)
92                 {
93                     Ok(result) => Ok($new_type_name::from(result)),
94                     Err(result) => Err($new_type_name::from(result)),
95                 }
96             }
97             #[allow(dead_code)]
98             pub fn compare_exchange_weak(
99                 &self,
100                 current: $new_type_name,
101                 new: $new_type_name,
102                 success: ::core::sync::atomic::Ordering,
103                 failure: ::core::sync::atomic::Ordering,
104             ) -> ::core::result::Result<$new_type_name, $new_type_name> {
105                 match self.container.compare_exchange_weak(
106                     current.into(),
107                     new.into(),
108                     success,
109                     failure,
110                 ) {
111                     Ok(result) => Ok($new_type_name::from(result)),
112                     Err(result) => Err($new_type_name::from(result)),
113                 }
114             }
115         }
116     };
117 }
118 
119 #[test]
120 fn test() {
121     use ::core::sync::atomic::AtomicUsize;
122     use core::mem::size_of;
123 
124     // Generate type `usize_like`.
125     int_like!(UsizeLike, usize);
126     assert_eq!(size_of::<UsizeLike>(), size_of::<usize>());
127 
128     // Generate types `usize_like` and `AtomicUsize`.
129     int_like!(UsizeLike2, AtomicUsizeLike, usize, AtomicUsize);
130     assert_eq!(size_of::<UsizeLike2>(), size_of::<usize>());
131     assert_eq!(size_of::<AtomicUsizeLike>(), size_of::<AtomicUsize>());
132 }
133