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