1extern crate crossbeam_utils;
17extern crate crossbeam_deque;
18
19#[cfg(test)]
20use std::sync::{Arc, Weak};
21
22use std::
23{
24 cell::RefCell, collections::HashMap, fmt::{self}, marker::PhantomData, ops::{Deref, DerefMut}, ptr::{self, NonNull}, sync::atomic::{AtomicPtr, AtomicU32, Ordering}, time::Duration
25};
26
27use crossbeam_deque::{Injector, Steal};
28use crossbeam_utils::{atomic::AtomicCell, sync::{Parker, Unparker}, Backoff};
29
30#[derive(Debug)]
34struct InstanceCopyOnWriteInner<ITEM: Send + fmt::Debug>
35{
36 #[cfg(test)]
38 arc_tag: Arc<()>,
39
40 refs: AtomicU32,
42
43 wake_up_lock: AtomicPtr<()>,
46
47 item: ITEM
49}
50
51impl<ITEM: Send + fmt::Debug> InstanceCopyOnWriteInner<ITEM>
52{
53 thread_local!
54 {
55 static BORROWS: RefCell<HashMap<usize, usize>> = RefCell::new(HashMap::with_capacity(10));
58 }
59
60 fn new(item: ITEM) -> Self
62 {
63 return
64 Self
65 {
66 #[cfg(test)]
67 arc_tag: Arc::new(()),
68
69 refs: AtomicU32::new(1),
70
71 wake_up_lock: AtomicPtr::new(ptr::null_mut()),
72
73 item: item,
74 };
75 }
76
77 #[cfg(test)]
79 fn get_weak_tag(&self) -> Weak<()>
80 {
81 return Arc::downgrade(&self.arc_tag);
82 }
83}
84
85#[derive(Debug)]
89struct InstanceCopyOnWriteClone<ITEM: Send + fmt::Debug>
90{
91 inst: NonNull<InstanceCopyOnWriteInner<ITEM>>
93}
94
95
96impl<ITEM: Send + fmt::Debug> Clone for InstanceCopyOnWriteClone<ITEM>
97{
98 #[inline]
100 fn clone(&self) -> Self
101 {
102 let inner = unsafe { self.inst.as_ref() };
103
104 inner.refs.fetch_add(1, Ordering::SeqCst);
105
106 return Self { inst: self.inst };
107 }
108}
109
110
111
112impl<ITEM: Send + fmt::Debug> Drop for InstanceCopyOnWriteClone<ITEM>
113{
114 fn drop(&mut self)
115 {
116 let subed = unsafe{ self.inst.as_ref() }.refs.fetch_sub(1, Ordering::AcqRel);
118
119 if subed == 2
120 {
121 let inst_ref = unsafe{ self.inst.as_ref() };
123
124 let wakeup_ptr = inst_ref.wake_up_lock.swap(ptr::null_mut(), Ordering::Relaxed);
125
126 if wakeup_ptr.is_null() == false
127 {
128 unsafe { Unparker::from_raw(wakeup_ptr.cast_const()) }.unpark();
129 }
130 }
131 else if subed == 1
132 {
133 InstanceCopyOnWriteInner
135 ::<ITEM>
136 ::BORROWS
137 .with_borrow_mut(|v|
138 {
139 v.remove(&self.inst.as_ptr().addr());
141 }
142 );
143
144 drop(unsafe { Box::from_raw(self.inst.as_ptr()) });
145 }
146
147 return;
148 }
149}
150
151impl<ITEM: Send + fmt::Debug> InstanceCopyOnWriteClone<ITEM>
152{
153 fn new(item: ITEM) -> Self
154 {
155 let status = Box::new(InstanceCopyOnWriteInner::new(item));
156
157 return Self{ inst: Box::leak(status).into() };
158 }
159
160 #[inline]
161 fn load_refs(&self) -> u32
162 {
163 return unsafe { self.inst.as_ref() }.refs.load(Ordering::Acquire);
164 }
165
166 #[inline]
167 fn inner(&self) -> &InstanceCopyOnWriteInner<ITEM>
168 {
169 return unsafe { self.inst.as_ref() };
170 }
171
172 #[inline]
173 fn inner_mut(&mut self) -> &mut InstanceCopyOnWriteInner<ITEM>
174 {
175 return unsafe { self.inst.as_mut() };
176 }
177}
178
179#[derive(Clone, Copy, Debug, PartialEq, Eq)]
181pub enum CowGuardError
182{
183 Poisoned,
185
186 ExclusiveLockPending,
189
190 WouldBlock,
192}
193
194impl fmt::Display for CowGuardError
195{
196 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
197 {
198 match self
199 {
200 Self::Poisoned =>
201 write!(f, "poisoned"),
202 Self::ExclusiveLockPending =>
203 write!(f, "exclusive lock pending"),
204 Self::WouldBlock =>
205 write!(f, "wouldblock"),
206 }
207 }
208}
209
210#[derive(Debug)]
212pub struct CowReadGuard<'read, ITEM: Send + fmt::Debug>
213{
214 inst: InstanceCopyOnWriteClone<ITEM>,
216
217 owner_ref: &'read InstanceCopyOnWrite<ITEM>,
219
220 _p_thread_lock: PhantomData<*const ()>,
221}
222
223
224impl<'read, ITEM: Send + fmt::Debug> CowReadGuard<'read, ITEM>
225{
226 #[inline]
247 fn new(owner: &'read InstanceCopyOnWrite<ITEM>, try_borrow: bool) -> Result<CowReadGuard<'read, ITEM>, CowGuardError>
248 {
249 let bkoff = Backoff::new();
250
251 loop
252 {
253 let status =
255 owner.owner_lock.compare_exchange(CowLockStatus::Ok, CowLockStatus::Borrow);
256
257 match status
258 {
259 Ok(CowLockStatus::Ok) =>
260 {
261 let ptr = owner.owner_inner.load(Ordering::Relaxed);
262
263 let cloned_read: InstanceCopyOnWriteClone<ITEM> = unsafe {ptr.as_ref()}.unwrap().clone();
264
265 let _ = owner.owner_lock.compare_exchange(CowLockStatus::Borrow, CowLockStatus::Ok);
267
268 InstanceCopyOnWriteInner::<ITEM>::BORROWS.with_borrow_mut(|v|
270 {
271 v.entry(cloned_read.inst.as_ptr().addr()).and_modify(|v| *v += 1).or_insert(1);
272 }
273 );
274
275 return Ok(
276 Self
277 {
278 inst: cloned_read,
279 owner_ref: owner,
280 _p_thread_lock: PhantomData
281 }
282 );
283 },
284 Err(CowLockStatus::Borrow) =>
285 {
286 bkoff.snooze();
288 continue;
289 },
290 Err(CowLockStatus::Poisoned) =>
291 {
292 return Err(CowGuardError::Poisoned);
293 },
294 Err(CowLockStatus::Park) =>
295 {
296 if try_borrow == false
299 {
300 if bkoff.is_completed() == true
301 {
302 let p = Parker::new();
303 let u = p.unparker().clone();
304
305 owner.park_queue.push(u);
306
307 p.park_timeout(Duration::from_millis(500));
308 }
309 else
310 {
311 bkoff.snooze();
312 }
313 }
314 else
315 {
316 return Err(CowGuardError::WouldBlock);
317 }
318
319 continue;
320 },
321 _ =>
322 panic!("assertion trap: wrong status: {:?}", status),
323 }
324 }
325
326 }
327}
328
329impl<'read, ITEM: Send + fmt::Debug> Deref for CowReadGuard<'read, ITEM>
330{
331 type Target = ITEM;
332
333 fn deref(&self) -> &Self::Target
334 {
335 return & unsafe { self.inst.inst.as_ref()}.item;
336 }
337}
338
339impl<'read, ITEM: Send + fmt::Debug> Drop for CowReadGuard<'read, ITEM>
340{
341 fn drop(&mut self)
342 {
343 InstanceCopyOnWriteInner
345 ::<ITEM>
346 ::BORROWS
347 .with_borrow_mut(|v|
348 {
349 v
350 .get_mut(&self.inst.inst.as_ptr().addr())
351 .map(|v| *v -= 1);
352 }
353 );
354 }
355}
356
357#[derive(Debug)]
365pub struct CowTransactionGuard<'tra, ITEM: Send + fmt::Debug>
366{
367 icow: &'tra InstanceCopyOnWrite<ITEM>,
369
370 new_inst: ITEM,
372
373 cloned_read: CowReadGuard<'tra, ITEM>,
375
376 _p_thread_lock: PhantomData<*const ()>,
378}
379
380impl<'tra, ITEM: Send + fmt::Debug> Deref for CowTransactionGuard<'tra, ITEM>
381{
382 type Target = ITEM;
383
384 fn deref(&self) -> &Self::Target
385 {
386 return &self.new_inst;
387 }
388}
389
390impl<'tra, ITEM: Send + fmt::Debug> DerefMut for CowTransactionGuard<'tra, ITEM>
391{
392 fn deref_mut(&mut self) -> &mut Self::Target
393 {
394 return &mut self.new_inst;
395 }
396}
397
398
399impl<'tra, ITEM: Send + fmt::Debug> CowTransactionGuard<'tra, ITEM>
400{
401 pub
403 fn get_previous(&self) -> &ITEM
404 {
405 return &self.cloned_read;
406 }
407
408 pub
431 fn completed(self, try_update: bool) -> Result<(),(Self, CowGuardError)>
432 {
433 let bkoff = Backoff::new();
434
435 loop
436 {
437 let status =
438 self.icow.owner_lock.compare_exchange(CowLockStatus::Ok, CowLockStatus::Borrow);
439
440 match status
441 {
442 Ok(CowLockStatus::Ok) =>
443 {
444 let boxed_inner = Box::new(InstanceCopyOnWriteClone::new(self.new_inst));
445
446 let prev_inner = self.icow.owner_inner.swap(Box::leak(boxed_inner), Ordering::Relaxed);
447
448 drop(unsafe { Box::from_raw(prev_inner) });
449
450 let _ = self.icow.owner_lock.compare_exchange(CowLockStatus::Borrow, CowLockStatus::Ok);
451
452 return Ok(());
453 },
454 Err(CowLockStatus::Poisoned) =>
455 {
456 return Err((self, CowGuardError::Poisoned));
457 },
458 Err(CowLockStatus::Borrow) =>
459 {
460 bkoff.snooze();
461 continue;
462 },
463 Err(CowLockStatus::Park) =>
464 {
465 if try_update == false
466 {
467 bkoff.snooze();
468 continue;
469 }
470 else
471 {
472 return Err((self, CowGuardError::ExclusiveLockPending));
474 }
475 },
476 _ =>
477 panic!("assertion trap: CowTransactionGuard::complete() unknwon status: {:?}", status)
478 }
479 }
480 }
481}
482
483#[derive(Clone, Copy, Debug, PartialEq, Eq)]
485pub enum NoCowGuardErr
486{
487 AlreadyLocked,
490
491 Borrowed,
494
495 Poisoned }
498
499impl fmt::Display for NoCowGuardErr
500{
501 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
502 {
503 match self
504 {
505 NoCowGuardErr::AlreadyLocked =>
506 write!(f, "already locked"),
507 NoCowGuardErr::Borrowed =>
508 write!(f, "borrowed"),
509 NoCowGuardErr::Poisoned =>
510 write!(f, "poisoned"),
511 }
512 }
513}
514
515#[derive(Clone, Debug)]
518struct NoCowPanicGuard
519{
520 #[cfg(all(panic = "unwind"))]
521 panicking: bool,
522}
523
524#[cfg(all(panic = "unwind"))]
525impl Default for NoCowPanicGuard
526{
527 fn default() -> Self
528 {
529 use std::thread;
530
531 Self { panicking: thread::panicking() }
532 }
533}
534
535
536#[derive(Debug)]
545pub struct NoCowGuard<'lock, ITEM: Send + fmt::Debug>
546{
547 poison_guard: NoCowPanicGuard,
549
550 inst: InstanceCopyOnWriteClone<ITEM>,
552
553 icow: &'lock InstanceCopyOnWrite<ITEM>,
555}
556
557impl<'lock, ITEM: Send + fmt::Debug> Drop for NoCowGuard<'lock, ITEM>
558{
559 fn drop(&mut self)
560 {
561 #[cfg(all(panic = "unwind"))]
563 let res =
564 if self.poison_guard.panicking == false && std::thread::panicking() == true
565 {
566 self.icow.owner_lock.compare_exchange(CowLockStatus::Park, CowLockStatus::Poisoned)
567 }
568 else
569 {
570 self.icow.owner_lock.compare_exchange(CowLockStatus::Park, CowLockStatus::Ok)
571 };
572
573 #[cfg(not(all(panic = "unwind")))]
574 let res =
575 self.icow.owner_lock.compare_exchange(CowLockStatus::Park, CowLockStatus::Ok);
576
577
578 if let Err(e) = res
579 {
580 panic!("asserion trap: expected CowLockStatus::Ok, got {}", e);
581 }
582
583 loop
584 {
585 match self.icow.park_queue.steal()
586 {
587 Steal::Empty =>
588 break,
589 Steal::Success(unp) =>
590 unp.unpark(),
591 Steal::Retry =>
592 {},
593 }
594 }
595
596 return;
597 }
598}
599
600impl<'lock, ITEM: Send + fmt::Debug> Deref for NoCowGuard<'lock, ITEM>
601{
602 type Target = ITEM;
603
604 fn deref(&self) -> &Self::Target
605 {
606 return & unsafe { self.inst.inst.as_ref() }.item;
607 }
608}
609
610impl<'lock, ITEM: Send + fmt::Debug> DerefMut for NoCowGuard<'lock, ITEM>
611{
612 fn deref_mut(&mut self) -> &mut Self::Target
613 {
614 return &mut unsafe { self.inst.inst.as_mut() }.item;
615 }
616}
617
618impl<'lock, ITEM: Send + fmt::Debug> NoCowGuard<'lock, ITEM>
619{
620 #[inline]
642 fn new(owner: &'lock InstanceCopyOnWrite<ITEM>, depoison: bool) -> Result<NoCowGuard<'lock, ITEM>, NoCowGuardErr>
643 {
644
645 let status =
646 if depoison == false
647 {
648 CowLockStatus::Ok
649 }
650 else
651 {
652 CowLockStatus::Poisoned
653 };
654
655 let poison_guard = NoCowPanicGuard::default();
656
657 let bkoff = Backoff::new();
658
659 loop
660 {
661 let status =
662 owner.owner_lock.compare_exchange(status, CowLockStatus::Park);
663
664 if let Ok(CowLockStatus::Ok) = status
665 {
666 let ptr = owner.owner_inner.load(Ordering::Relaxed);
667 let ptr_ref = unsafe{ ptr.as_ref() }.unwrap();
668
669 if
671 InstanceCopyOnWriteInner
672 ::<ITEM>
673 ::BORROWS
674 .with_borrow(|v|
675 v.get(&ptr_ref.inst.as_ptr().addr()).map_or(true, |f| f.eq(&0))
676 )
677 == false
678 {
679 let _ = owner.owner_lock.compare_exchange(CowLockStatus::Park, CowLockStatus::Ok);
680
681 return Err(NoCowGuardErr::Borrowed);
682 }
683
684 let mut unparker_ptr: Option<*const ()> = None;
685
686 let p = Parker::new();
687
688 loop
690 {
691
692
693 let ptr_refs = ptr_ref.load_refs();
694
695
696 if ptr_refs == 1
697 {
698 break;
699 }
700 else if ptr_refs == 0
701 {
702 panic!("assetion trap: ptr_rfs == 0");
704 }
705
706 if bkoff.is_completed() == true
707 {
708
709 if let None = unparker_ptr
712 {
713 let cloned_read: InstanceCopyOnWriteClone<ITEM> = ptr_ref.clone();
714
715 let unpark_ptr = Unparker::into_raw(p.unparker().clone());
716
717 unparker_ptr.replace(unpark_ptr);
718
719 cloned_read.inner().wake_up_lock.store(unpark_ptr.cast_mut(), Ordering::Relaxed);
720 }
721
722 p.park_timeout(Duration::from_millis(10));
723 }
724 else
725 {
726 bkoff.snooze();
727 }
728 }
729
730 if let Some(_) = unparker_ptr
731 {
732 let unpark_ptr = ptr_ref.inner().wake_up_lock.swap(ptr::null_mut(), Ordering::Relaxed).cast_const();
733
734 if unpark_ptr.is_null() == false
735 {
736 drop( unsafe { Unparker::from_raw(unpark_ptr) });
737 }
738 }
739
740 return Ok(
741 Self
742 {
743 poison_guard: poison_guard,
744 inst: ptr_ref.clone(),
745 icow: owner,
746 }
747 );
748 }
749 else if let Err(CowLockStatus::Poisoned) = status
750 {
751 return Err(NoCowGuardErr::Poisoned);
752 }
753 else if let Err(CowLockStatus::Borrow) = status
754 {
755 bkoff.snooze();
756 continue;
757 }
758 else
759 {
760 return Err(NoCowGuardErr::AlreadyLocked);
761 }
762 } }
765}
766
767#[derive(Clone, Copy, Debug, PartialEq, Eq)]
769enum CowLockStatus
770{
771 Ok, Borrow, Park, Poisoned
772}
773
774impl fmt::Display for CowLockStatus
775{
776 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
777 {
778 match self
779 {
780 Self::Ok =>
781 write!(f, "OK"),
782 Self::Borrow =>
783 write!(f, "BORROW"),
784 Self::Park =>
785 write!(f, "PARK"),
786 Self::Poisoned =>
787 write!(f, "POISONED")
788 }
789 }
790}
791
792#[derive(Debug)]
835pub struct InstanceCopyOnWrite<ITEM: Send + fmt::Debug>
836{
837 owner_lock: AtomicCell<CowLockStatus>,
839
840 park_queue: Injector<Unparker>,
842
843 owner_inner: AtomicPtr<InstanceCopyOnWriteClone<ITEM>>,
846}
847
848impl<ITEM: Send + fmt::Debug> Drop for InstanceCopyOnWrite<ITEM>
849{
850 fn drop(&mut self)
851 {
852 let status =
853 self.owner_lock.compare_exchange(CowLockStatus::Ok, CowLockStatus::Borrow);
854
855 if let Ok(CowLockStatus::Ok) = status
856 {
857 let ptr = self.owner_inner.swap(ptr::null_mut(), Ordering::Relaxed);
858
859 if ptr.is_null() == false
860 {
861 drop(unsafe { Box::from_raw(ptr) });
862 }
863
864 while let Steal::Success(s) = self.park_queue.steal()
865 {
866 s.unpark();
867 }
868
869 return;
870 }
871 else
872 {
873 panic!("assertion trap: destructing InstanceCopyOnWrite while borrowed");
874 }
875 }
876}
877
878impl<ITEM: Send + fmt::Debug> InstanceCopyOnWrite<ITEM>
879{
880 pub
882 fn new(item: ITEM) -> Self
883 {
884 let boxed_inner = Box::new(InstanceCopyOnWriteClone::new(item));
885
886 return
887 Self
888 {
889 owner_lock: AtomicCell::new(CowLockStatus::Ok),
890 park_queue: Injector::new(),
891 owner_inner: AtomicPtr::new( Box::leak(boxed_inner) )
892 };
893 }
894
895 #[inline]
904 pub
905 fn borrow(&self) -> Result<CowReadGuard<'_, ITEM>, CowGuardError>
906 {
907 return CowReadGuard::new(self, false);
908 }
909
910 #[inline]
921 pub
922 fn try_borrow(&self) -> Result<CowReadGuard<'_, ITEM>, CowGuardError>
923 {
924 return CowReadGuard::new(self, true);
925 }
926
927 #[inline]
935 pub
936 fn lock(&self) -> Result<NoCowGuard<'_, ITEM>, NoCowGuardErr>
937 {
938 return NoCowGuard::new(self, false);
939 }
940
941 pub
952 fn remove_poison_lock(&self) -> Result<NoCowGuard<'_, ITEM>, NoCowGuardErr>
953 {
954 return NoCowGuard::new(self, true);
955 }
956
957 pub
972 fn remove_poison_write(&self, new_inst: ITEM) -> Result<(), NoCowGuardErr>
973 {
974 let Ok(_) = self.owner_lock.compare_exchange(CowLockStatus::Poisoned, CowLockStatus::Park)
975 else { return Err( NoCowGuardErr::AlreadyLocked )};
976
977 let boxed_inner = Box::new(InstanceCopyOnWriteClone::new(new_inst));
978
979 let prev_inner = self.owner_inner.swap(Box::leak(boxed_inner), Ordering::Relaxed);
980
981 drop(unsafe { Box::from_raw(prev_inner) });
982
983 let Ok(_) = self.owner_lock.compare_exchange(CowLockStatus::Park, CowLockStatus::Ok)
984 else { return Err(NoCowGuardErr::Poisoned) };
985
986 return Ok(());
987 }
988}
989
990impl<ITEM: Send + fmt::Debug + Copy> InstanceCopyOnWrite<ITEM>
991{
992 pub
999 fn start_copying(&self) -> Result<CowTransactionGuard<'_, ITEM>, CowGuardError>
1000 {
1001 let cloned_read = self.borrow()?;
1002
1003 let new_inst = unsafe { cloned_read.inst.inst.as_ref()}.item;
1004
1005 return Ok(
1006 CowTransactionGuard
1007 {
1008 icow: self,
1009 new_inst: new_inst,
1010 cloned_read: cloned_read,
1011 _p_thread_lock: PhantomData,
1012 }
1013 );
1014 }
1015
1016 pub
1023 fn try_start_copying(&self) -> Result<CowTransactionGuard<'_, ITEM>, CowGuardError>
1024 {
1025 let cloned_read = self.try_borrow()?;
1026
1027 let new_inst = unsafe { cloned_read.inst.inst.as_ref()}.item;
1028
1029 return Ok(
1030 CowTransactionGuard
1031 {
1032 icow: self,
1033 new_inst: new_inst,
1034 cloned_read: cloned_read,
1035 _p_thread_lock: PhantomData,
1036 }
1037 );
1038 }
1039}
1040
1041impl<ITEM: Send + fmt::Debug + Clone> InstanceCopyOnWrite<ITEM>
1042{
1043 pub
1050 fn start_cloning(&self) -> Result<CowTransactionGuard<'_, ITEM>, CowGuardError>
1051 {
1052 let cloned_read = self.borrow()?;
1053
1054 let new_inst = unsafe { cloned_read.inst.inst.as_ref()}.item.clone();
1055
1056 return Ok(
1057 CowTransactionGuard
1058 {
1059 icow: self,
1060 new_inst: new_inst,
1061 cloned_read: cloned_read,
1062 _p_thread_lock: PhantomData,
1063 }
1064 );
1065 }
1066
1067 pub
1074 fn try_start_cloning(&self) -> Result<CowTransactionGuard<'_, ITEM>, CowGuardError>
1075 {
1076 let cloned_read = self.try_borrow()?;
1077
1078 let new_inst = unsafe { cloned_read.inst.inst.as_ref()}.item.clone();
1079
1080 return Ok(
1081 CowTransactionGuard
1082 {
1083 icow: self,
1084 new_inst: new_inst,
1085 cloned_read: cloned_read,
1086 _p_thread_lock: PhantomData,
1087 }
1088 );
1089 }
1090}
1091
1092impl<ITEM: Send + fmt::Debug + Default> InstanceCopyOnWrite<ITEM>
1093{
1094 pub
1101 fn start_default(&self) -> Result<CowTransactionGuard<'_, ITEM>, CowGuardError>
1102 {
1103 let cloned_read = self.borrow()?;
1104
1105 return Ok(
1106 CowTransactionGuard
1107 {
1108 icow: self,
1109 new_inst: ITEM::default(),
1110 cloned_read: cloned_read,
1111 _p_thread_lock: PhantomData,
1112 }
1113 );
1114 }
1115
1116 pub
1124 fn try_start_default(&self) -> Result<CowTransactionGuard<'_, ITEM>, CowGuardError>
1125 {
1126 let cloned_read = self.try_borrow()?;
1127
1128 return Ok(
1129 CowTransactionGuard
1130 {
1131 icow: self,
1132 new_inst: ITEM::default(),
1133 cloned_read: cloned_read,
1134 _p_thread_lock: PhantomData,
1135 }
1136 );
1137 }
1138}
1139
1140impl<ITEM: Send + fmt::Debug> InstanceCopyOnWrite<ITEM>
1141{
1142 pub
1149 fn start_new(&self, new_inst: ITEM) -> Result<CowTransactionGuard<'_, ITEM>, CowGuardError>
1150 {
1151 let cloned_read = self.borrow()?;
1152
1153 return Ok(
1154 CowTransactionGuard
1155 {
1156 icow: self,
1157 new_inst: new_inst,
1158 cloned_read: cloned_read,
1159 _p_thread_lock: PhantomData,
1160 }
1161 );
1162 }
1163
1164 pub
1172 fn try_start_new(&self, new_inst: ITEM) -> Result<CowTransactionGuard<'_, ITEM>, CowGuardError>
1173 {
1174 let cloned_read = self.try_borrow()?;
1175
1176 return Ok(
1177 CowTransactionGuard
1178 {
1179 icow: self,
1180 new_inst: new_inst,
1181 cloned_read: cloned_read,
1182 _p_thread_lock: PhantomData,
1183 }
1184 );
1185 }
1186}
1187
1188#[cfg(test)]
1189mod tests
1190{
1191 use std::{sync::{atomic::Ordering, mpsc, LazyLock, Mutex}, time::{Duration, Instant}};
1192
1193
1194 use crate::{CowGuardError, InstanceCopyOnWrite, InstanceCopyOnWriteInner, NoCowGuardErr};
1195
1196 #[derive(Debug, Copy, Clone)]
1197 struct TestStruct
1198 {
1199 start: u64,
1200 stop: u64
1201 }
1202
1203 impl TestStruct
1204 {
1205 fn new(val: u64, val2: u64) -> Self
1206 {
1207 return Self{ start: val, stop: val2 };
1208 }
1209 }
1210
1211 #[test]
1212 fn test_bench()
1213 {
1214 let val =
1215 InstanceCopyOnWrite::new(TestStruct::new(1, 2));
1216
1217 for _ in 0..10
1218 {
1219 let inst_glob = Instant::now();
1220 let test_borrow = val.borrow().unwrap();
1221
1222 let e_g = inst_glob.elapsed();
1223 println!("{:?}", e_g);
1224 }
1225
1226 println!("mux");
1227
1228 let mux = Mutex::new(TestStruct::new(1, 2));
1229
1230 for _ in 0..10
1231 {
1232 let inst_glob = Instant::now();
1233 let test_borrow = val.lock().unwrap();
1234
1235 let e_g = inst_glob.elapsed();
1236 println!("{:?}", e_g);
1237 }
1238 }
1239
1240 #[test]
1241 fn test_simple_nocow()
1242 {
1243
1244 let val =
1245 InstanceCopyOnWrite::new(TestStruct::new(1, 2));
1246
1247 let test_borrow = val.borrow().unwrap().start;
1248
1249
1250 assert_eq!(test_borrow, 1);
1251
1252 let lock = val.lock();
1253
1254 assert_eq!(lock.is_ok(), true);
1255
1256 let mut lock = lock.unwrap();
1257
1258 let lock_dup = val.lock();
1259
1260 assert_eq!(lock_dup.is_err(), true);
1261
1262 lock.start = 2;
1263 lock.stop = 3;
1264
1265 drop(lock);
1266
1267 let borrow = val.borrow().unwrap();
1268
1269 assert_eq!(borrow.start, 2);
1270 assert_eq!(borrow.stop, 3);
1271
1272 }
1273
1274 #[test]
1275 fn test_simple_multithread_lock_parking_test()
1276 {
1277 static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> =
1278 LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2)));
1279
1280 let borrow1 = VAL.borrow().unwrap();
1281 assert_eq!(borrow1.start, 1);
1282 assert_eq!(borrow1.stop, 2);
1283
1284 let inst_glob = Instant::now();
1285
1286 let thread1 =
1287 std::thread::spawn(move ||
1288 {
1289 let mut lock = VAL.lock().unwrap();
1290
1291
1292
1293 lock.start = 5;
1294 lock.stop = 6;
1295 std::thread::sleep(Duration::from_millis(944));
1298
1299 drop(lock);
1300 }
1301 );
1302
1303 drop(borrow1);
1304
1305 std::thread::sleep(Duration::from_micros(1));
1306 let inst = Instant::now();
1307
1308 let borrow2 = VAL.borrow().unwrap();
1309
1310 let e_g = inst_glob.elapsed();
1311 let e_b = inst.elapsed();
1312
1313 println!("{:?} {:?}", e_g, e_b);
1314
1315 let dur = e_g - e_b;
1316 println!("{}", dur.as_millis());
1317 assert_eq!(dur.as_millis(), 0);
1318 }
1319
1320 #[test]
1322 fn test_simple_multithread_lock_parking_test2()
1323 {
1324 static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> =
1325 LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2)));
1326
1327 let borrow1 = VAL.borrow().unwrap();
1328 assert_eq!(borrow1.start, 1);
1329 assert_eq!(borrow1.stop, 2);
1330
1331
1332 let inst_glob = Instant::now();
1333 let thread1 =
1334 std::thread::spawn(move ||
1335 {
1336 let inst_loc = Instant::now();
1337 let mut lock = VAL.lock().unwrap();
1338 let e_g = inst_loc.elapsed();
1339
1340
1341 lock.start = 5;
1342 lock.stop = 6;
1343 drop(lock);
1348
1349 return e_g;
1350 }
1351 );
1352
1353 std::thread::sleep(Duration::from_millis(944));
1354 drop(borrow1);
1355 let e_g = inst_glob.elapsed();
1356
1357 let e_th = thread1.join().unwrap();
1358 println!("{:?} {:?}", e_g, e_th);
1359
1360 let dur = e_g - e_th;
1361 println!("{}", dur.as_millis());
1362 assert_eq!(dur.as_millis(), 0);
1363 }
1364
1365 #[test]
1367 fn test_simple_multithread_lock_comp()
1368 {
1369 static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> =
1370 LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2)));
1371
1372
1373 let borrow1 = VAL.borrow().unwrap();
1374 assert_eq!(borrow1.start, 1);
1375 assert_eq!(borrow1.stop, 2);
1376
1377 let (mpsc_send, mpsc_rcv) = mpsc::channel::<u64>();
1378 let (mpsc_send2, mpsc_rcv2) = mpsc::channel::<u64>();
1379
1380 let thread1 =
1381 std::thread::spawn(move ||
1382 {
1383 for _ in 0..10000
1384 {
1385 let mut lock =
1386 loop
1387 {
1388 let lock = VAL.lock();
1389
1390 if let Err(NoCowGuardErr::AlreadyLocked) = lock
1391 {
1392 std::thread::sleep(Duration::from_nanos(100));
1393 continue;
1394 }
1395
1396 break lock.unwrap();
1397 };
1398
1399
1400
1401 lock.start = 5;
1402 lock.stop = 6;
1403
1404 drop(lock);
1405 let _ = mpsc_send.send(1);
1411
1412 let _ = mpsc_rcv2.recv();
1413
1414 std::thread::sleep(Duration::from_nanos(1000));
1415 }
1416 }
1417 );
1418
1419 drop(borrow1);
1420
1421 for i in 0..10000
1422 {
1423 let val = mpsc_rcv.recv();
1424 let e_b =
1429 {
1430 let inst = Instant::now();
1431 let borrow2 = VAL.borrow().unwrap();
1432
1433 let e_b = inst.elapsed();
1434
1435 assert_eq!(borrow2.start, 5);
1436 assert_eq!(borrow2.stop, 6);
1437
1438 drop(borrow2);
1439
1440 e_b
1441 };
1442 let _ = mpsc_send2.send(1);
1443
1444 let inst = Instant::now();
1445 let mut lock = VAL.lock().unwrap();
1446 let e_l = inst.elapsed();
1447
1448 lock.start = 1;
1449 lock.stop = 2;
1450
1451 drop(lock);
1452
1453 println!("b: {:?} e: {:?}", e_b, e_l);
1454 assert!(e_b.as_millis() == 0);
1455 assert!(e_l.as_millis() == 0);
1456 }
1457
1458 let borrow1 = VAL.borrow().unwrap();
1459 assert_eq!(borrow1.start, 1);
1460 assert_eq!(borrow1.stop, 2);
1461
1462 thread1.join().unwrap();
1463
1464 }
1465
1466
1467 #[test]
1468 fn test_simple_copy()
1469 {
1470 let val =
1471 InstanceCopyOnWrite::new(TestStruct::new(1, 2));
1472
1473 let s = Instant::now();
1474 let borrow1 = val.borrow().unwrap();
1475 let e = s.elapsed();
1476
1477 let s = Instant::now();
1478 let borrow2 = val.borrow().unwrap();
1479 let e2 = s.elapsed();
1480
1481 println!("{:?} {:?}", e, e2);
1482
1483 assert_eq!(borrow1.start, 1);
1484 assert_eq!(borrow1.stop, 2);
1485
1486 assert_eq!(borrow1.start, borrow2.start);
1487 assert_eq!(borrow1.stop, borrow2.stop);
1488
1489 let mut transaction = val.start_copying().unwrap();
1490
1491 transaction.start = 5;
1492 transaction.stop = 6;
1493
1494 assert_eq!(borrow1.start, 1);
1495 assert_eq!(borrow1.stop, 2);
1496
1497 transaction.completed(false).unwrap();
1498
1499 assert_eq!(borrow1.start, 1);
1500 assert_eq!(borrow1.stop, 2);
1501
1502 let borrow3 = val.borrow().unwrap();
1503
1504 assert_eq!(borrow3.start, 5);
1505 assert_eq!(borrow3.stop, 6);
1506
1507 drop(borrow1);
1508
1509 let refs = borrow2.inst.inner().refs.load(std::sync::atomic::Ordering::Relaxed);
1510 assert_eq!(refs, 1);
1511
1512 let weak_tag = borrow2.inst.inner().get_weak_tag();
1513
1514 {
1515 let arc_upg = weak_tag.upgrade();
1516 assert_eq!(arc_upg.is_some(), true);
1517 }
1518
1519 drop(borrow2);
1520
1521 {
1522 let arc_upg = weak_tag.upgrade();
1523 assert_eq!(arc_upg.is_none(), true);
1524 }
1525
1526 }
1527
1528 #[derive(Debug, Default)]
1529 struct TestStructDef
1530 {
1531 start: Option<u64>,
1532 stop: Option<u64>,
1533 }
1534
1535 impl TestStructDef
1536 {
1537 fn new(val: u64, val2: u64) -> Self
1538 {
1539 return Self{ start: Some(val), stop: Some(val2) };
1540 }
1541 }
1542
1543
1544 #[test]
1545 fn test_simple_default()
1546 {
1547 let val =
1548 InstanceCopyOnWrite::new(TestStructDef::new(1, 2));
1549
1550 let s = Instant::now();
1551 let borrow1 = val.borrow().unwrap();
1552 let e = s.elapsed();
1553
1554 for _ in 0..10
1555 {
1556 let s = Instant::now();
1557 let borrow2 = val.borrow().unwrap();
1558 let e2 = s.elapsed();
1559 println!("{:?} {:?}", e, e2);
1560
1561 }
1562
1563 let s = Instant::now();
1564 let borrow2 = val.borrow().unwrap();
1565 let e2 = s.elapsed();
1566 println!("{:?} {:?}", e, e2);
1567
1568 assert_eq!(borrow1.start, Some(1));
1569 assert_eq!(borrow1.stop, Some(2));
1570
1571 assert_eq!(borrow1.start, borrow2.start);
1572 assert_eq!(borrow1.stop, borrow2.stop);
1573
1574 let mut transaction = val.start_default().unwrap();
1575
1576 transaction.start = Some(5);
1577 transaction.stop = Some(6);
1578
1579 assert_eq!(borrow1.start, Some(1));
1580 assert_eq!(borrow1.stop, Some(2));
1581
1582 transaction.completed(false).unwrap();
1583
1584 assert_eq!(borrow1.start, Some(1));
1585 assert_eq!(borrow1.stop, Some(2));
1586
1587 let borrow3 = val.borrow().unwrap();
1588
1589 assert_eq!(borrow3.start, Some(5));
1590 assert_eq!(borrow3.stop, Some(6));
1591
1592 drop(borrow1);
1593
1594 let refs = borrow2.inst.inner().refs.load(std::sync::atomic::Ordering::Relaxed);
1595 assert_eq!(refs, 1);
1596
1597 let weak_tag = borrow2.inst.inner().get_weak_tag();
1598
1599 {
1600 let arc_upg = weak_tag.upgrade();
1601 assert_eq!(arc_upg.is_some(), true);
1602 }
1603
1604 drop(borrow2);
1605
1606 {
1607 let arc_upg = weak_tag.upgrade();
1608 assert_eq!(arc_upg.is_none(), true);
1609 }
1610
1611 }
1612
1613 #[test]
1614 fn test_simple_multithread_clone()
1615 {
1616 static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> =
1617 LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2)));
1618
1619
1620 let borrow1 = VAL.borrow().unwrap();
1621
1622 let thread1 =
1623 std::thread::spawn(move ||
1624 {
1625 let borrow1 = VAL.borrow().unwrap();
1626
1627 let mut transaction = VAL.start_copying().unwrap();
1628
1629 transaction.start = 5;
1630 transaction.stop = 6;
1631
1632 transaction.completed(false).unwrap();
1633
1634 let borrow2 = VAL.borrow().unwrap();
1635
1636 assert_eq!(borrow1.start, 1);
1637 assert_eq!(borrow1.stop, 2);
1638
1639 assert_eq!(borrow2.start, 5);
1640 assert_eq!(borrow2.stop, 6);
1641 }
1642 );
1643
1644 let borrow2 = VAL.borrow().unwrap();
1645 let borrow3 = VAL.borrow().unwrap();
1646
1647 assert_eq!(borrow1.start, 1);
1648 assert_eq!(borrow1.stop, 2);
1649
1650 thread1.join().unwrap();
1651
1652 drop(borrow2);
1653 let weak_tag = borrow3.inst.inner().get_weak_tag();
1654 drop(borrow3);
1655
1656 {
1657 let arc_upg = weak_tag.upgrade();
1658 assert_eq!(arc_upg.is_some(), true);
1659 }
1660
1661
1662 }
1663
1664 #[test]
1665 fn test_simple_multithread_clone_compl()
1666 {
1667 static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> =
1668 LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2)));
1669
1670
1671
1672
1673 for _ in 0..100000
1674 {
1675 let borrow1 = VAL.borrow().unwrap();
1676 assert_eq!(borrow1.start, 1);
1677 assert_eq!(borrow1.stop, 2);
1678
1679 let (mpsc_send, mpsc_rcv) = mpsc::channel::<u64>();
1680
1681 let thread1 =
1682 std::thread::spawn(move ||
1683 {
1684 let borrow1 = VAL.borrow().unwrap();
1685
1686 let mut transaction = VAL.start_copying().unwrap();
1687
1688 transaction.start = 5;
1689 transaction.stop = 6;
1690
1691 let _ = mpsc_send.send(1);
1692
1693 std::thread::sleep(Duration::from_micros(1));
1694 transaction.completed(false).unwrap();
1695
1696 let borrow2 = VAL.borrow().unwrap();
1697
1698 assert_eq!(borrow1.start, 1);
1699 assert_eq!(borrow1.stop, 2);
1700
1701 assert_eq!(borrow2.start, 5);
1702 assert_eq!(borrow2.stop, 6);
1703 }
1704 );
1705
1706 let _ = mpsc_rcv.recv();
1707
1708 for _ in 0..100000000
1709 {
1710 let borrow2 = VAL.borrow().unwrap();
1711
1712 if borrow2.start == 1
1713 {
1714 continue;
1715 }
1716 else
1717 {
1718 break;
1719 }
1720 }
1721
1722 let borrow1 = VAL.borrow().unwrap();
1723 assert_eq!(borrow1.start, 5);
1724 assert_eq!(borrow1.stop, 6);
1725
1726 thread1.join().unwrap();
1727
1728 let mut transaction = VAL.start_copying().unwrap();
1729 transaction.start = 1;
1730 transaction.stop = 2;
1731 transaction.completed(false).unwrap();
1732 }
1733
1734 }
1735
1736 #[test]
1737 fn test_simple_multithread_clone_compl_fast()
1738 {
1739 static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> =
1740 LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2)));
1741
1742
1743
1744
1745 for i in 0..100000
1746 {
1747 let borrow1 = VAL.borrow().unwrap();
1748 assert_eq!(borrow1.start, 1);
1749 assert_eq!(borrow1.stop, 2);
1750
1751 let (mpsc_send, mpsc_rcv) = mpsc::channel::<u64>();
1752
1753 let thread1 =
1754 std::thread::spawn(move ||
1755 {
1756 let borrow1 = VAL.borrow().unwrap();
1757
1758 let mut transaction = VAL.start_copying().unwrap();
1759
1760 transaction.start = 5;
1761 transaction.stop = 6;
1762
1763 let _ = mpsc_send.send(1);
1764
1765 std::thread::sleep(Duration::from_nanos(100001-i));
1766 transaction.completed(false).unwrap();
1767
1768 let borrow2 = VAL.borrow().unwrap();
1769
1770 assert_eq!(borrow1.start, 1);
1771 assert_eq!(borrow1.stop, 2);
1772
1773 assert_eq!(borrow2.start, 5);
1774 assert_eq!(borrow2.stop, 6);
1775 }
1776 );
1777
1778 let _ = mpsc_rcv.recv();
1779
1780 for _ in 0..100000000
1781 {
1782 let borrow2 = VAL.borrow().unwrap();
1783
1784 if borrow2.start == 1
1785 {
1786 continue;
1787 }
1788 else
1789 {
1790 break;
1791 }
1792 }
1793
1794 let borrow1 = VAL.borrow().unwrap();
1795 assert_eq!(borrow1.start, 5);
1796 assert_eq!(borrow1.stop, 6);
1797
1798 thread1.join().unwrap();
1799
1800 let mut transaction = VAL.start_copying().unwrap();
1801 transaction.start = 1;
1802 transaction.stop = 2;
1803 transaction.completed(false).unwrap();
1804 }
1805
1806 }
1807
1808 #[test]
1809 fn test_simple_multithread_clone_compl2()
1810 {
1811 static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> =
1812 LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2)));
1813
1814
1815
1816
1817 let borrow1 = VAL.borrow().unwrap();
1818 assert_eq!(borrow1.start, 1);
1819 assert_eq!(borrow1.stop, 2);
1820
1821 let (mpsc_send, mpsc_rcv) = mpsc::channel::<u64>();
1822 let (mpsc_send2, mpsc_rcv2) = mpsc::channel::<u64>();
1823
1824 let thread1 =
1825 std::thread::spawn(move ||
1826 {
1827 for _ in 0..1000
1828 {
1829 let _ = mpsc_rcv2.recv();
1830 let borrow1 = VAL.borrow().unwrap();
1831
1832 let mut transaction = VAL.start_copying().unwrap();
1833
1834 transaction.start = 5;
1835 transaction.stop = 6;
1836
1837
1838
1839 std::thread::sleep(Duration::from_nanos(1001));
1840 transaction.completed(false).unwrap();
1841
1842 let borrow2 = VAL.borrow().unwrap();
1843
1844
1845 assert_eq!(borrow1.start, 1);
1846 assert_eq!(borrow1.stop, 2);
1847
1848 assert_eq!(borrow2.start, 5);
1849 assert_eq!(borrow2.stop, 6);
1850
1851 let _ = mpsc_send.send(1);
1852 }
1853 }
1854 );
1855
1856
1857
1858 for x in 0..1000
1859 {
1860 println!("{}", x);
1861 mpsc_send2.send(1).unwrap();
1862 let _ = mpsc_rcv.recv();
1863
1864 let borrow1 = VAL.borrow().unwrap();
1865 assert_eq!(borrow1.start, 5);
1866 assert_eq!(borrow1.stop, 6);
1867
1868 let mut transaction = VAL.start_copying().unwrap();
1869 transaction.start = 1;
1870 transaction.stop = 2;
1871 transaction.completed(false).unwrap();
1872
1873 let borrow1 = VAL.borrow().unwrap();
1874 assert_eq!(borrow1.start, 1);
1875 assert_eq!(borrow1.stop, 2);
1876
1877 }
1878
1879
1880
1881 thread1.join().unwrap();
1882
1883
1884 }
1885
1886
1887 #[test]
1888 fn test_thread_local()
1889 {
1890 static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> =
1891 LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2)));
1892
1893 static VAL2: LazyLock<InstanceCopyOnWrite<TestStruct>> =
1894 LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2)));
1895
1896 static VAL3: LazyLock<InstanceCopyOnWrite<TestStruct>> =
1897 LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2)));
1898
1899 let borrow1 = VAL.borrow().unwrap();
1900 assert_eq!(borrow1.start, 1);
1901 assert_eq!(borrow1.stop, 2);
1902
1903 let borrow_ptr_0 = borrow1.inst.inst.as_ptr().addr();
1904
1905 let thread1 =
1906 std::thread::spawn(move ||
1907 {
1908 let b = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| v.get(&borrow_ptr_0).map(|v| *v).clone());
1909
1910 return b;
1911 }
1912 );
1913
1914 let thread_borrow = thread1.join().unwrap();
1915
1916 let local_borrow = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| *(v.get(&borrow_ptr_0).unwrap()));
1917
1918 println!("tthread: {:?}, local: {}", thread_borrow, local_borrow);
1919
1920 assert_eq!(thread_borrow.is_none(), true);
1921 assert_eq!(local_borrow, 1);
1922
1923 drop(borrow1);
1924
1925 let local_borrow = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| *(v.get(&borrow_ptr_0).unwrap()));
1926
1927 println!("tthread: {:?}, local: {}", thread_borrow, local_borrow);
1928 assert_eq!(local_borrow, 0);
1929
1930
1931 let borrow1 = VAL.borrow().unwrap();
1933 assert_eq!(borrow1.start, 1);
1934 assert_eq!(borrow1.stop, 2);
1935
1936 let res = VAL.lock();
1937 assert_eq!(Some(NoCowGuardErr::Borrowed), res.err());
1938
1939 drop(borrow1);
1940
1941 let res1 = VAL2.lock();
1943 assert_eq!(true, res1.is_ok(), "{:?}", res1);
1944
1945 let borrow_ptr_1 = res1.as_ref().unwrap().inst.inst.as_ptr().addr();
1946
1947 let res2 = VAL2.lock();
1948 assert_eq!(Some(NoCowGuardErr::AlreadyLocked), res2.err());
1949
1950 let thread1 =
1952 std::thread::spawn(move ||
1953 {
1954 let borrow1 = VAL2.try_borrow();
1955 assert_eq!(borrow1.err(), Some(CowGuardError::WouldBlock));
1956
1957 let borrow1 = VAL.borrow().unwrap();
1958 assert_eq!(borrow1.start, 1);
1959 assert_eq!(borrow1.stop, 2);
1960
1961 let b = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| v.get(&borrow_ptr_0).map(|v| *v).clone());
1962
1963 let mut clone = VAL3.start_cloning().unwrap();
1964
1965 let borrow_ptr_2 = VAL3.owner_inner.load(Ordering::Relaxed).addr();
1966
1967 clone.start = 3;
1968
1969 clone.completed(false).unwrap();
1970
1971 let b2 = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| v.get(&borrow_ptr_1).map(|v| *v).clone());
1972
1973 let b3 = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| v.get(&borrow_ptr_2).map(|v| *v).clone());
1974
1975 return (b, b2, b3);
1976 }
1977 );
1978
1979
1980 let borrow_ptr_2 = VAL3.owner_inner.load(Ordering::Relaxed).addr();
1981
1982 let local_borrow1 = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| (v.get(&borrow_ptr_0).map(|v| *v).clone()));
1983 let local_borrow2 = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| (v.get(&borrow_ptr_1).map(|v| *v).clone()));
1984 let local_borrow3 = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| (v.get(&borrow_ptr_2).map(|v| *v).clone()));
1985
1986 let (thread_borrow1, thread_borrow2, thread_borrow3) = thread1.join().unwrap();
1987 drop(res1.unwrap());
1988
1989 assert_eq!(Some(0), local_borrow1);
1990 assert_eq!(Some(1), thread_borrow1);
1991
1992 assert_eq!(None, thread_borrow2);
1993 assert_eq!(None, local_borrow2);
1994
1995 assert_eq!(None, thread_borrow3);
1996 assert_eq!(None, local_borrow3);
1997 }
1998
1999
2000 #[test]
2003 #[should_panic(expected = "test panic1")]
2004 fn test_thread_poison()
2005 {
2006 static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> =
2007 LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2)));
2008
2009
2010 let borrow1 = VAL.borrow().unwrap();
2011 assert_eq!(borrow1.start, 1);
2012 assert_eq!(borrow1.stop, 2);
2013
2014
2015 let thread1 =
2016 std::thread::spawn(move ||
2017 {
2018 let mut lock = VAL.lock().unwrap();
2019 lock.start = 2;
2020 std::thread::sleep(Duration::from_micros(1));
2021
2022 panic!("test panic1");
2023 }
2024 );
2025
2026 drop(borrow1);
2027
2028 let thread_res = thread1.join();
2029
2030 let borrow = VAL.borrow();
2031 assert_eq!(Some(CowGuardError::Poisoned), borrow.err());
2032
2033 let lock = VAL.lock();
2034 assert_eq!(Some(NoCowGuardErr::Poisoned), lock.err());
2035
2036 let transaction = VAL.start_copying();
2037 assert_eq!(Some(CowGuardError::Poisoned), transaction.err());
2038
2039 println!("{:?}", thread_res);
2040
2041 panic!("test panic1");
2042 }
2043
2044 #[test]
2045 fn test_main_drop()
2046 {
2047 let val =
2048 InstanceCopyOnWrite::new(TestStruct::new(1, 2));
2049
2050 {
2051 let test_borrow = val.borrow().unwrap().start;
2052
2053 assert_eq!(test_borrow, 1);
2054 }
2055
2056 {
2057 let lock = val.lock();
2058
2059 assert_eq!(lock.is_ok(), true);
2060
2061 let mut lock = lock.unwrap();
2062
2063 let lock_dup = val.lock();
2064
2065 assert_eq!(lock_dup.is_err(), true);
2066
2067 lock.start = 2;
2068 lock.stop = 3;
2069
2070 drop(lock);
2071 }
2072
2073 {
2074 let borrow = val.borrow().unwrap();
2075
2076 drop(borrow);
2077 }
2078
2079 drop(val);
2080
2081 return;
2082 }
2083}
2084