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