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