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