instance_copy_on_write/cow_mutex.rs
1/*-
2 * instance-copy-on-write - a synchronization primitive based on copy-on-write.
3 *
4 * Copyright (C) 2025 Aleksandr Morozov alex@
5 *
6 * The scram-rs crate can be redistributed and/or modified
7 * under the terms of either of the following licenses:
8 *
9 * 1. the Mozilla Public License Version 2.0 (the “MPL”) OR
10 *
11 * 2. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
12 */
13
14#[cfg(test)]
15use std::sync::Weak;
16use std::{fmt, ops::{Deref, DerefMut}, sync::{Arc, RwLock, RwLockWriteGuard, TryLockError}};
17
18use crossbeam_utils::Backoff;
19
20use crate::{ICoWError, ICoWLockTypes};
21
22
23/// A read only guard. Implements [Deref] only. The guarded value is valid
24/// all the time, even if the inner value was updated. The updated value
25/// will not be visible in the current instance until `re-read` is
26/// performed.
27#[derive(Debug)]
28pub struct ICoWRead<'read, ITEM: fmt::Debug + Send>
29{
30 /// Guarded value.
31 item: Arc<ITEM>,
32
33 /// A bind to base.
34 bind: &'read ICoW<ITEM>
35}
36
37#[cfg(test)]
38impl<'read, ITEM: fmt::Debug + Send> ICoWRead<'read, ITEM>
39{
40 fn weak(&self) -> Weak<ITEM>
41 {
42 return Arc::downgrade(&self.item);
43 }
44}
45
46impl<'read, ITEM: fmt::Debug + Send> Deref for ICoWRead<'read, ITEM>
47{
48 type Target = ITEM;
49
50 fn deref(&self) -> &Self::Target
51 {
52 return &self.item;
53 }
54}
55
56
57/// A write-guard which holds new value to which the new values are written. And
58/// previous value too. This type of guard is not exclusive, so it does not prevent
59/// multiple CoW operations. Normally, if some object which may be written
60/// simultaniously i.e lost connection to remote server and reconnect is required,
61/// the `exclusive` lock would be more desirable.
62#[derive(Debug)]
63pub struct ICoWCopy<'copy, ITEM: fmt::Debug + Send>
64{
65 /// A reference to previous value
66 prev_item: ICoWRead<'copy, ITEM>,
67
68 /// A freshly createc/copied/clonned item
69 new_item: ITEM,
70
71 /// A reference to base to avoid Send.
72 inst: &'copy ICoW<ITEM>
73}
74
75impl<'copy, ITEM: fmt::Debug + Send> Deref for ICoWCopy<'copy, ITEM>
76{
77 type Target = ITEM;
78
79 fn deref(&self) -> &Self::Target
80 {
81 return &self.new_item;
82 }
83}
84
85impl<'copy, ITEM: fmt::Debug + Send> DerefMut for ICoWCopy<'copy, ITEM>
86{
87 fn deref_mut(&mut self) -> &mut Self::Target
88 {
89 return &mut self.new_item
90 }
91}
92
93impl<'copy, ITEM: fmt::Debug + Send> ICoWCopy<'copy, ITEM>
94{
95 /// Returns a reference to previous value. To access modified version use
96 /// [Deref] or [DerefMut].
97 pub
98 fn prev_val(&self) -> &ITEM
99 {
100 return &self.prev_item;
101 }
102
103 /// Commits the changes made in the guarded variable. A non-blocking
104 /// function. It will not block the thread completly and returns the
105 /// [ICoWError::WouldBlock] if attempt to grab the pointer atomically
106 /// fails.
107 ///
108 /// # Returns
109 ///
110 /// The [Result::Err] is returned with:
111 ///
112 /// * `0` - [ICoWError] with the error type.
113 ///
114 /// * `1` - [ICoWCopy] instance itself.
115 ///
116 /// Error types [ICoWError]:
117 ///
118 /// * [ICoWError::ExclusiveLockPending] - if exclusivly locked from another thread.
119 ///
120 /// * [ICoWError::WouldBlock] - `atomic only!` if "exponential backoff has completed and blocking the thread is advised".
121 pub
122 fn commit(self) -> Result<(), (ICoWError, Self)>
123 {
124 let write_lock =
125 self
126 .inst
127 .inner
128 .try_write();
129 //.unwrap_or_else(|e| e.into_inner());
130
131 let mut lock =
132 match write_lock
133 {
134 Ok(lock) =>
135 lock,
136 Err(TryLockError::Poisoned(lock_err)) =>
137 lock_err.into_inner(),
138 Err(TryLockError::WouldBlock) =>
139 return Err((ICoWError::ExclusiveLockPending, self)),
140 };
141
142 *lock = Arc::new(self.new_item);
143
144 return Ok(());
145 }
146
147}
148
149/// A write-guard which holds new value to which the new values are written. And
150/// previous value too. This type of guard is exclusive, so multiple
151/// CoW operations **CANNOT** be performed in parallel which is good for instance
152/// update without racing. The readers are also waiting until the changes are
153/// commited.
154#[derive(Debug)]
155pub struct ICoWLock<'lock, ITEM: fmt::Debug + Send>
156{
157 /// An exclusive lock in the previous value.
158 prev_item: RwLockWriteGuard<'lock, Arc<ITEM>>,
159
160 /// A freshly createc/copied/clonned item
161 item: ITEM,
162
163 /// A reference to base to avoid Send.
164 inst: &'lock ICoW<ITEM>
165}
166
167impl<'lock, ITEM: fmt::Debug + Send> ICoWLock<'lock, ITEM>
168{
169 /// Returns a reference to previous value. To access modified version use
170 /// [Deref] or [DerefMut].
171 pub
172 fn prev_val(&self) -> &ITEM
173 {
174 return self.prev_item.as_ref();
175 }
176
177 /// Commits the changes made in the guarded variable.
178 ///
179 /// # Returns
180 ///
181 /// Always returns [Result::Ok], but the `atomic` realization
182 /// would return [Result::Err] if:
183 ///
184 /// > The [Result::Err] is retruned if race condition happens i.e when
185 /// > updating the inner atomic ptr fails because someone have already
186 /// > changed the value.
187 #[inline]
188 pub
189 fn commit(mut self) -> Result<(), Self>
190 {
191 *self.prev_item = Arc::new(self.item);
192
193 return Ok(());
194 }
195}
196
197impl<'lock, ITEM: fmt::Debug + Send> Deref for ICoWLock<'lock, ITEM>
198{
199 type Target = ITEM;
200
201 fn deref(&self) -> &Self::Target
202 {
203 return &self.item;
204 }
205}
206
207impl<'lock, ITEM: fmt::Debug + Send> DerefMut for ICoWLock<'lock, ITEM>
208{
209 fn deref_mut(&mut self) -> &mut Self::Target
210 {
211 return &mut self.item
212 }
213}
214
215/// A main structure which implements CoW approach based on [RwLock] for the
216/// multithreading syncing. The object stored inside can be read directly, but
217/// modifying the `inner` value is performed using `CoW` copy-on-write approach.
218///
219/// The inner value must either [Copy], [Clone], [Default], or provide
220/// new value manually. The copied value is modified and stored back either
221/// shared or exclusive method. The exclusive lock prevents other CoW operations
222/// guaranteeing the uniq write access.
223///
224/// ```ignore
225/// #[derive(Debug, Clone)]
226/// struct TestStruct { s: u32 }
227///
228/// let cow_val = ICoW::new(TestStruct{ s: 2 });
229///
230/// // read
231/// let read0 = cow_val.read().unwrap();
232/// // ...
233/// drop(read0);
234///
235/// // write new non-exclusivly
236/// let mut write0 = cow_val.try_clone().unwrap();
237/// write0.s = 3;
238///
239/// write0.commit().unwrap();
240///
241/// // write new exclusivly
242/// let mut write0 = cow_val.try_clone_exclusivly().unwrap();
243/// write0.s = 3;
244///
245/// write0.commit().unwrap();
246///
247/// ```
248#[derive(Debug)]
249pub struct ICoW<ITEM: fmt::Debug + Send>
250{
251 /// A rwlock protected CoW.
252 inner: RwLock<Arc<ITEM>>
253}
254
255impl<ITEM: fmt::Debug + Send> ICoW<ITEM>
256{
257 /// Initalizes a new instance.
258 pub
259 fn new(item: ITEM) -> Self
260 {
261 return Self{ inner: RwLock::new(Arc::new(item))}
262 }
263
264 /// Returns the syncing meachanism.
265 pub
266 fn get_lock_type() -> ICoWLockTypes
267 {
268 return ICoWLockTypes::RwLock;
269 }
270}
271
272impl<ITEM: fmt::Debug + Send> ICoW<ITEM>
273{
274 /// Attempts to read the inner value returning the guard. This function
275 /// blocks the current thread until the value becomes available. This
276 /// can happen if exclusive copy-on-write is in progress.
277 ///
278 /// # Returns
279 ///
280 /// An instance with clonned reference is returned.
281 pub
282 fn read(&self) -> ICoWRead<'_, ITEM>
283 {
284 let lock =
285 self
286 .inner
287 .read()
288 .unwrap_or_else(|e| e.into_inner());
289
290 return ICoWRead{ item: lock.clone(), bind: self };
291 }
292
293 /// Attempts to read the inner value, returning the read guard in case of success.
294 /// This function does not block the current thread until the value becomes available.
295 /// This function fails if exclusive copy-on-write is in progress.
296 ///
297 /// But, this fucntion would block the thread until the [Backoff] reports
298 /// that it is recomended to park the thread.
299 ///
300 /// # Returns
301 ///
302 /// A [Option] is retrurned. The [Option::None] is returned if operation
303 /// would block for a long time.
304 pub
305 fn try_read(&self) -> Option<ICoWRead<'_, ITEM>>
306 {
307 let lock_res =
308 self
309 .inner
310 .try_read();
311
312 match lock_res
313 {
314 Ok(lock) =>
315 {
316 return Some(ICoWRead{ item: lock.clone(), bind: self });
317 },
318 Err(TryLockError::WouldBlock)=>
319 {
320 return None;
321 },
322 Err(TryLockError::Poisoned(lock)) =>
323 {
324 return Some(ICoWRead{ item: lock.into_inner().clone(), bind: self });
325 }
326 }
327 }
328
329 /// Attempts to grab the **exclusive** Copy-on-Write to prevent duplicate
330 /// writing.
331 ///
332 /// Non-blocking function i.e returns if it fails to acquire the
333 /// clone before some deadline.
334 ///
335 /// # Returns
336 ///
337 /// An [Option] is returned where the [Option::None] is returned if
338 /// an exclusive CoW lock have already been issued.
339 pub
340 fn try_new_exclusivly(&self, new_item: ITEM) -> Option<ICoWLock<'_, ITEM>>
341 {
342 let write_lock =
343 match self.inner.try_write()
344 {
345 Ok(r) => r,
346 Err(TryLockError::Poisoned(e)) => e.into_inner(),
347 Err(TryLockError::WouldBlock) =>
348 return None
349 };
350
351 return Some(
352 ICoWLock{ prev_item: write_lock, item: new_item, inst: self }
353 );
354 }
355
356 /// Attempts to update old value to new value for the inner.
357 ///
358 /// Non-blocking function i.e returns if it fails to acquire the
359 /// clone before some deadline. And does not block if the write access
360 /// is not available now due to the exclusive lock pending.
361 ///
362 /// Does not return guard. Updates the value in-place.
363 ///
364 /// # Returns
365 ///
366 /// A [Result] is returned where the [Result::Err] is returned with:
367 ///
368 /// * [ICoWError::ExclusiveLockPending] - if exclsive write already pending.
369 ///
370 /// * errors which are returned by [ICoWCopy::commit()].
371 pub
372 fn try_new_inplace(&self, new_item: ITEM) -> Result<(), (ICoWError, ITEM)>
373 {
374 if let Some(read) = self.try_read()
375 {
376 let ret =
377 ICoWCopy
378 {
379 prev_item: read,
380 new_item: new_item,
381 inst: self
382 };
383
384 return ret.commit().map_err(|e| (e.0, e.1.new_item));
385 }
386 else
387 {
388 return Err((ICoWError::WouldBlock, new_item));
389 }
390 }
391
392 /// Attempts to update old value to new value for the inner
393 /// **exclusively**.
394 ///
395 /// Non-blocking function i.e returns if it fails to acquire the
396 /// clone before some deadline.
397 ///
398 /// Does not return guard. Updates the value in-place.
399 ///
400 /// # Returns
401 ///
402 /// A [Result] is returned where the [Result::Err] is returned with:
403 ///
404 /// * [ICoWError::ExclusiveLockPending] - if exclsive write already pending.
405 ///
406 /// * [ICoWError::AlreadyUpdated] - if duplicate write operation attempt.
407 ///
408 /// * [ICoWError::RaceCondition] - a race condition detected during update.
409 ///
410 /// * errors which are returned by [ICoWCopy::commit()].
411 pub
412 fn try_new_exclusivly_inplace(&self, new_item: ITEM) -> Result<(), (ICoWError, ITEM)>
413 {
414
415 let write_lock =
416 match self.inner.try_write()
417 {
418 Ok(lock) =>
419 lock,
420 Err(TryLockError::Poisoned(e)) =>
421 e.into_inner(),
422 Err(TryLockError::WouldBlock) =>
423 return Err((ICoWError::ExclusiveLockPending, new_item))
424 };
425
426 let ret =
427 ICoWLock{ prev_item: write_lock, item: new_item, inst: self };
428
429 return Ok(ret.commit().unwrap());
430 }
431}
432
433impl<ITEM: fmt::Debug + Send + Copy> ICoW<ITEM>
434{
435 /// Performs the copy of the inner value for writing.
436 ///
437 /// Blocking function i.e always retruns the result.
438 ///
439 /// # Returns
440 ///
441 /// An [ICoWCopy] is returned.
442 pub
443 fn copy(&self) -> ICoWCopy<'_, ITEM>
444 {
445 let read = self.read();
446
447 let new_item = *read.item.as_ref();
448
449 let ret =
450 ICoWCopy
451 {
452 prev_item: read,
453 new_item: new_item,
454 inst: self
455 };
456
457 return ret;
458 }
459
460 /// Attempts to perform the copy of the inner value for writing.
461 ///
462 /// Non-blocking function i.e returns if it fails to acquire the
463 /// copy before some deadline.
464 ///
465 /// # Returns
466 ///
467 /// An [Option] is returned where the [Option::None] is returned if
468 /// it failed.
469 pub
470 fn try_copy(&self) -> Option<ICoWCopy<'_, ITEM>>
471 {
472 let read = self.try_read()?;
473
474 let new_item = *read.item.as_ref();
475
476 let ret =
477 ICoWCopy
478 {
479 prev_item: read,
480 new_item: new_item,
481 inst: self
482 };
483
484 return Some(ret);
485 }
486
487 /// Attempts to perform the copy of the inner value for
488 /// **exclusive** writing.
489 ///
490 /// Non-blocking function i.e returns if it fails to acquire the
491 /// copy before some deadline.
492 ///
493 /// # Returns
494 ///
495 /// An [Option] is returned where the [Option::None] is returned if
496 /// an exclusive CoW lock have already been issued.
497 pub
498 fn try_copy_exclusivly(&self) -> Option<ICoWLock<'_, ITEM>>
499 {
500
501 let write_lock =
502 match self.inner.try_write()
503 {
504 Ok(r) => r,
505 Err(TryLockError::Poisoned(e)) => e.into_inner(),
506 Err(TryLockError::WouldBlock) =>
507 return None
508 };
509
510 let new_item = *write_lock.as_ref();
511
512 return Some(
513 ICoWLock{ prev_item: write_lock, item: new_item, inst: self }
514 );
515 }
516}
517
518impl<ITEM: fmt::Debug + Send + Clone> ICoW<ITEM>
519{
520 /// Attempts to perform the clone of the inner value for writing.
521 ///
522 /// Blocking function i.e always retruns the result.
523 ///
524 /// # Returns
525 ///
526 /// An [ICoWCopy] is returned.
527 pub
528 fn clone(&self) -> ICoWCopy<'_, ITEM>
529 {
530 let read = self.read();
531
532 let new_item = read.item.as_ref().clone();
533
534 let ret =
535 ICoWCopy
536 {
537 prev_item: read,
538 new_item: new_item,
539 inst: self
540 };
541
542 return ret;
543 }
544
545 /// Attempts to perform the clone of the inner value for writing.
546 ///
547 /// Non-blocking function i.e returns if it fails to acquire the
548 /// clone before some deadline.
549 ///
550 /// # Returns
551 ///
552 /// An [Option] is returned where the [Option::None] is returned if
553 /// it failed.
554 pub
555 fn try_clone(&self) -> Option<ICoWCopy<'_, ITEM>>
556 {
557 let read = self.try_read()?;
558
559 let new_item = read.item.as_ref().clone();
560
561 let ret =
562 ICoWCopy
563 {
564 prev_item: read,
565 new_item: new_item,
566 inst: self
567 };
568
569 return Some(ret);
570 }
571
572 /// Attempts to perform the clone of the inner value for
573 /// **exclusive** writing.
574 ///
575 /// Non-blocking function i.e returns if it fails to acquire the
576 /// clone before some deadline.
577 ///
578 /// # Returns
579 ///
580 /// An [Option] is returned where the [Option::None] is returned if
581 /// an exclusive CoW lock have already been issued.
582 pub
583 fn try_clone_exclusivly(&self) -> Option<ICoWLock<'_, ITEM>>
584 {
585
586 let write_lock =
587 match self.inner.try_write()
588 {
589 Ok(r) => r,
590 Err(TryLockError::Poisoned(e)) => e.into_inner(),
591 Err(TryLockError::WouldBlock) =>
592 return None
593 };
594
595 let new_item = write_lock.as_ref().clone();
596
597 return Some(
598 ICoWLock{ prev_item: write_lock, item: new_item, inst: self }
599 );
600 }
601}
602
603impl<ITEM: fmt::Debug + Send + Default> ICoW<ITEM>
604{
605 /// Construct the guard from the [Default] of the inner value for writing.
606 ///
607 /// Blocking function i.e always retruns the result.
608 ///
609 /// # Returns
610 ///
611 /// An [Option] is returned where the [Option::None] is returned if
612 /// it failed.
613 pub
614 fn from_default(&self) -> ICoWCopy<'_, ITEM>
615 {
616 let read = self.read();
617
618 let new_item = ITEM::default();
619
620 let ret =
621 ICoWCopy
622 {
623 prev_item: read,
624 new_item: new_item,
625 inst: self
626 };
627
628 return ret;
629 }
630
631 /// Attempts to init default of the inner value for writing.
632 ///
633 /// Non-blocking function i.e returns if it fails to acquire the
634 /// clone before some deadline.
635 ///
636 /// # Returns
637 ///
638 /// An [Option] is returned where the [Option::None] is returned if
639 /// it failed.
640 pub
641 fn try_default(&self) -> Option<ICoWCopy<'_, ITEM>>
642 {
643 let read = self.try_read()?;
644
645 let new_item = ITEM::default();
646
647 let ret =
648 ICoWCopy
649 {
650 prev_item: read,
651 new_item: new_item,
652 inst: self
653 };
654
655 return Some(ret);
656 }
657
658
659 /// Attempts to init default of the inner value for
660 /// **exclusive** writing.
661 ///
662 /// Non-blocking function i.e returns if it fails to acquire the
663 /// clone before some deadline.
664 ///
665 /// # Returns
666 ///
667 /// An [Option] is returned where the [Option::None] is returned if
668 /// an exclusive CoW lock have already been issued.
669 pub
670 fn try_default_exclusivly(&self) -> Option<ICoWLock<'_, ITEM>>
671 {
672 let write_lock =
673 match self.inner.try_write()
674 {
675 Ok(r) => r,
676 Err(TryLockError::Poisoned(e)) => e.into_inner(),
677 Err(TryLockError::WouldBlock) =>
678 return None
679 };
680
681 let new_item = ITEM::default();
682
683 return Some(
684 ICoWLock{ prev_item: write_lock, item: new_item, inst: self }
685 );
686 }
687}
688
689
690#[cfg(test)]
691mod test
692{
693 use std::{sync::{mpsc, LazyLock}, time::{Duration, Instant}};
694
695 use super::*;
696
697
698
699
700 #[test]
701 fn test_3()
702 {
703 #[derive(Debug, Clone)]
704 struct Test { s: String };
705
706 let icow = ICoW::new(Test{ s: "test".into() });
707
708 for _ in 0..10
709 {
710 let s = Instant::now();
711
712 let read0 = icow.read();
713
714 let e = s.elapsed();
715
716 println!("{:?}", e);
717 }
718
719 }
720
721 #[test]
722 fn test_33()
723 {
724 #[derive(Debug, Clone)]
725 struct Test { s: String };
726
727 let icow = ICoW::new(Test{ s: "test".into() });
728
729 let write_ex = icow.try_clone_exclusivly().unwrap();
730
731 {
732 let write_ex_err = icow.try_clone_exclusivly();
733 assert_eq!(write_ex_err.is_none(), true);
734 }
735
736 let write_ex_err = icow.try_clone();
737 assert_eq!(write_ex_err.is_none(), true);
738
739 let read1 = icow.try_read();
740 assert_eq!(read1.is_none(), true);
741
742 drop(write_ex);
743
744 drop(icow);
745
746 }
747
748 #[test]
749 fn test_4()
750 {
751 #[derive(Debug, Clone)]
752 struct Test { s: u32 }
753
754 let icow = ICoW::new(Test{ s: 1 });
755
756 let read0 = icow.read();
757 let read1 = icow.read();
758
759 let mut excl_write = icow.try_clone_exclusivly().unwrap();
760
761 excl_write.item.s = 5;
762
763
764 excl_write.commit().unwrap();
765
766 assert_eq!(read0.item.s, 1);
767
768 let read3 = icow.read();
769 assert_eq!(read3.item.s, 5);
770
771 let mut writing = icow.try_clone().unwrap();
772 writing.s = 4;
773
774 writing.commit().unwrap();
775
776 assert_eq!(read0.item.s, 1);
777 assert_eq!(read3.item.s, 5);
778
779 let read4 = icow.read();
780 assert_eq!(read4.s, 4);
781 }
782
783 #[test]
784 fn test_5()
785 {
786 #[derive(Debug, Clone)]
787 struct Test { s: u32 }
788
789 let icow = Arc::new(ICoW::new(Test{ s: 1 }));
790
791 let read0 = icow.read();
792 let read2 = icow.read();
793
794 let c_icow = icow.clone();
795
796 let (se, rc) = mpsc::channel::<()>();
797 let handler0 =
798 std::thread::spawn(move ||
799 {
800 let mut lock0 = c_icow.try_clone_exclusivly().unwrap();
801
802 se.send(()).unwrap();
803
804 lock0.item.s = 5;
805
806 std::thread::sleep(Duration::from_micros(2));
807
808 lock0.commit().unwrap();
809 }
810 );
811
812 rc.recv().unwrap();
813
814 let s = Instant::now();
815
816 let read1 = icow.read();
817
818 let e = s.elapsed();
819
820 println!("{:?}", e);
821
822
823 assert_eq!(read1.item.s, 5);
824 assert_eq!(read0.item.s, 1);
825
826 handler0.join().unwrap();
827
828 let weak0 = read0.weak();
829 let weak1 = read1.weak();
830
831 drop(read0);
832 drop(read1);
833
834 assert_eq!(weak0.upgrade().is_some(), true);
835 assert_eq!(weak1.upgrade().is_some(), true);
836
837 drop(read2);
838 assert_eq!(weak0.upgrade().is_none(), true);
839 assert_eq!(weak1.upgrade().is_some(), true);
840 }
841
842
843 #[test]
844 fn test_6()
845 {
846 #[derive(Debug, Clone)]
847 struct Test { s: u32 }
848
849 let icow = Arc::new(ICoW::new(Test{ s: 1 }));
850
851 let read0 = icow.read();
852 let read2 = icow.read();
853
854 let c_icow = icow.clone();
855
856 let (se, rc) = mpsc::channel::<()>();
857 let handler0 =
858 std::thread::spawn(move ||
859 {
860 let read2 = c_icow.read();
861
862 let mut lock0 = c_icow.try_clone_exclusivly().unwrap();
863
864 se.send(()).unwrap();
865
866 lock0.item.s = 5;
867
868 std::thread::sleep(Duration::from_nanos(50));
869 lock0.commit().unwrap();
870
871 let read3 = c_icow.read();
872
873 assert_eq!(read2.item.s, 1);
874 assert_eq!(read3.item.s, 5);
875 }
876 );
877
878 rc.recv().unwrap();
879
880 for _ in 0..100000000
881 {
882 let read1 = icow.read();
883
884 if read1.item.s == 1
885 {
886 continue;
887 }
888 else
889 {
890 break;
891 }
892 }
893
894 let read1 = icow.read();
895 assert_eq!(read1.item.s, 5);
896
897 handler0.join().unwrap();
898
899 return;
900 }
901
902
903 #[test]
904 fn test_7()
905 {
906 #[derive(Debug, Clone)]
907 struct TestStruct { s: u32 }
908
909 impl TestStruct
910 {
911 fn new(s: u32) -> Self
912 {
913 return Self{ s: s };
914 }
915 }
916
917 static VAL: LazyLock<ICoW<TestStruct>> =
918 LazyLock::new(|| ICoW::new(TestStruct::new(1)));
919
920
921
922
923 let borrow1 = VAL.read();
924 assert_eq!(borrow1.item.s, 1);
925
926 let (mpsc_send, mpsc_rcv) = mpsc::channel::<u64>();
927 let (mpsc_send2, mpsc_rcv2) = mpsc::channel::<u64>();
928
929 let thread1 =
930 std::thread::spawn(move ||
931 {
932 for _ in 0..1000
933 {
934 let _ = mpsc_rcv2.recv();
935 let borrow1 = VAL.read();
936
937 let mut transaction = VAL.try_clone_exclusivly().unwrap();
938
939 transaction.item.s = 5;
940
941
942
943 std::thread::sleep(Duration::from_nanos(1001));
944 transaction.commit().unwrap();
945
946 let borrow2 = VAL.read();
947
948
949 assert_eq!(borrow1.item.s, 1);
950
951 assert_eq!(borrow2.item.s, 5);
952
953 let _ = mpsc_send.send(1);
954 }
955 }
956 );
957
958
959
960 for x in 0..1000
961 {
962 println!("{}", x);
963 mpsc_send2.send(1).unwrap();
964 let _ = mpsc_rcv.recv();
965
966 let borrow1 = VAL.read();
967 assert_eq!(borrow1.item.s, 5);
968
969 let mut transaction = VAL.try_clone_exclusivly().unwrap();
970 transaction.item.s = 1;
971 transaction.commit().unwrap();
972
973 let borrow1 = VAL.read();
974 assert_eq!(borrow1.item.s, 1);
975
976 }
977
978
979
980 thread1.join().unwrap();
981
982
983 }
984
985
986 #[test]
987 fn test_8()
988 {
989 #[derive(Debug, Clone)]
990 struct Test { s: u32 }
991
992 let icow = Arc::new(ICoW::new(Test{ s: 1 }));
993
994 for _ in 0..20
995 {
996 let read0 = icow.read();
997 let read2 = icow.read();
998
999 let c_icow = icow.clone();
1000
1001 //let (se, rc) = mpsc::channel::<()>();
1002 let handler0 =
1003 std::thread::spawn(move ||
1004 {
1005 let read2 = c_icow.read();
1006
1007 let mut lock0 = c_icow.try_clone().unwrap();
1008
1009 //se.send(()).unwrap();
1010
1011 lock0.s = 5;
1012
1013 std::thread::sleep(Duration::from_micros(1));
1014 lock0.commit().unwrap();
1015
1016 let read3 = c_icow.read();
1017
1018 assert_eq!(read2.item.s, 1);
1019 assert_eq!(read3.item.s, 5);
1020 }
1021 );
1022
1023 //rc.recv().unwrap();
1024
1025 for i in 0..1000000000
1026 {
1027 let read1 = icow.read();
1028
1029 if read1.item.s == 1
1030 {
1031 continue;
1032 }
1033 else
1034 {
1035 println!("{}", i);
1036 break;
1037 }
1038 }
1039
1040 let read1 = icow.read();
1041 assert_eq!(read1.item.s, 5);
1042
1043 handler0.join().unwrap();
1044
1045 let mut lock0 = icow.try_clone().unwrap();
1046 lock0.s = 1;
1047 lock0.commit().unwrap();
1048 }
1049
1050 return;
1051 }
1052}