@@ -15,8 +15,16 @@ use serde::{Deserialize, Serialize};
15
15
pub ( super ) struct Store < T = Entry > {
16
16
/// Stored state for all objects.
17
17
entries : Vec < T > ,
18
+
19
+ /// A unique id for this store, used to track references
20
+ id : StoreId ,
18
21
}
19
22
23
+
24
+ #[ derive( Debug , Eq , PartialEq , Hash , Clone , Copy ) ]
25
+ pub ( super ) struct StoreId ( usize ) ;
26
+
27
+
20
28
pub ( super ) trait Object : Sized {
21
29
type Entry ;
22
30
@@ -40,6 +48,10 @@ pub(super) struct Ref<T = ()> {
40
48
/// Index in the store
41
49
index : usize ,
42
50
51
+ /// Id of the store that created this reference. Optional, since `Ref`s can also be created from
52
+ /// a bare `usize` index
53
+ store_id : StoreId ,
54
+
43
55
_p : PhantomData < T > ,
44
56
}
45
57
@@ -147,6 +159,7 @@ impl<T> Store<T> {
147
159
pub ( super ) fn with_capacity ( capacity : usize ) -> Store < T > {
148
160
Store {
149
161
entries : Vec :: with_capacity ( capacity) ,
162
+ id : StoreId :: new ( ) ,
150
163
}
151
164
}
152
165
@@ -162,6 +175,10 @@ impl<T> Store<T> {
162
175
self . entries . reserve_exact ( additional) ;
163
176
}
164
177
178
+ pub ( super ) fn get_id ( & self ) -> StoreId {
179
+ self . id
180
+ }
181
+
165
182
/// Insert an object into the store
166
183
pub ( super ) fn insert < O > ( & mut self , item : O ) -> Ref < O >
167
184
where
@@ -172,6 +189,7 @@ impl<T> Store<T> {
172
189
173
190
Ref {
174
191
index,
192
+ store_id : self . id ,
175
193
_p : PhantomData ,
176
194
}
177
195
}
@@ -183,25 +201,29 @@ impl<T> Store<T> {
183
201
184
202
pub ( crate ) fn clear ( & mut self ) {
185
203
self . entries . clear ( ) ;
204
+ self . id = StoreId :: new ( ) ;
186
205
}
187
206
188
207
pub ( super ) fn iter_ref < O > ( & self ) -> impl DoubleEndedIterator < Item = Ref < O > > + ' _
189
208
where
190
209
O : Object < Entry = T > ,
191
210
{
211
+ let store_id = self . id ;
212
+
192
213
self . entries
193
214
. iter ( )
194
215
. enumerate ( )
195
216
. filter ( |( _, e) | O :: get_ref ( e) . is_some ( ) )
196
- . map ( |( index, _) | Ref {
217
+ . map ( move |( index, _) | Ref {
197
218
index,
219
+ store_id,
198
220
_p : PhantomData ,
199
221
} )
200
222
}
201
223
202
- pub ( super ) fn iter_mut < ' a , O > ( & ' a mut self ) -> impl DoubleEndedIterator < Item = & mut O >
203
- where
204
- O : Object < Entry = T > + ' a ,
224
+ pub ( super ) fn iter_mut < ' a , O > ( & ' a mut self ) -> impl DoubleEndedIterator < Item = & mut O >
225
+ where
226
+ O : Object < Entry = T > + ' a ,
205
227
{
206
228
self . entries . iter_mut ( ) . filter_map ( O :: get_mut)
207
229
}
@@ -259,11 +281,27 @@ impl Store {
259
281
}
260
282
}
261
283
284
+ impl StoreId {
285
+ pub ( crate ) fn new ( ) -> StoreId {
286
+ use std:: sync:: atomic:: AtomicUsize ;
287
+ use std:: sync:: atomic:: Ordering :: Relaxed ;
288
+
289
+ // The number picked here is arbitrary. It is mostly to avoid collision
290
+ // with "zero" to aid with debugging.
291
+ static NEXT_ID : AtomicUsize = AtomicUsize :: new ( 41_123_456 ) ;
292
+
293
+ let next = NEXT_ID . fetch_add ( 1 , Relaxed ) ;
294
+
295
+ StoreId ( next)
296
+ }
297
+ }
298
+
262
299
impl < T > Ref < T > {
263
300
/// Erase the type marker
264
301
pub ( super ) fn erase ( self ) -> Ref < ( ) > {
265
302
Ref {
266
303
index : self . index ,
304
+ store_id : self . store_id ,
267
305
_p : PhantomData ,
268
306
}
269
307
}
@@ -274,25 +312,38 @@ impl<T> Ref<T> {
274
312
}
275
313
276
314
impl < T : Object > Ref < T > {
315
+ /// Panic if the reference belongs to a different store
316
+ fn assert_store_id ( self , store : & Store < T :: Entry > ) {
317
+ assert_eq ! (
318
+ self . store_id,
319
+ store. id,
320
+ "Tried to access an object using a reference that belongs to a different store. \
321
+ This might indicate you are trying to reuse an object from an earlier execution"
322
+ )
323
+ }
324
+
277
325
/// Get a reference to the object associated with this reference from the store
278
326
pub ( super ) fn get ( self , store : & Store < T :: Entry > ) -> & T {
327
+ self . assert_store_id ( & store) ;
279
328
T :: get_ref ( & store. entries [ self . index ] )
280
329
. expect ( "[loom internal bug] unexpected object stored at reference" )
281
330
}
282
331
283
332
/// Get a mutable reference to the object associated with this reference
284
333
/// from the store
285
334
pub ( super ) fn get_mut ( self , store : & mut Store < T :: Entry > ) -> & mut T {
335
+ self . assert_store_id ( & store) ;
286
336
T :: get_mut ( & mut store. entries [ self . index ] )
287
337
. expect ( "[loom internal bug] unexpected object stored at reference" )
288
338
}
289
339
}
290
340
291
341
impl Ref {
292
342
/// Convert a store index `usize` into a ref
293
- pub ( super ) fn from_usize ( index : usize ) -> Ref {
343
+ pub ( super ) fn from_usize ( index : usize , store_id : StoreId ) -> Ref {
294
344
Ref {
295
345
index,
346
+ store_id,
296
347
_p : PhantomData ,
297
348
}
298
349
}
@@ -303,6 +354,7 @@ impl Ref {
303
354
{
304
355
T :: get_ref ( & store. entries [ self . index ] ) . map ( |_| Ref {
305
356
index : self . index ,
357
+ store_id : self . store_id ,
306
358
_p : PhantomData ,
307
359
} )
308
360
}
@@ -312,6 +364,7 @@ impl<T> Clone for Ref<T> {
312
364
fn clone ( & self ) -> Ref < T > {
313
365
Ref {
314
366
index : self . index ,
367
+ store_id : self . store_id ,
315
368
_p : PhantomData ,
316
369
}
317
370
}
0 commit comments