1 use super::util::*;
2 use crate::{clear::Clear, sync::alloc, Pack, Pool};
3 use loom::{
4     sync::{
5         atomic::{AtomicBool, Ordering},
6         Condvar, Mutex,
7     },
8     thread,
9 };
10 use std::sync::Arc;
11 
12 #[derive(Default, Debug)]
13 struct State {
14     is_dropped: AtomicBool,
15     is_cleared: AtomicBool,
16     id: usize,
17 }
18 
19 impl State {
assert_clear(&self)20     fn assert_clear(&self) {
21         assert!(!self.is_dropped.load(Ordering::SeqCst));
22         assert!(self.is_cleared.load(Ordering::SeqCst));
23     }
24 
assert_not_clear(&self)25     fn assert_not_clear(&self) {
26         assert!(!self.is_dropped.load(Ordering::SeqCst));
27         assert!(!self.is_cleared.load(Ordering::SeqCst));
28     }
29 }
30 
31 impl PartialEq for State {
eq(&self, other: &State) -> bool32     fn eq(&self, other: &State) -> bool {
33         self.id.eq(&other.id)
34     }
35 }
36 
37 #[derive(Default, Debug)]
38 struct DontDropMe(Arc<State>);
39 
40 impl PartialEq for DontDropMe {
eq(&self, other: &DontDropMe) -> bool41     fn eq(&self, other: &DontDropMe) -> bool {
42         self.0.eq(&other.0)
43     }
44 }
45 
46 impl DontDropMe {
new(id: usize) -> (Arc<State>, Self)47     fn new(id: usize) -> (Arc<State>, Self) {
48         let state = Arc::new(State {
49             is_dropped: AtomicBool::new(false),
50             is_cleared: AtomicBool::new(false),
51             id,
52         });
53         (state.clone(), Self(state))
54     }
55 }
56 
57 impl Drop for DontDropMe {
drop(&mut self)58     fn drop(&mut self) {
59         test_println!("-> DontDropMe drop: dropping data {:?}", self.0.id);
60         self.0.is_dropped.store(true, Ordering::SeqCst)
61     }
62 }
63 
64 impl Clear for DontDropMe {
clear(&mut self)65     fn clear(&mut self) {
66         test_println!("-> DontDropMe clear: clearing data {:?}", self.0.id);
67         self.0.is_cleared.store(true, Ordering::SeqCst);
68     }
69 }
70 
71 #[test]
dont_drop()72 fn dont_drop() {
73     run_model("dont_drop", || {
74         let pool: Pool<DontDropMe> = Pool::new();
75         let (item1, value) = DontDropMe::new(1);
76         test_println!("-> dont_drop: Inserting into pool {}", item1.id);
77         let idx = pool
78             .create_with(move |item| *item = value)
79             .expect("create_with");
80 
81         item1.assert_not_clear();
82 
83         test_println!("-> dont_drop: clearing idx: {}", idx);
84         pool.clear(idx);
85 
86         item1.assert_clear();
87     });
88 }
89 
90 #[test]
concurrent_create_with_clear()91 fn concurrent_create_with_clear() {
92     run_model("concurrent_create_with_clear", || {
93         let pool: Arc<Pool<DontDropMe>> = Arc::new(Pool::new());
94         let pair = Arc::new((Mutex::new(None), Condvar::new()));
95 
96         let (item1, value) = DontDropMe::new(1);
97         let idx1 = pool
98             .create_with(move |item| *item = value)
99             .expect("create_with");
100         let p = pool.clone();
101         let pair2 = pair.clone();
102         let test_value = item1.clone();
103         let t1 = thread::spawn(move || {
104             let (lock, cvar) = &*pair2;
105             test_println!("-> making get request");
106             assert_eq!(p.get(idx1).unwrap().0.id, test_value.id);
107             let mut next = lock.lock().unwrap();
108             *next = Some(());
109             cvar.notify_one();
110         });
111 
112         test_println!("-> making get request");
113         let guard = pool.get(idx1);
114 
115         let (lock, cvar) = &*pair;
116         let mut next = lock.lock().unwrap();
117         // wait until we have a guard on the other thread.
118         while next.is_none() {
119             next = cvar.wait(next).unwrap();
120         }
121         // the item should be marked (clear returns true)...
122         assert!(pool.clear(idx1));
123         // ...but the value shouldn't be removed yet.
124         item1.assert_not_clear();
125 
126         t1.join().expect("thread 1 unable to join");
127 
128         drop(guard);
129         item1.assert_clear();
130     })
131 }
132 
133 #[test]
racy_clear()134 fn racy_clear() {
135     run_model("racy_clear", || {
136         let pool = Arc::new(Pool::new());
137         let (item, value) = DontDropMe::new(1);
138 
139         let idx = pool
140             .create_with(move |item| *item = value)
141             .expect("create_with");
142         assert_eq!(pool.get(idx).unwrap().0.id, item.id);
143 
144         let p = pool.clone();
145         let t2 = thread::spawn(move || p.clear(idx));
146         let r1 = pool.clear(idx);
147         let r2 = t2.join().expect("thread 2 should not panic");
148 
149         test_println!("r1: {}, r2: {}", r1, r2);
150 
151         assert!(
152             !(r1 && r2),
153             "Both threads should not have cleared the value"
154         );
155         assert!(r1 || r2, "One thread should have removed the value");
156         assert!(pool.get(idx).is_none());
157         item.assert_clear();
158     })
159 }
160 
161 #[test]
clear_local_and_reuse()162 fn clear_local_and_reuse() {
163     run_model("take_remote_and_reuse", || {
164         let pool = Arc::new(Pool::new_with_config::<TinyConfig>());
165 
166         let idx1 = pool
167             .create_with(|item: &mut String| {
168                 item.push_str("hello world");
169             })
170             .expect("create_with");
171         let idx2 = pool
172             .create_with(|item| item.push_str("foo"))
173             .expect("create_with");
174         let idx3 = pool
175             .create_with(|item| item.push_str("bar"))
176             .expect("create_with");
177 
178         assert_eq!(pool.get(idx1).unwrap(), String::from("hello world"));
179         assert_eq!(pool.get(idx2).unwrap(), String::from("foo"));
180         assert_eq!(pool.get(idx3).unwrap(), String::from("bar"));
181 
182         let first = idx1 & (!crate::page::slot::Generation::<TinyConfig>::MASK);
183         assert!(pool.clear(idx1));
184 
185         let idx1 = pool
186             .create_with(move |item| item.push_str("h"))
187             .expect("create_with");
188 
189         let second = idx1 & (!crate::page::slot::Generation::<TinyConfig>::MASK);
190         assert_eq!(first, second);
191         assert!(pool.get(idx1).unwrap().capacity() >= 11);
192     })
193 }
194 
195 #[test]
create_mut_guard_prevents_access()196 fn create_mut_guard_prevents_access() {
197     run_model("create_mut_guard_prevents_access", || {
198         let pool = Arc::new(Pool::<String>::new());
199         let guard = pool.create().unwrap();
200         let key: usize = guard.key();
201 
202         let pool2 = pool.clone();
203         thread::spawn(move || {
204             assert!(pool2.get(key).is_none());
205         })
206         .join()
207         .unwrap();
208     });
209 }
210 
211 #[test]
create_mut_guard()212 fn create_mut_guard() {
213     run_model("create_mut_guard", || {
214         let pool = Arc::new(Pool::<String>::new());
215         let mut guard = pool.create().unwrap();
216         let key: usize = guard.key();
217 
218         let pool2 = pool.clone();
219         let t1 = thread::spawn(move || {
220             test_dbg!(pool2.get(key));
221         });
222 
223         guard.push_str("Hello world");
224         drop(guard);
225 
226         t1.join().unwrap();
227     });
228 }
229 
230 #[test]
create_mut_guard_2()231 fn create_mut_guard_2() {
232     run_model("create_mut_guard_2", || {
233         let pool = Arc::new(Pool::<String>::new());
234         let mut guard = pool.create().unwrap();
235         let key: usize = guard.key();
236 
237         let pool2 = pool.clone();
238         let pool3 = pool.clone();
239         let t1 = thread::spawn(move || {
240             test_dbg!(pool2.get(key));
241         });
242 
243         guard.push_str("Hello world");
244         let t2 = thread::spawn(move || {
245             test_dbg!(pool3.get(key));
246         });
247         drop(guard);
248 
249         t1.join().unwrap();
250         t2.join().unwrap();
251     });
252 }
253 
254 #[test]
create_mut_guard_downgrade()255 fn create_mut_guard_downgrade() {
256     run_model("create_mut_guard_downgrade", || {
257         let pool = Arc::new(Pool::<String>::new());
258         let mut guard = pool.create().unwrap();
259         let key: usize = guard.key();
260 
261         let pool2 = pool.clone();
262         let pool3 = pool.clone();
263         let t1 = thread::spawn(move || {
264             test_dbg!(pool2.get(key));
265         });
266 
267         guard.push_str("Hello world");
268         let guard = guard.downgrade();
269         let t2 = thread::spawn(move || {
270             test_dbg!(pool3.get(key));
271         });
272 
273         t1.join().unwrap();
274         t2.join().unwrap();
275         assert_eq!(guard, "Hello world".to_owned());
276     });
277 }
278 
279 #[test]
create_mut_guard_downgrade_clear()280 fn create_mut_guard_downgrade_clear() {
281     run_model("create_mut_guard_downgrade_clear", || {
282         let pool = Arc::new(Pool::<String>::new());
283         let mut guard = pool.create().unwrap();
284         let key: usize = guard.key();
285 
286         let pool2 = pool.clone();
287 
288         guard.push_str("Hello world");
289         let guard = guard.downgrade();
290         let pool3 = pool.clone();
291         let t1 = thread::spawn(move || {
292             test_dbg!(pool2.get(key));
293         });
294         let t2 = thread::spawn(move || {
295             test_dbg!(pool3.clear(key));
296         });
297 
298         assert_eq!(guard, "Hello world".to_owned());
299         drop(guard);
300 
301         t1.join().unwrap();
302         t2.join().unwrap();
303 
304         assert!(pool.get(key).is_none());
305     });
306 }
307 
308 #[test]
create_mut_downgrade_during_clear()309 fn create_mut_downgrade_during_clear() {
310     run_model("create_mut_downgrade_during_clear", || {
311         let pool = Arc::new(Pool::<String>::new());
312         let mut guard = pool.create().unwrap();
313         let key: usize = guard.key();
314         guard.push_str("Hello world");
315 
316         let pool2 = pool.clone();
317         let guard = guard.downgrade();
318         let t1 = thread::spawn(move || {
319             test_dbg!(pool2.clear(key));
320         });
321 
322         t1.join().unwrap();
323 
324         assert_eq!(guard, "Hello world".to_owned());
325         drop(guard);
326 
327         assert!(pool.get(key).is_none());
328     });
329 }
330 
331 #[test]
ownedref_send_out_of_local()332 fn ownedref_send_out_of_local() {
333     run_model("ownedref_send_out_of_local", || {
334         let pool = Arc::new(Pool::<alloc::Track<String>>::new());
335         let key1 = pool
336             .create_with(|item| item.get_mut().push_str("hello"))
337             .expect("create item 1");
338         let key2 = pool
339             .create_with(|item| item.get_mut().push_str("goodbye"))
340             .expect("create item 2");
341 
342         let item1 = pool.clone().get_owned(key1).expect("get key1");
343         let item2 = pool.clone().get_owned(key2).expect("get key2");
344         let pool2 = pool.clone();
345 
346         test_dbg!(pool.clear(key1));
347 
348         let t1 = thread::spawn(move || {
349             assert_eq!(item1.get_ref(), &String::from("hello"));
350             drop(item1);
351         });
352         let t2 = thread::spawn(move || {
353             assert_eq!(item2.get_ref(), &String::from("goodbye"));
354             test_dbg!(pool2.clear(key2));
355             drop(item2);
356         });
357 
358         t1.join().unwrap();
359         t2.join().unwrap();
360 
361         assert!(pool.get(key1).is_none());
362         assert!(pool.get(key2).is_none());
363     });
364 }
365 
366 #[test]
ownedrefs_outlive_pool()367 fn ownedrefs_outlive_pool() {
368     run_model("ownedrefs_outlive_pool", || {
369         let pool = Arc::new(Pool::<alloc::Track<String>>::new());
370         let key1 = pool
371             .create_with(|item| item.get_mut().push_str("hello"))
372             .expect("create item 1");
373         let key2 = pool
374             .create_with(|item| item.get_mut().push_str("goodbye"))
375             .expect("create item 2");
376 
377         let item1_1 = pool.clone().get_owned(key1).expect("get key1");
378         let item1_2 = pool.clone().get_owned(key1).expect("get key1 again");
379         let item2 = pool.clone().get_owned(key2).expect("get key2");
380         drop(pool);
381 
382         let t1 = thread::spawn(move || {
383             assert_eq!(item1_1.get_ref(), &String::from("hello"));
384             drop(item1_1);
385         });
386 
387         let t2 = thread::spawn(move || {
388             assert_eq!(item2.get_ref(), &String::from("goodbye"));
389             drop(item2);
390         });
391 
392         t1.join().unwrap();
393         t2.join().unwrap();
394 
395         assert_eq!(item1_2.get_ref(), &String::from("hello"));
396     });
397 }
398 
399 #[test]
ownedref_ping_pong()400 fn ownedref_ping_pong() {
401     run_model("ownedref_ping_pong", || {
402         let pool = Arc::new(Pool::<alloc::Track<String>>::new());
403         let key1 = pool
404             .create_with(|item| item.get_mut().push_str("hello"))
405             .expect("create item 1");
406         let key2 = pool
407             .create_with(|item| item.get_mut().push_str("world"))
408             .expect("create item 2");
409 
410         let item1 = pool.clone().get_owned(key1).expect("get key1");
411         let pool2 = pool.clone();
412         let pool3 = pool.clone();
413 
414         let t1 = thread::spawn(move || {
415             assert_eq!(item1.get_ref(), &String::from("hello"));
416             pool2.clear(key1);
417             item1
418         });
419 
420         let t2 = thread::spawn(move || {
421             let item2 = pool3.clone().get_owned(key2).unwrap();
422             assert_eq!(item2.get_ref(), &String::from("world"));
423             pool3.clear(key1);
424             item2
425         });
426 
427         let item1 = t1.join().unwrap();
428         let item2 = t2.join().unwrap();
429 
430         assert_eq!(item1.get_ref(), &String::from("hello"));
431         assert_eq!(item2.get_ref(), &String::from("world"));
432     });
433 }
434 
435 #[test]
ownedref_drop_from_other_threads()436 fn ownedref_drop_from_other_threads() {
437     run_model("ownedref_drop_from_other_threads", || {
438         let pool = Arc::new(Pool::<alloc::Track<String>>::new());
439         let key1 = pool
440             .create_with(|item| item.get_mut().push_str("hello"))
441             .expect("create item 1");
442         let item1 = pool.clone().get_owned(key1).expect("get key1");
443 
444         let pool2 = pool.clone();
445 
446         let t1 = thread::spawn(move || {
447             let pool = pool2.clone();
448             let key2 = pool
449                 .create_with(|item| item.get_mut().push_str("goodbye"))
450                 .expect("create item 1");
451             let item2 = pool.clone().get_owned(key2).expect("get key1");
452             let t2 = thread::spawn(move || {
453                 assert_eq!(item2.get_ref(), &String::from("goodbye"));
454                 test_dbg!(pool2.clear(key1));
455                 drop(item2)
456             });
457             assert_eq!(item1.get_ref(), &String::from("hello"));
458             test_dbg!(pool.clear(key2));
459             drop(item1);
460             (t2, key2)
461         });
462 
463         let (t2, key2) = t1.join().unwrap();
464         test_dbg!(pool.get(key1));
465         test_dbg!(pool.get(key2));
466 
467         t2.join().unwrap();
468 
469         assert!(pool.get(key1).is_none());
470         assert!(pool.get(key2).is_none());
471     });
472 }
473 
474 #[test]
create_owned_mut_guard()475 fn create_owned_mut_guard() {
476     run_model("create_owned_mut_guard", || {
477         let pool = Arc::new(Pool::<String>::new());
478         let mut guard = pool.clone().create_owned().unwrap();
479         let key: usize = guard.key();
480 
481         let pool2 = pool.clone();
482         let t1 = thread::spawn(move || {
483             test_dbg!(pool2.get(key));
484         });
485 
486         guard.push_str("Hello world");
487         drop(guard);
488 
489         t1.join().unwrap();
490     });
491 }
492 
493 #[test]
create_owned_mut_guard_send()494 fn create_owned_mut_guard_send() {
495     run_model("create_owned_mut_guard", || {
496         let pool = Arc::new(Pool::<String>::new());
497         let mut guard = pool.clone().create_owned().unwrap();
498         let key: usize = guard.key();
499 
500         let pool2 = pool.clone();
501         let t1 = thread::spawn(move || {
502             test_dbg!(pool2.get(key));
503         });
504 
505         let t2 = thread::spawn(move || {
506             guard.push_str("Hello world");
507             drop(guard);
508         });
509 
510         t1.join().unwrap();
511         t2.join().unwrap();
512     });
513 }
514 
515 #[test]
create_owned_mut_guard_2()516 fn create_owned_mut_guard_2() {
517     run_model("create_owned_mut_guard_2", || {
518         let pool = Arc::new(Pool::<String>::new());
519         let mut guard = pool.clone().create_owned().unwrap();
520         let key: usize = guard.key();
521 
522         let pool2 = pool.clone();
523         let pool3 = pool.clone();
524         let t1 = thread::spawn(move || {
525             test_dbg!(pool2.get(key));
526         });
527 
528         guard.push_str("Hello world");
529         let t2 = thread::spawn(move || {
530             test_dbg!(pool3.get(key));
531         });
532         drop(guard);
533 
534         t1.join().unwrap();
535         t2.join().unwrap();
536     });
537 }
538 
539 #[test]
create_owned_mut_guard_downgrade()540 fn create_owned_mut_guard_downgrade() {
541     run_model("create_owned_mut_guard_downgrade", || {
542         let pool = Arc::new(Pool::<String>::new());
543         let mut guard = pool.clone().create_owned().unwrap();
544         guard.push_str("Hello world");
545 
546         let key: usize = guard.key();
547 
548         let pool2 = pool.clone();
549         let pool3 = pool.clone();
550         let t1 = thread::spawn(move || {
551             test_dbg!(pool2.get(key));
552         });
553 
554         let guard = guard.downgrade();
555         let t2 = thread::spawn(move || {
556             assert_eq!(pool3.get(key).unwrap(), "Hello world".to_owned());
557         });
558 
559         t1.join().unwrap();
560         t2.join().unwrap();
561         assert_eq!(guard, "Hello world".to_owned());
562     });
563 }
564 
565 #[test]
create_owned_mut_guard_downgrade_then_clear()566 fn create_owned_mut_guard_downgrade_then_clear() {
567     run_model("create_owned_mut_guard_downgrade_then_clear", || {
568         let pool = Arc::new(Pool::<String>::new());
569         let mut guard = pool.clone().create_owned().unwrap();
570         let key: usize = guard.key();
571 
572         let pool2 = pool.clone();
573 
574         guard.push_str("Hello world");
575         let guard = guard.downgrade();
576         let pool3 = pool.clone();
577         let t1 = thread::spawn(move || {
578             test_dbg!(pool2.get(key));
579         });
580         let t2 = thread::spawn(move || {
581             test_dbg!(pool3.clear(key));
582         });
583 
584         assert_eq!(guard, "Hello world".to_owned());
585         drop(guard);
586 
587         t1.join().unwrap();
588         t2.join().unwrap();
589 
590         assert!(pool.get(key).is_none());
591     });
592 }
593 
594 #[test]
create_owned_mut_downgrade_during_clear()595 fn create_owned_mut_downgrade_during_clear() {
596     run_model("create_owned_mut_downgrade_during_clear", || {
597         let pool = Arc::new(Pool::<String>::new());
598         let mut guard = pool.clone().create_owned().unwrap();
599         let key: usize = guard.key();
600         guard.push_str("Hello world");
601 
602         let pool2 = pool.clone();
603         let guard = guard.downgrade();
604         let t1 = thread::spawn(move || {
605             test_dbg!(pool2.clear(key));
606         });
607 
608         t1.join().unwrap();
609 
610         assert_eq!(guard, "Hello world".to_owned());
611         drop(guard);
612 
613         assert!(pool.get(key).is_none());
614     });
615 }
616 
617 #[test]
create_mut_downgrade_during_clear_by_other_thead()618 fn create_mut_downgrade_during_clear_by_other_thead() {
619     run_model("create_mut_downgrade_during_clear_by_other_thread", || {
620         let pool = Arc::new(Pool::<String>::new());
621         let mut guard = pool.clone().create_owned().unwrap();
622         let key: usize = guard.key();
623         guard.push_str("Hello world");
624 
625         let pool2 = pool.clone();
626         let t1 = thread::spawn(move || {
627             let guard = guard.downgrade();
628             assert_eq!(guard, "Hello world".to_owned());
629             drop(guard);
630         });
631 
632         let t2 = thread::spawn(move || {
633             test_dbg!(pool2.clear(key));
634         });
635 
636         test_dbg!(pool.get(key));
637 
638         t1.join().unwrap();
639         t2.join().unwrap();
640     });
641 }
642