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