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