1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use std::fmt::Debug;
use std::iter::{Step, Sum};
use std::sync::atomic::Ordering;
use atoi::FromRadix10;
pub trait Idx:
Copy
+ std::ops::Add<Output = Self>
+ std::ops::AddAssign
+ std::ops::Sub<Output = Self>
+ std::ops::Div<Output = Self>
+ std::ops::Mul<Output = Self>
+ Ord
+ Debug
+ Send
+ Sum
+ Sync
+ Sized
+ Step
+ 'static
{
type Atomic: AtomicIdx<Inner = Self>;
fn new(idx: usize) -> Self;
fn zero() -> Self;
fn index(self) -> usize;
fn atomic(self) -> Self::Atomic;
fn parse(bytes: &[u8]) -> (Self, usize);
}
pub trait AtomicIdx: Send + Sync {
type Inner: Idx<Atomic = Self>;
fn load(&self, order: Ordering) -> Self::Inner;
fn fetch_add(&self, val: Self::Inner, order: Ordering) -> Self::Inner;
fn get_and_increment(&self, order: Ordering) -> Self::Inner;
fn zero() -> Self;
fn into_inner(self) -> Self::Inner;
}
macro_rules! impl_idx {
($TYPE:ty,$ATOMIC_TYPE:ident) => {
use std::sync::atomic::$ATOMIC_TYPE;
impl Idx for $TYPE {
type Atomic = $ATOMIC_TYPE;
#[inline]
fn new(idx: usize) -> Self {
assert!(idx <= <$TYPE>::MAX as usize);
idx as $TYPE
}
#[inline]
fn zero() -> Self {
0
}
#[inline]
fn index(self) -> usize {
self as usize
}
#[inline]
fn atomic(self) -> $ATOMIC_TYPE {
<$ATOMIC_TYPE>::new(self)
}
#[inline]
fn parse(bytes: &[u8]) -> (Self, usize) {
FromRadix10::from_radix_10(bytes)
}
}
impl AtomicIdx for $ATOMIC_TYPE {
type Inner = $TYPE;
#[inline]
fn load(&self, order: Ordering) -> Self::Inner {
self.load(order)
}
#[inline]
fn fetch_add(&self, val: $TYPE, order: Ordering) -> Self::Inner {
self.fetch_add(val, order)
}
#[inline]
fn get_and_increment(&self, order: Ordering) -> Self::Inner {
self.fetch_add(1, order)
}
#[inline]
fn zero() -> Self {
<$ATOMIC_TYPE>::new(0)
}
#[inline]
fn into_inner(self) -> Self::Inner {
self.into_inner()
}
}
};
}
impl_idx!(u8, AtomicU8);
impl_idx!(u16, AtomicU16);
impl_idx!(u32, AtomicU32);
impl_idx!(u64, AtomicU64);
impl_idx!(usize, AtomicUsize);
impl_idx!(i8, AtomicI8);
impl_idx!(i16, AtomicI16);
impl_idx!(i32, AtomicI32);
impl_idx!(i64, AtomicI64);
impl_idx!(isize, AtomicIsize);