1use std::{sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}, cmp::Ordering, hash::{Hash, Hasher}, mem::swap};
11
12#[derive(Debug)]
84pub struct SyncCell<T: ?Sized> {
85 data: RwLock<T>,
87}
88
89impl <T> SyncCell<T> {
90 pub const fn new(data: T) -> Self {
94 Self {
95 data: RwLock::new(data)
96 }
97 }
98
99 pub fn set(&self, value: T) {
106 match self.data.write() {
107 Ok(mut data) => *data = value,
108 Err(err) => panic!("Failed to set cell value. Lock was poisoned: {}", err),
109 }
110 }
111
112 pub fn into_inner(self) -> T {
117 match self.data.into_inner() {
118 Ok(data) => data,
119 Err(err) => panic!("Failed to get cell value. Lock was poisoned: {}", err),
120 }
121 }
122
123 pub fn replace(&self, mut value: T) -> T {
131 match self.data.write() {
132 Ok(mut data) => {
133 swap(&mut *data, &mut value);
134 value
135 },
136 Err(err) => panic!("Failed to set cell value. Lock was poisoned: {}", err),
137 }
138 }
139}
140
141impl <T: ?Sized> SyncCell<T> {
142 pub fn borrow(&self) -> RwLockReadGuard<T> {
147 match self.data.read() {
148 Ok(data) => data,
149 Err(err) => panic!("Failed to get cell value. Lock was poisoned: {}", err),
150 }
151 }
152
153 pub fn borrow_mut(&self) -> RwLockWriteGuard<T> {
158 match self.data.write() {
159 Ok(data) => data,
160 Err(err) => panic!("Failed to get cell value. Lock was poisoned: {}", err),
161 }
162 }
163}
164
165impl <T: Clone> SyncCell<T> {
166 pub fn get(&self) -> T {
171 match self.data.read() {
172 Ok(data) => data.clone(),
173 Err(err) => panic!("Failed to get cell value. Lock was poisoned: {}", err),
174 }
175 }
176}
177
178impl <T: Clone> Clone for SyncCell<T> {
179 fn clone(&self) -> Self {
180 Self::new(self.get())
181 }
182}
183
184impl <T: Default> Default for SyncCell<T> {
185 fn default() -> Self {
186 Self::new(T::default())
187 }
188}
189
190impl <T: PartialEq + ?Sized> PartialEq for SyncCell<T> {
191 fn eq(&self, other: &Self) -> bool {
192 self.borrow().eq(&*other.borrow())
193 }
194}
195
196impl <T: Eq + ?Sized> Eq for SyncCell<T> {
197}
198
199impl <T: PartialOrd + ?Sized> PartialOrd for SyncCell<T> {
200 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
201 self.borrow().partial_cmp(&*other.borrow())
202 }
203}
204
205impl <T: Ord + ?Sized> Ord for SyncCell<T> {
206 fn cmp(&self, other: &Self) -> Ordering {
207 self.borrow().cmp(&*other.borrow())
208 }
209}
210
211impl <T: Hash + ?Sized> Hash for SyncCell<T> {
212 fn hash<H: Hasher>(&self, state: &mut H) {
213 self.borrow().hash(state)
214 }
215}
216
217impl <T> From<T> for SyncCell<T> {
218 fn from(value: T) -> Self {
219 Self::new(value)
220 }
221}
222
223pub struct HeldSyncCell<T> {
246 current_value: SyncCell<T>,
248 next_value: SyncCell<Option<T>>,
250}
251
252impl <T> HeldSyncCell<T> {
253 pub const fn new(data: T) -> Self {
257 Self {
258 current_value: SyncCell::new(data),
259 next_value: SyncCell::new(None),
260 }
261 }
262
263 pub fn set(&self, value: T) {
275 self.next_value.set(Some(value))
276 }
277
278 pub fn into_inner(self) -> T {
284 self.next_value.into_inner()
285 .unwrap_or(self.current_value.into_inner())
286 }
287
288 pub fn borrow(&self) -> RwLockReadGuard<T> {
294 self.current_value.borrow()
295 }
296
297 pub fn borrow_mut(&self) -> RwLockWriteGuard<T> {
304 self.current_value.borrow_mut()
305 }
306
307 pub fn has_update(&self) -> bool {
312 self.next_value.borrow().is_some()
313 }
314
315 pub fn update(&self) {
321 if let Some(next) = self.next_value.replace(None) {
322 self.current_value.set(next);
323 }
324 }
325}
326
327impl <T: Clone> HeldSyncCell<T> {
328 pub fn get(&self) -> T {
333 self.current_value.get()
334 }
335}
336
337impl <T: Clone> Clone for HeldSyncCell<T> {
338 fn clone(&self) -> Self {
339 Self::new(self.get())
340 }
341}
342
343impl <T: Default> Default for HeldSyncCell<T> {
344 fn default() -> Self {
345 Self::new(T::default())
346 }
347}
348
349impl <T: PartialEq> PartialEq for HeldSyncCell<T> {
350 fn eq(&self, other: &Self) -> bool {
351 self.borrow().eq(&*other.borrow())
352 }
353}
354
355impl <T: Eq> Eq for HeldSyncCell<T> {
356}
357
358impl <T: PartialOrd> PartialOrd for HeldSyncCell<T> {
359 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
360 self.borrow().partial_cmp(&*other.borrow())
361 }
362}
363
364impl <T: Ord> Ord for HeldSyncCell<T> {
365 fn cmp(&self, other: &Self) -> Ordering {
366 self.borrow().cmp(&*other.borrow())
367 }
368}
369
370impl <T: Hash> Hash for HeldSyncCell<T> {
371 fn hash<H: Hasher>(&self, state: &mut H) {
372 self.borrow().hash(state)
373 }
374}
375
376impl <T> From<T> for HeldSyncCell<T> {
377 fn from(value: T) -> Self {
378 Self::new(value)
379 }
380}
381
382#[cfg(test)]
383mod tests {
384 use core::panic;
385 use std::{thread, sync::Arc};
386
387 use crate::{SyncCell, HeldSyncCell};
388
389 #[test]
390 pub fn test_sync_cell_new() {
391 let _cell = SyncCell::new(1);
392 }
393
394 #[test]
395 pub fn test_sync_cell_set() {
396 let cell = SyncCell::new(2);
397
398 cell.set(3);
399
400 assert_eq!(3, cell.get())
401 }
402
403 #[test]
404 pub fn test_sync_cell_get() {
405 let cell = SyncCell::new(4);
406
407 assert_eq!(4, cell.get())
408 }
409
410 #[test]
411 pub fn test_sync_cell_replace() {
412 let cell = SyncCell::new(2);
413
414 let old = cell.replace(3);
415
416 assert_eq!(2, old);
417 assert_eq!(3, cell.get())
418 }
419
420 #[test]
421 #[should_panic]
422 pub fn test_sync_cell_replace_poisoned() {
423 let cell = Arc::new(SyncCell::new(4));
424
425 let cell2 = cell.clone();
426
427 let _ = thread::spawn(move || {
428 let _borrow = cell2.borrow();
429
430 panic!("Intentional panic.");
431 }).join();
432
433 let old = cell.replace(3);
434
435 assert_ne!(2, old);
436 assert_ne!(3, cell.get())
437 }
438
439 #[test]
440 pub fn test_sync_cell_into_inner() {
441 let cell = SyncCell::new(4);
442
443 assert_eq!(4, cell.into_inner())
444 }
445
446 #[test]
447 pub fn test_sync_cell_mutable_borrow() {
448 let cell = SyncCell::new(4);
449
450 let mut borrow = cell.borrow_mut();
451
452 *borrow = 5;
453
454 drop(borrow);
455
456 assert_eq!(5, cell.get())
457 }
458
459 #[test]
460 #[should_panic]
461 pub fn test_sync_cell_mutable_borrow_poisoned() {
462 let cell = Arc::new(SyncCell::new(4));
463
464 let cell2 = cell.clone();
465
466 let _ = thread::spawn(move || {
467 let _borrow = cell2.borrow();
468
469 panic!("Intentional panic.");
470 }).join();
471
472 let mut borrow = cell.borrow_mut();
473
474 *borrow = 5;
475
476 drop(borrow);
477
478 assert_ne!(5, cell.get())
479 }
480
481 #[test]
482 #[should_panic]
483 pub fn test_sync_cell_get_poisoned() {
484 let cell = Arc::new(SyncCell::new(4));
485
486 let cell2 = cell.clone();
487
488 let _ = thread::spawn(move || {
489 let _borrow = cell2.borrow();
490
491 panic!("Intentional panic.");
492 }).join();
493
494 assert_ne!(4, cell.get())
495 }
496
497 #[test]
498 #[should_panic]
499 pub fn test_sync_cell_set_poisoned() {
500 let cell = Arc::new(SyncCell::new(4));
501
502 let cell2 = cell.clone();
503
504 let _ = thread::spawn(move || {
505 let _borrow = cell2.borrow();
506
507 panic!("Intentional panic.");
508 }).join();
509
510 cell.set(5);
511
512 assert_ne!(5, cell.get());
513 }
514
515 #[test]
516 pub fn test_held_sync_cell_new() {
517 let _cell = HeldSyncCell::new(0);
518 }
519
520 #[test]
521 pub fn test_held_sync_cell_get() {
522 let cell = HeldSyncCell::new(1);
523
524 assert_eq!(1, cell.get())
525 }
526
527 #[test]
528 pub fn test_held_sync_cell_set_no_update() {
529 let cell = HeldSyncCell::new(1);
530
531 cell.set(2);
532
533 assert_eq!(true, cell.has_update());
534 assert_eq!(1, cell.get())
535 }
536
537 #[test]
538 pub fn test_held_sync_cell_set_update() {
539 let cell = HeldSyncCell::new(1);
540
541 cell.set(2);
542 cell.update();
543
544 assert_eq!(false, cell.has_update());
545 assert_eq!(2, cell.get())
546 }
547
548 #[test]
549 pub fn test_held_sync_cell_set_double_update() {
550 let cell = HeldSyncCell::new(1);
551
552 cell.set(2);
553 cell.update();
554 cell.update();
555
556 assert_eq!(false, cell.has_update());
557 assert_eq!(2, cell.get())
558 }
559
560 #[test]
561 pub fn test_held_sync_cell_no_set_update() {
562 let cell = HeldSyncCell::new(1);
563
564 cell.update();
565
566 assert_eq!(false, cell.has_update());
567 assert_eq!(1, cell.get())
568 }
569
570 #[test]
571 pub fn test_held_sync_cell_no_set() {
572 let cell = HeldSyncCell::new(1);
573
574 assert_eq!(false, cell.has_update());
575 assert_eq!(1, cell.get())
576 }
577
578 #[test]
579 pub fn test_held_sync_cell_into_inner() {
580 let cell = HeldSyncCell::new(4);
581
582 assert_eq!(4, cell.into_inner())
583 }
584
585 #[test]
586 pub fn test_held_sync_cell_set_into_inner() {
587 let cell = HeldSyncCell::new(4);
588
589 cell.set(5);
590
591 assert_eq!(5, cell.into_inner())
592 }
593
594 #[test]
595 pub fn test_held_sync_cell_set_update_into_inner() {
596 let cell = HeldSyncCell::new(4);
597
598 cell.set(5);
599 cell.update();
600
601 assert_eq!(5, cell.into_inner())
602 }
603
604 #[test]
605 pub fn test_held_sync_cell_mutable_borrow() {
606 let cell = HeldSyncCell::new(4);
607
608 let mut borrow = cell.borrow_mut();
609
610 *borrow = 5;
611
612 drop(borrow);
613
614 assert_eq!(5, cell.get())
615 }
616
617 #[test]
618 pub fn test_held_sync_cell_mutable_borrow_set() {
619 let cell = HeldSyncCell::new(4);
620
621 let mut borrow = cell.borrow_mut();
622
623 *borrow = 5;
624
625 cell.set(6);
626
627 drop(borrow);
628
629 assert_eq!(5, cell.get());
630 cell.update();
631 assert_eq!(6, cell.get());
632 }
633}
634