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