• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use super::util::*;
2 use crate::sync::alloc;
3 use crate::Slab;
4 use loom::sync::{Condvar, Mutex};
5 use loom::thread;
6 use std::sync::{
7     atomic::{AtomicBool, Ordering},
8     Arc,
9 };
10 
11 #[test]
take_local()12 fn take_local() {
13     run_model("take_local", || {
14         let slab = Arc::new(Slab::new());
15 
16         let s = slab.clone();
17         let t1 = thread::spawn(move || {
18             let idx = s.insert(1).expect("insert");
19             assert_eq!(s.get(idx).unwrap(), 1);
20             assert_eq!(s.take(idx), Some(1));
21             assert!(s.get(idx).is_none());
22             let idx = s.insert(2).expect("insert");
23             assert_eq!(s.get(idx).unwrap(), 2);
24             assert_eq!(s.take(idx), Some(2));
25             assert!(s.get(idx).is_none());
26         });
27 
28         let s = slab.clone();
29         let t2 = thread::spawn(move || {
30             let idx = s.insert(3).expect("insert");
31             assert_eq!(s.get(idx).unwrap(), 3);
32             assert_eq!(s.take(idx), Some(3));
33             assert!(s.get(idx).is_none());
34             let idx = s.insert(4).expect("insert");
35             assert_eq!(s.get(idx).unwrap(), 4);
36             assert_eq!(s.take(idx), Some(4));
37             assert!(s.get(idx).is_none());
38         });
39 
40         let s = slab;
41         let idx1 = s.insert(5).expect("insert");
42         assert_eq!(s.get(idx1).unwrap(), 5);
43         let idx2 = s.insert(6).expect("insert");
44         assert_eq!(s.get(idx2).unwrap(), 6);
45         assert_eq!(s.take(idx1), Some(5));
46         assert!(s.get(idx1).is_none());
47         assert_eq!(s.get(idx2).unwrap(), 6);
48         assert_eq!(s.take(idx2), Some(6));
49         assert!(s.get(idx2).is_none());
50 
51         t1.join().expect("thread 1 should not panic");
52         t2.join().expect("thread 2 should not panic");
53     });
54 }
55 
56 #[test]
take_remote()57 fn take_remote() {
58     run_model("take_remote", || {
59         let slab = Arc::new(Slab::new());
60 
61         let idx1 = slab.insert(1).expect("insert");
62         assert_eq!(slab.get(idx1).unwrap(), 1);
63         let idx2 = slab.insert(2).expect("insert");
64         assert_eq!(slab.get(idx2).unwrap(), 2);
65 
66         let idx3 = slab.insert(3).expect("insert");
67         assert_eq!(slab.get(idx3).unwrap(), 3);
68 
69         let s = slab.clone();
70         let t1 = thread::spawn(move || {
71             assert_eq!(s.get(idx2).unwrap(), 2);
72             assert_eq!(s.take(idx2), Some(2));
73         });
74 
75         let s = slab.clone();
76         let t2 = thread::spawn(move || {
77             assert_eq!(s.get(idx3).unwrap(), 3);
78             assert_eq!(s.take(idx3), Some(3));
79         });
80 
81         t1.join().expect("thread 1 should not panic");
82         t2.join().expect("thread 2 should not panic");
83 
84         assert_eq!(slab.get(idx1).unwrap(), 1);
85         assert!(slab.get(idx2).is_none());
86         assert!(slab.get(idx3).is_none());
87     });
88 }
89 
90 #[test]
racy_take()91 fn racy_take() {
92     run_model("racy_take", || {
93         let slab = Arc::new(Slab::new());
94 
95         let idx = slab.insert(1).expect("insert");
96         assert_eq!(slab.get(idx).unwrap(), 1);
97 
98         let s1 = slab.clone();
99         let s2 = slab.clone();
100 
101         let t1 = thread::spawn(move || s1.take(idx));
102         let t2 = thread::spawn(move || s2.take(idx));
103 
104         let r1 = t1.join().expect("thread 1 should not panic");
105         let r2 = t2.join().expect("thread 2 should not panic");
106 
107         assert!(
108             r1.is_none() || r2.is_none(),
109             "both threads should not have removed the value"
110         );
111         assert_eq!(
112             r1.or(r2),
113             Some(1),
114             "one thread should have removed the value"
115         );
116         assert!(slab.get(idx).is_none());
117     });
118 }
119 
120 #[test]
racy_take_local()121 fn racy_take_local() {
122     run_model("racy_take_local", || {
123         let slab = Arc::new(Slab::new());
124 
125         let idx = slab.insert(1).expect("insert");
126         assert_eq!(slab.get(idx).unwrap(), 1);
127 
128         let s = slab.clone();
129         let t2 = thread::spawn(move || s.take(idx));
130         let r1 = slab.take(idx);
131         let r2 = t2.join().expect("thread 2 should not panic");
132 
133         assert!(
134             r1.is_none() || r2.is_none(),
135             "both threads should not have removed the value"
136         );
137         assert!(
138             r1.or(r2).is_some(),
139             "one thread should have removed the value"
140         );
141         assert!(slab.get(idx).is_none());
142     });
143 }
144 
145 #[test]
concurrent_insert_take()146 fn concurrent_insert_take() {
147     run_model("concurrent_insert_remove", || {
148         let slab = Arc::new(Slab::new());
149         let pair = Arc::new((Mutex::new(None), Condvar::new()));
150 
151         let slab2 = slab.clone();
152         let pair2 = pair.clone();
153         let remover = thread::spawn(move || {
154             let (lock, cvar) = &*pair2;
155             for i in 0..2 {
156                 test_println!("--- remover i={} ---", i);
157                 let mut next = lock.lock().unwrap();
158                 while next.is_none() {
159                     next = cvar.wait(next).unwrap();
160                 }
161                 let key = next.take().unwrap();
162                 assert_eq!(slab2.take(key), Some(i));
163                 cvar.notify_one();
164             }
165         });
166 
167         let (lock, cvar) = &*pair;
168         for i in 0..2 {
169             test_println!("--- inserter i={} ---", i);
170             let key = slab.insert(i).expect("insert");
171 
172             let mut next = lock.lock().unwrap();
173             *next = Some(key);
174             cvar.notify_one();
175 
176             // Wait for the item to be removed.
177             while next.is_some() {
178                 next = cvar.wait(next).unwrap();
179             }
180 
181             assert!(slab.get(key).is_none());
182         }
183 
184         remover.join().unwrap();
185     })
186 }
187 
188 #[test]
take_remote_and_reuse()189 fn take_remote_and_reuse() {
190     run_model("take_remote_and_reuse", || {
191         let slab = Arc::new(Slab::new_with_config::<TinyConfig>());
192 
193         let idx1 = slab.insert(1).expect("insert");
194         let idx2 = slab.insert(2).expect("insert");
195         let idx3 = slab.insert(3).expect("insert");
196         let idx4 = slab.insert(4).expect("insert");
197 
198         assert_eq!(slab.get(idx1).unwrap(), 1, "slab: {:#?}", slab);
199         assert_eq!(slab.get(idx2).unwrap(), 2, "slab: {:#?}", slab);
200         assert_eq!(slab.get(idx3).unwrap(), 3, "slab: {:#?}", slab);
201         assert_eq!(slab.get(idx4).unwrap(), 4, "slab: {:#?}", slab);
202 
203         let s = slab.clone();
204         let t1 = thread::spawn(move || {
205             assert_eq!(s.take(idx1), Some(1), "slab: {:#?}", s);
206         });
207 
208         let idx1 = slab.insert(5).expect("insert");
209         t1.join().expect("thread 1 should not panic");
210 
211         assert_eq!(slab.get(idx1).unwrap(), 5, "slab: {:#?}", slab);
212         assert_eq!(slab.get(idx2).unwrap(), 2, "slab: {:#?}", slab);
213         assert_eq!(slab.get(idx3).unwrap(), 3, "slab: {:#?}", slab);
214         assert_eq!(slab.get(idx4).unwrap(), 4, "slab: {:#?}", slab);
215     });
216 }
217 
store_when_free<C: crate::Config>(slab: &Arc<Slab<usize, C>>, t: usize) -> usize218 fn store_when_free<C: crate::Config>(slab: &Arc<Slab<usize, C>>, t: usize) -> usize {
219     loop {
220         test_println!("try store {:?}", t);
221         if let Some(key) = slab.insert(t) {
222             test_println!("inserted at {:#x}", key);
223             return key;
224         }
225         test_println!("retrying; slab is full...");
226         thread::yield_now();
227     }
228 }
229 
230 struct TinierConfig;
231 
232 impl crate::Config for TinierConfig {
233     const INITIAL_PAGE_SIZE: usize = 2;
234     const MAX_PAGES: usize = 1;
235 }
236 
237 #[test]
concurrent_remove_remote_and_reuse()238 fn concurrent_remove_remote_and_reuse() {
239     let mut model = loom::model::Builder::new();
240     model.max_branches = 100000;
241     run_builder("concurrent_remove_remote_and_reuse", model, || {
242         let slab = Arc::new(Slab::new_with_config::<TinierConfig>());
243 
244         let idx1 = slab.insert(1).unwrap();
245         let idx2 = slab.insert(2).unwrap();
246 
247         assert_eq!(slab.get(idx1).unwrap(), 1, "slab: {:#?}", slab);
248         assert_eq!(slab.get(idx2).unwrap(), 2, "slab: {:#?}", slab);
249 
250         let s = slab.clone();
251         let s2 = slab.clone();
252 
253         let t1 = thread::spawn(move || {
254             s.take(idx1).expect("must remove");
255         });
256 
257         let t2 = thread::spawn(move || {
258             s2.take(idx2).expect("must remove");
259         });
260 
261         let idx3 = store_when_free(&slab, 3);
262         t1.join().expect("thread 1 should not panic");
263         t2.join().expect("thread 1 should not panic");
264 
265         assert!(slab.get(idx1).is_none(), "slab: {:#?}", slab);
266         assert!(slab.get(idx2).is_none(), "slab: {:#?}", slab);
267         assert_eq!(slab.get(idx3).unwrap(), 3, "slab: {:#?}", slab);
268     });
269 }
270 
271 struct SetDropped {
272     val: usize,
273     dropped: std::sync::Arc<AtomicBool>,
274 }
275 
276 struct AssertDropped {
277     dropped: std::sync::Arc<AtomicBool>,
278 }
279 
280 impl AssertDropped {
new(val: usize) -> (Self, SetDropped)281     fn new(val: usize) -> (Self, SetDropped) {
282         let dropped = std::sync::Arc::new(AtomicBool::new(false));
283         let val = SetDropped {
284             val,
285             dropped: dropped.clone(),
286         };
287         (Self { dropped }, val)
288     }
289 
assert_dropped(&self)290     fn assert_dropped(&self) {
291         assert!(
292             self.dropped.load(Ordering::SeqCst),
293             "value should have been dropped!"
294         );
295     }
296 }
297 
298 impl Drop for SetDropped {
drop(&mut self)299     fn drop(&mut self) {
300         self.dropped.store(true, Ordering::SeqCst);
301     }
302 }
303 
304 #[test]
remove_local()305 fn remove_local() {
306     run_model("remove_local", || {
307         let slab = Arc::new(Slab::new_with_config::<TinyConfig>());
308         let slab2 = slab.clone();
309 
310         let (dropped, item) = AssertDropped::new(1);
311         let idx = slab.insert(item).expect("insert");
312 
313         let guard = slab.get(idx).unwrap();
314 
315         assert!(slab.remove(idx));
316 
317         let t1 = thread::spawn(move || {
318             let g = slab2.get(idx);
319             drop(g);
320         });
321 
322         assert!(slab.get(idx).is_none());
323 
324         t1.join().expect("thread 1 should not panic");
325 
326         drop(guard);
327         assert!(slab.get(idx).is_none());
328         dropped.assert_dropped();
329     })
330 }
331 
332 #[test]
remove_remote()333 fn remove_remote() {
334     run_model("remove_remote", || {
335         let slab = Arc::new(Slab::new_with_config::<TinyConfig>());
336         let slab2 = slab.clone();
337 
338         let (dropped, item) = AssertDropped::new(1);
339         let idx = slab.insert(item).expect("insert");
340 
341         assert!(slab.remove(idx));
342         let t1 = thread::spawn(move || {
343             let g = slab2.get(idx);
344             drop(g);
345         });
346 
347         t1.join().expect("thread 1 should not panic");
348 
349         assert!(slab.get(idx).is_none());
350         dropped.assert_dropped();
351     });
352 }
353 
354 #[test]
remove_remote_during_insert()355 fn remove_remote_during_insert() {
356     run_model("remove_remote_during_insert", || {
357         let slab = Arc::new(Slab::new_with_config::<TinyConfig>());
358         let slab2 = slab.clone();
359 
360         let (dropped, item) = AssertDropped::new(1);
361         let idx = slab.insert(item).expect("insert");
362 
363         let t1 = thread::spawn(move || {
364             let g = slab2.get(idx);
365             assert_ne!(g.as_ref().map(|v| v.val), Some(2));
366             drop(g);
367         });
368 
369         let (_, item) = AssertDropped::new(2);
370         assert!(slab.remove(idx));
371         let idx2 = slab.insert(item).expect("insert");
372 
373         t1.join().expect("thread 1 should not panic");
374 
375         assert!(slab.get(idx).is_none());
376         assert!(slab.get(idx2).is_some());
377         dropped.assert_dropped();
378     });
379 }
380 
381 #[test]
unique_iter()382 fn unique_iter() {
383     run_model("unique_iter", || {
384         let mut slab = Arc::new(Slab::new());
385 
386         let s = slab.clone();
387         let t1 = thread::spawn(move || {
388             s.insert(1).expect("insert");
389             s.insert(2).expect("insert");
390         });
391 
392         let s = slab.clone();
393         let t2 = thread::spawn(move || {
394             s.insert(3).expect("insert");
395             s.insert(4).expect("insert");
396         });
397 
398         t1.join().expect("thread 1 should not panic");
399         t2.join().expect("thread 2 should not panic");
400 
401         let slab = Arc::get_mut(&mut slab).expect("other arcs should be dropped");
402         let items: Vec<_> = slab.unique_iter().map(|&i| i).collect();
403         assert!(items.contains(&1), "items: {:?}", items);
404         assert!(items.contains(&2), "items: {:?}", items);
405         assert!(items.contains(&3), "items: {:?}", items);
406         assert!(items.contains(&4), "items: {:?}", items);
407     });
408 }
409 
410 #[test]
custom_page_sz()411 fn custom_page_sz() {
412     let mut model = loom::model::Builder::new();
413     model.max_branches = 100000;
414     model.check(|| {
415         let slab = Slab::<usize>::new_with_config::<TinyConfig>();
416 
417         for i in 0..1024usize {
418             test_println!("{}", i);
419             let k = slab.insert(i).expect("insert");
420             let v = slab.get(k).expect("get");
421             assert_eq!(v, i, "slab: {:#?}", slab);
422         }
423     });
424 }
425 
426 #[test]
max_refs()427 fn max_refs() {
428     struct LargeGenConfig;
429 
430     // Configure the slab with a very large number of bits for the generation
431     // counter. That way, there will be very few bits for the ref count left
432     // over, and this test won't have to malloc millions of references.
433     impl crate::cfg::Config for LargeGenConfig {
434         const INITIAL_PAGE_SIZE: usize = 2;
435         const MAX_THREADS: usize = 32;
436         const MAX_PAGES: usize = 2;
437     }
438 
439     let mut model = loom::model::Builder::new();
440     model.max_branches = 100000;
441     model.check(|| {
442         let slab = Slab::new_with_config::<LargeGenConfig>();
443         let key = slab.insert("hello world").unwrap();
444         let max = crate::page::slot::RefCount::<LargeGenConfig>::MAX;
445 
446         // Create the maximum number of concurrent references to the entry.
447         let mut refs = (0..max)
448             .map(|_| slab.get(key).unwrap())
449             // Store the refs in a vec so they don't get dropped immediately.
450             .collect::<Vec<_>>();
451 
452         assert!(slab.get(key).is_none());
453 
454         // After dropping a ref, we should now be able to access the slot again.
455         drop(refs.pop());
456         let ref1 = slab.get(key);
457         assert!(ref1.is_some());
458 
459         // Ref1 should max out the number of references again.
460         assert!(slab.get(key).is_none());
461     })
462 }
463 
464 mod free_list_reuse {
465     use super::*;
466     struct TinyConfig;
467 
468     impl crate::cfg::Config for TinyConfig {
469         const INITIAL_PAGE_SIZE: usize = 2;
470     }
471 
472     #[test]
local_remove()473     fn local_remove() {
474         run_model("free_list_reuse::local_remove", || {
475             let slab = Slab::new_with_config::<TinyConfig>();
476 
477             let t1 = slab.insert("hello").expect("insert");
478             let t2 = slab.insert("world").expect("insert");
479             assert_eq!(
480                 crate::page::indices::<TinyConfig>(t1).1,
481                 0,
482                 "1st slot should be on 0th page"
483             );
484             assert_eq!(
485                 crate::page::indices::<TinyConfig>(t2).1,
486                 0,
487                 "2nd slot should be on 0th page"
488             );
489             let t3 = slab.insert("earth").expect("insert");
490             assert_eq!(
491                 crate::page::indices::<TinyConfig>(t3).1,
492                 1,
493                 "3rd slot should be on 1st page"
494             );
495 
496             slab.remove(t2);
497             let t4 = slab.insert("universe").expect("insert");
498             assert_eq!(
499                 crate::page::indices::<TinyConfig>(t4).1,
500                 0,
501                 "2nd slot should be reused (0th page)"
502             );
503 
504             slab.remove(t1);
505             let _ = slab.insert("goodbye").expect("insert");
506             assert_eq!(
507                 crate::page::indices::<TinyConfig>(t4).1,
508                 0,
509                 "1st slot should be reused (0th page)"
510             );
511         });
512     }
513 
514     #[test]
local_take()515     fn local_take() {
516         run_model("free_list_reuse::local_take", || {
517             let slab = Slab::new_with_config::<TinyConfig>();
518 
519             let t1 = slab.insert("hello").expect("insert");
520             let t2 = slab.insert("world").expect("insert");
521             assert_eq!(
522                 crate::page::indices::<TinyConfig>(t1).1,
523                 0,
524                 "1st slot should be on 0th page"
525             );
526             assert_eq!(
527                 crate::page::indices::<TinyConfig>(t2).1,
528                 0,
529                 "2nd slot should be on 0th page"
530             );
531             let t3 = slab.insert("earth").expect("insert");
532             assert_eq!(
533                 crate::page::indices::<TinyConfig>(t3).1,
534                 1,
535                 "3rd slot should be on 1st page"
536             );
537 
538             assert_eq!(slab.take(t2), Some("world"));
539             let t4 = slab.insert("universe").expect("insert");
540             assert_eq!(
541                 crate::page::indices::<TinyConfig>(t4).1,
542                 0,
543                 "2nd slot should be reused (0th page)"
544             );
545 
546             assert_eq!(slab.take(t1), Some("hello"));
547             let _ = slab.insert("goodbye").expect("insert");
548             assert_eq!(
549                 crate::page::indices::<TinyConfig>(t4).1,
550                 0,
551                 "1st slot should be reused (0th page)"
552             );
553         });
554     }
555 }
556 
557 #[test]
vacant_entry()558 fn vacant_entry() {
559     run_model("vacant_entry", || {
560         let slab = Arc::new(Slab::new());
561         let entry = slab.vacant_entry().unwrap();
562         let key: usize = entry.key();
563 
564         let slab2 = slab.clone();
565         let t1 = thread::spawn(move || {
566             test_dbg!(slab2.get(key));
567         });
568 
569         entry.insert("hello world");
570         t1.join().unwrap();
571 
572         assert_eq!(slab.get(key).expect("get"), "hello world");
573     });
574 }
575 
576 #[test]
vacant_entry_2()577 fn vacant_entry_2() {
578     run_model("vacant_entry_2", || {
579         let slab = Arc::new(Slab::new());
580         let entry = slab.vacant_entry().unwrap();
581         let key: usize = entry.key();
582 
583         let slab2 = slab.clone();
584         let slab3 = slab.clone();
585         let t1 = thread::spawn(move || {
586             test_dbg!(slab2.get(key));
587         });
588 
589         entry.insert("hello world");
590         let t2 = thread::spawn(move || {
591             test_dbg!(slab3.get(key));
592         });
593 
594         t1.join().unwrap();
595         t2.join().unwrap();
596         assert_eq!(slab.get(key).expect("get"), "hello world");
597     });
598 }
599 
600 #[test]
vacant_entry_remove()601 fn vacant_entry_remove() {
602     run_model("vacant_entry_remove", || {
603         let slab = Arc::new(Slab::new());
604         let entry = slab.vacant_entry().unwrap();
605         let key: usize = entry.key();
606 
607         let slab2 = slab.clone();
608         let t1 = thread::spawn(move || {
609             assert!(!slab2.remove(key));
610         });
611 
612         t1.join().unwrap();
613 
614         entry.insert("hello world");
615         assert_eq!(slab.get(key).expect("get"), "hello world");
616     });
617 }
618 
619 #[test]
owned_entry_send_out_of_local()620 fn owned_entry_send_out_of_local() {
621     run_model("owned_entry_send_out_of_local", || {
622         let slab = Arc::new(Slab::<alloc::Track<String>>::new());
623         let key1 = slab
624             .insert(alloc::Track::new(String::from("hello")))
625             .expect("insert item 1");
626         let key2 = slab
627             .insert(alloc::Track::new(String::from("goodbye")))
628             .expect("insert item 2");
629 
630         let item1 = slab.clone().get_owned(key1).expect("get key1");
631         let item2 = slab.clone().get_owned(key2).expect("get key2");
632         let slab2 = slab.clone();
633 
634         test_dbg!(slab.remove(key1));
635 
636         let t1 = thread::spawn(move || {
637             assert_eq!(item1.get_ref(), &String::from("hello"));
638             drop(item1);
639         });
640         let t2 = thread::spawn(move || {
641             assert_eq!(item2.get_ref(), &String::from("goodbye"));
642             test_dbg!(slab2.remove(key2));
643             drop(item2);
644         });
645 
646         t1.join().unwrap();
647         t2.join().unwrap();
648 
649         assert!(slab.get(key1).is_none());
650         assert!(slab.get(key2).is_none());
651     });
652 }
653 
654 #[test]
owned_entrys_outlive_slab()655 fn owned_entrys_outlive_slab() {
656     run_model("owned_entrys_outlive_slab", || {
657         let slab = Arc::new(Slab::<alloc::Track<String>>::new());
658         let key1 = slab
659             .insert(alloc::Track::new(String::from("hello")))
660             .expect("insert item 1");
661         let key2 = slab
662             .insert(alloc::Track::new(String::from("goodbye")))
663             .expect("insert item 2");
664 
665         let item1_1 = slab.clone().get_owned(key1).expect("get key1");
666         let item1_2 = slab.clone().get_owned(key1).expect("get key1 again");
667         let item2 = slab.clone().get_owned(key2).expect("get key2");
668         drop(slab);
669 
670         let t1 = thread::spawn(move || {
671             assert_eq!(item1_1.get_ref(), &String::from("hello"));
672             drop(item1_1);
673         });
674 
675         let t2 = thread::spawn(move || {
676             assert_eq!(item2.get_ref(), &String::from("goodbye"));
677             drop(item2);
678         });
679 
680         t1.join().unwrap();
681         t2.join().unwrap();
682 
683         assert_eq!(item1_2.get_ref(), &String::from("hello"));
684     });
685 }
686 
687 #[test]
owned_entry_ping_pong()688 fn owned_entry_ping_pong() {
689     run_model("owned_entry_ping_pong", || {
690         let slab = Arc::new(Slab::<alloc::Track<String>>::new());
691         let key1 = slab
692             .insert(alloc::Track::new(String::from("hello")))
693             .expect("insert item 1");
694         let key2 = slab
695             .insert(alloc::Track::new(String::from("world")))
696             .expect("insert item 2");
697 
698         let item1 = slab.clone().get_owned(key1).expect("get key1");
699         let slab2 = slab.clone();
700         let slab3 = slab.clone();
701 
702         let t1 = thread::spawn(move || {
703             assert_eq!(item1.get_ref(), &String::from("hello"));
704             slab2.remove(key1);
705             item1
706         });
707 
708         let t2 = thread::spawn(move || {
709             let item2 = slab3.clone().get_owned(key2).unwrap();
710             assert_eq!(item2.get_ref(), &String::from("world"));
711             slab3.remove(key1);
712             item2
713         });
714 
715         let item1 = t1.join().unwrap();
716         let item2 = t2.join().unwrap();
717 
718         assert_eq!(item1.get_ref(), &String::from("hello"));
719         assert_eq!(item2.get_ref(), &String::from("world"));
720     });
721 }
722 
723 #[test]
owned_entry_drop_from_other_threads()724 fn owned_entry_drop_from_other_threads() {
725     run_model("owned_entry_drop_from_other_threads", || {
726         let slab = Arc::new(Slab::<alloc::Track<String>>::new());
727         let key1 = slab
728             .insert(alloc::Track::new(String::from("hello")))
729             .expect("insert item 1");
730         let item1 = slab.clone().get_owned(key1).expect("get key1");
731 
732         let slab2 = slab.clone();
733 
734         let t1 = thread::spawn(move || {
735             let slab = slab2.clone();
736             let key2 = slab
737                 .insert(alloc::Track::new(String::from("goodbye")))
738                 .expect("insert item 1");
739             let item2 = slab.clone().get_owned(key2).expect("get key1");
740             let t2 = thread::spawn(move || {
741                 assert_eq!(item2.get_ref(), &String::from("goodbye"));
742                 test_dbg!(slab2.remove(key1));
743                 drop(item2)
744             });
745             assert_eq!(item1.get_ref(), &String::from("hello"));
746             test_dbg!(slab.remove(key2));
747             drop(item1);
748             (t2, key2)
749         });
750 
751         let (t2, key2) = t1.join().unwrap();
752         test_dbg!(slab.get(key1));
753         test_dbg!(slab.get(key2));
754 
755         t2.join().unwrap();
756 
757         assert!(slab.get(key1).is_none());
758         assert!(slab.get(key2).is_none());
759     });
760 }
761