1use std::{fmt, u32};
24use std::marker::PhantomData;
25
26#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq)]
27#[cfg_attr(feature = "capture", derive(Serialize))]
28#[cfg_attr(feature = "replay", derive(Deserialize))]
29struct Epoch(u32);
30
31impl Epoch {
32 fn new() -> Self {
36 Epoch(1)
37 }
38
39 fn invalid() -> Self {
41 Epoch(0)
42 }
43}
44
45#[cfg_attr(feature = "capture", derive(Serialize))]
46#[cfg_attr(feature = "replay", derive(Deserialize))]
47#[derive(MallocSizeOf)]
48pub struct FreeListHandle<M> {
49 index: u32,
50 epoch: Epoch,
51 _marker: PhantomData<M>,
52}
53
54impl<M> fmt::Debug for FreeListHandle<M> {
56 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57 f.debug_struct("StrongHandle")
58 .field("index", &self.index)
59 .field("epoch", &self.epoch.0)
60 .finish()
61 }
62}
63
64impl<M> FreeListHandle<M> {
65 pub fn weak(&self) -> WeakFreeListHandle<M> {
66 WeakFreeListHandle {
67 index: self.index,
68 epoch: self.epoch,
69 _marker: PhantomData,
70 }
71 }
72
73 pub fn invalid() -> Self {
74 Self {
75 index: 0,
76 epoch: Epoch::invalid(),
77 _marker: PhantomData,
78 }
79 }
80
81 pub fn matches(&self, weak_handle: &WeakFreeListHandle<M>) -> bool {
84 self.index == weak_handle.index &&
85 self.epoch == weak_handle.epoch
86 }
87}
88
89impl<M> Clone for WeakFreeListHandle<M> {
90 fn clone(&self) -> Self {
91 WeakFreeListHandle {
92 index: self.index,
93 epoch: self.epoch,
94 _marker: PhantomData,
95 }
96 }
97}
98
99impl<M> PartialEq for WeakFreeListHandle<M> {
100 fn eq(&self, other: &Self) -> bool {
101 self.index == other.index && self.epoch == other.epoch
102 }
103}
104
105#[cfg_attr(feature = "capture", derive(Serialize))]
106#[cfg_attr(feature = "replay", derive(Deserialize))]
107#[derive(MallocSizeOf)]
108pub struct WeakFreeListHandle<M> {
109 index: u32,
110 epoch: Epoch,
111 _marker: PhantomData<M>,
112}
113
114impl<M> fmt::Debug for WeakFreeListHandle<M> {
116 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
117 f.debug_struct("WeakHandle")
118 .field("index", &self.index)
119 .field("epoch", &self.epoch.0)
120 .finish()
121 }
122}
123
124impl<M> WeakFreeListHandle<M> {
125 pub fn invalid() -> Self {
127 Self {
128 index: 0,
129 epoch: Epoch::invalid(),
130 _marker: PhantomData,
131 }
132 }
133}
134
135#[derive(Debug, MallocSizeOf)]
136#[cfg_attr(feature = "capture", derive(Serialize))]
137#[cfg_attr(feature = "replay", derive(Deserialize))]
138struct Slot<T> {
139 next: Option<u32>,
140 epoch: Epoch,
141 value: Option<T>,
142}
143
144#[derive(Debug, MallocSizeOf)]
145#[cfg_attr(feature = "capture", derive(Serialize))]
146#[cfg_attr(feature = "replay", derive(Deserialize))]
147pub struct FreeList<T, M> {
148 slots: Vec<Slot<T>>,
149 free_list_head: Option<u32>,
150 active_count: usize,
151 _marker: PhantomData<M>,
152}
153
154impl<T, M> FreeList<T, M> {
155 pub fn new() -> Self {
159 let first_slot = Slot {
163 next: None,
164 epoch: Epoch::new(),
165 value: None,
166 };
167 FreeList {
168 slots: vec![first_slot],
169 free_list_head: Some(0),
170 active_count: 0,
171 _marker: PhantomData,
172 }
173 }
174
175 pub fn clear(&mut self) {
176 self.slots.truncate(1);
177 self.slots[0] = Slot {
178 next: None,
179 epoch: Epoch::new(),
180 value: None,
181 };
182 self.free_list_head = Some(0);
183 self.active_count = 0;
184 }
185
186 #[allow(dead_code)]
187 pub fn get(&self, id: &FreeListHandle<M>) -> &T {
188 self.slots[id.index as usize].value.as_ref().unwrap()
189 }
190
191 #[allow(dead_code)]
192 pub fn get_mut(&mut self, id: &FreeListHandle<M>) -> &mut T {
193 self.slots[id.index as usize].value.as_mut().unwrap()
194 }
195
196 pub fn get_opt(&self, id: &WeakFreeListHandle<M>) -> Option<&T> {
197 let slot = &self.slots[id.index as usize];
198 if slot.epoch == id.epoch {
199 slot.value.as_ref()
200 } else {
201 None
202 }
203 }
204
205 pub fn get_opt_mut(&mut self, id: &WeakFreeListHandle<M>) -> Option<&mut T> {
206 let slot = &mut self.slots[id.index as usize];
207 if slot.epoch == id.epoch {
208 slot.value.as_mut()
209 } else {
210 None
211 }
212 }
213
214 pub fn insert(&mut self, item: T) -> FreeListHandle<M> {
215 self.active_count += 1;
216
217 match self.free_list_head {
218 Some(free_index) => {
219 let slot = &mut self.slots[free_index as usize];
220
221 self.free_list_head = slot.next;
223 slot.next = None;
224 slot.value = Some(item);
225
226 FreeListHandle {
227 index: free_index,
228 epoch: slot.epoch,
229 _marker: PhantomData,
230 }
231 }
232 None => {
233 let index = self.slots.len() as u32;
234 let epoch = Epoch::new();
235
236 self.slots.push(Slot {
237 next: None,
238 epoch,
239 value: Some(item),
240 });
241
242 FreeListHandle {
243 index,
244 epoch,
245 _marker: PhantomData,
246 }
247 }
248 }
249 }
250
251 pub fn free(&mut self, id: FreeListHandle<M>) -> T {
252 self.active_count -= 1;
253 let slot = &mut self.slots[id.index as usize];
254 slot.next = self.free_list_head;
255 slot.epoch = Epoch(slot.epoch.0 + 1);
256 self.free_list_head = Some(id.index);
257 slot.value.take().unwrap()
258 }
259
260 #[allow(dead_code)]
261 pub fn len(&self) -> usize {
262 self.active_count
263 }
264}