instance_copy_on_write/
lib.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
15
16extern crate crossbeam_utils;
17extern crate crossbeam_deque;
18
19#[cfg(test)]
20use std::sync::{Arc, Weak};
21
22use std::
23{
24    cell::RefCell, collections::HashMap, fmt::{self}, marker::PhantomData, ops::{Deref, DerefMut}, ptr::{self, NonNull}, sync::atomic::{AtomicPtr, AtomicU32, Ordering}, time::Duration
25};
26
27use crossbeam_deque::{Injector, Steal};
28use crossbeam_utils::{atomic::AtomicCell, sync::{Parker, Unparker}, Backoff};
29
30/// An internal instance which exists in the heap i.e boxed which pointer is leaked.
31/// Must be destructed manually. Contains all controlling items and the stored item 
32/// itself.
33#[derive(Debug)]
34struct InstanceCopyOnWriteInner<ITEM: Send + fmt::Debug>
35{
36    /// Needed for tests only.
37    #[cfg(test)]
38    arc_tag: Arc<()>,
39
40    /// Amount of borrows. Normally it eq 1 which means exists in base only.
41    refs: AtomicU32,
42
43    /// An exclusive lock which required to be waken up when all (except base) borrows
44    /// are dropped.
45    wake_up_lock: AtomicPtr<()>,
46
47    /// A stored item.
48    item: ITEM
49}
50
51impl<ITEM: Send + fmt::Debug> InstanceCopyOnWriteInner<ITEM>
52{
53    thread_local! 
54    {
55        /// A borrows counter for EACH THREAD which helps to detect dead locks when borrowed and
56        /// gains exclusive lock from same thread (viceversa not possible).
57        static BORROWS: RefCell<HashMap<usize, usize>> = RefCell::new(HashMap::with_capacity(10));
58    }
59
60    /// Creates new instance.
61    fn new(item: ITEM) -> Self
62    {
63        return 
64            Self
65            {
66                #[cfg(test)]
67                arc_tag: Arc::new(()),
68
69                refs: AtomicU32::new(1),
70
71                wake_up_lock: AtomicPtr::new(ptr::null_mut()),
72
73                item: item,
74            };
75    }
76
77    /// Returns the weak reference to check if instance is still exists.
78    #[cfg(test)]
79    fn get_weak_tag(&self) -> Weak<()>
80    {
81        return Arc::downgrade(&self.arc_tag);
82    }
83}
84
85/// An instance which contains a clonned [InstanceCopyOnWriteInner]. Desctructs the
86/// [InstanceCopyOnWriteInner] when no references left or wakes up the locking
87/// thread.
88#[derive(Debug)]
89struct InstanceCopyOnWriteClone<ITEM: Send + fmt::Debug>
90{
91    /// A copied pointer to the heap.
92    inst: NonNull<InstanceCopyOnWriteInner<ITEM>>
93}
94
95
96impl<ITEM: Send + fmt::Debug> Clone for InstanceCopyOnWriteClone<ITEM>
97{
98    /// Clones the self. 
99    #[inline]
100    fn clone(&self) -> Self 
101    {
102        let inner = unsafe { self.inst.as_ref() };
103
104        inner.refs.fetch_add(1, Ordering::SeqCst);
105
106        return Self { inst: self.inst };
107    }
108}
109
110
111
112impl<ITEM: Send + fmt::Debug> Drop for InstanceCopyOnWriteClone<ITEM>
113{
114    fn drop(&mut self) 
115    {
116        // decrease the refs, returns the value before substruction
117        let subed = unsafe{ self.inst.as_ref() }.refs.fetch_sub(1, Ordering::AcqRel);
118
119        if subed == 2
120        {
121            // check if the locking thread needs to be unparked i.e waked up.
122            let inst_ref = unsafe{ self.inst.as_ref() };
123
124            let wakeup_ptr = inst_ref.wake_up_lock.swap(ptr::null_mut(), Ordering::Relaxed);
125
126            if wakeup_ptr.is_null() == false
127            {
128                unsafe { Unparker::from_raw(wakeup_ptr.cast_const()) }.unpark();
129            }
130        }
131        else if subed == 1
132        {
133            // remove the borrow ID
134            InstanceCopyOnWriteInner
135                ::<ITEM>
136                ::BORROWS
137                    .with_borrow_mut(|v|
138                        {
139                           // v.remove(&self.inner().id);
140                            v.remove(&self.inst.as_ptr().addr());
141                        }
142                    );
143            
144            drop(unsafe { Box::from_raw(self.inst.as_ptr()) });
145        }
146
147        return;
148    }
149}
150
151impl<ITEM: Send + fmt::Debug>  InstanceCopyOnWriteClone<ITEM>
152{
153    fn new(item: ITEM) -> Self
154    {
155        let status = Box::new(InstanceCopyOnWriteInner::new(item));
156
157        return Self{ inst: Box::leak(status).into() };
158    }
159
160    #[inline]
161    fn load_refs(&self) -> u32
162    {
163        return unsafe { self.inst.as_ref() }.refs.load(Ordering::Acquire);
164    }
165
166    #[inline]
167    fn inner(&self) -> &InstanceCopyOnWriteInner<ITEM>
168    {
169        return unsafe { self.inst.as_ref() };
170    }
171
172    #[inline]
173    fn inner_mut(&mut self) -> &mut InstanceCopyOnWriteInner<ITEM>
174    {
175        return unsafe { self.inst.as_mut() };
176    }
177}
178
179/// A error for the Cow operations.
180#[derive(Clone, Copy, Debug, PartialEq, Eq)]
181pub enum CowGuardError
182{
183    /// The instance was poisoned during exclusive lock (non-cow operation).
184    Poisoned,
185
186    /// An exclusive lock is pending so another writing opration performing Cow 
187    /// would block.
188    ExclusiveLockPending,
189
190    /// Is returned by the borrow operation if an exclusive lock (non-cow op) is pending.
191    WouldBlock, 
192}
193
194impl fmt::Display for CowGuardError
195{
196    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
197    {
198        match self
199        {
200            Self::Poisoned => 
201                write!(f, "poisoned"),
202            Self::ExclusiveLockPending => 
203                write!(f, "exclusive lock pending"),
204            Self::WouldBlock => 
205                write!(f, "wouldblock"),
206        }
207    }
208}
209
210/// A guard which guards the read-only CoW operation. 
211#[derive(Debug)]
212pub struct CowReadGuard<'read, ITEM: Send + fmt::Debug> 
213{
214    /// A clonned instance with increased reference value
215    inst: InstanceCopyOnWriteClone<ITEM>,
216
217    /// A reference to the main instance.
218    owner_ref: &'read InstanceCopyOnWrite<ITEM>,
219
220    _p_thread_lock: PhantomData<*const ()>,
221}
222
223
224impl<'read, ITEM: Send + fmt::Debug> CowReadGuard<'read, ITEM>
225{
226    /// Creates new instance.
227    /// 
228    /// # Arguments
229    /// 
230    /// * `owner` - a reference to base structure [InstanceCopyOnWrite].
231    /// 
232    /// * `try_borrow` - if set to `true` will return [CowGuardError::WouldBlock].
233    /// 
234    /// # Returns
235    /// 
236    /// A [Result] is returned with:
237    /// 
238    /// * [Result::Ok] with the guard is returned.
239    /// 
240    /// * [Result::Err] with the error is returned:
241    /// 
242    /// 
243    /// * [CowGuardError::Poisoned] - if the exclusive was poisoned i.e thread panicked.
244    /// 
245    /// * [CowGuardError::WouldBlock] - if the argument `try_borrow` is set to `true`.
246    #[inline]
247    fn new(owner: &'read InstanceCopyOnWrite<ITEM>, try_borrow: bool) -> Result<CowReadGuard<'read, ITEM>, CowGuardError>
248    {
249        let bkoff = Backoff::new();
250
251        loop
252        {
253            // try to update the status
254            let status = 
255                owner.owner_lock.compare_exchange(CowLockStatus::Ok, CowLockStatus::Borrow);
256
257            match status
258            {
259                Ok(CowLockStatus::Ok) =>
260                {
261                    let ptr = owner.owner_inner.load(Ordering::Relaxed);
262
263                    let cloned_read: InstanceCopyOnWriteClone<ITEM> = unsafe {ptr.as_ref()}.unwrap().clone();
264
265                    // return the status back. it does not matter if it was not restored due to changes.
266                    let _ = owner.owner_lock.compare_exchange(CowLockStatus::Borrow, CowLockStatus::Ok);
267
268                    // set the thread local borrow counter for the exclusive lock
269                    InstanceCopyOnWriteInner::<ITEM>::BORROWS.with_borrow_mut(|v| 
270                        {
271                            v.entry(cloned_read.inst.as_ptr().addr()).and_modify(|v| *v += 1).or_insert(1);
272                        }
273                    );
274
275                    return Ok(
276                        Self
277                        {
278                            inst: cloned_read,
279                            owner_ref: owner,
280                            _p_thread_lock: PhantomData
281                        }
282                    );
283                },
284                Err(CowLockStatus::Borrow) =>
285                {
286                    // someone already borrowed it
287                    bkoff.snooze();
288                    continue;
289                },
290                Err(CowLockStatus::Poisoned) =>
291                {
292                    return Err(CowGuardError::Poisoned);
293                },
294                Err(CowLockStatus::Park) =>
295                {
296                    // an exclusive lock is pending.
297
298                    if try_borrow == false
299                    {
300                        if bkoff.is_completed() == true
301                        {
302                            let p = Parker::new();
303                            let u = p.unparker().clone();
304
305                            owner.park_queue.push(u);
306
307                            p.park_timeout(Duration::from_millis(500));
308                        }
309                        else
310                        {
311                            bkoff.snooze();
312                        }
313                    }
314                    else
315                    {
316                        return Err(CowGuardError::WouldBlock);
317                    }
318
319                    continue;
320                },
321                _ => 
322                    panic!("assertion trap: wrong status: {:?}", status),
323            }
324        }
325       
326    }
327}
328
329impl<'read, ITEM: Send + fmt::Debug> Deref for CowReadGuard<'read, ITEM>
330{
331    type Target = ITEM;
332
333    fn deref(&self) -> &Self::Target
334    {
335        return & unsafe { self.inst.inst.as_ref()}.item;
336    }
337}
338
339impl<'read, ITEM: Send + fmt::Debug> Drop for CowReadGuard<'read, ITEM>
340{
341    fn drop(&mut self) 
342    {
343        // decrease the borrow count for the thread.
344        InstanceCopyOnWriteInner
345            ::<ITEM>
346            ::BORROWS
347                .with_borrow_mut(|v| 
348                    {
349                        v
350                            .get_mut(&self.inst.inst.as_ptr().addr())
351                            .map(|v| *v -= 1);
352                    }
353                );
354    }
355}
356
357/// A guard which guards the CoW read/write operation. During this operation, the 
358/// instance is borrowed and copied or clonned or default or new instance created.
359/// 
360/// This method of modifying does not require to release all borrows i.e [CowReadGuard].
361/// Instead the value in the base will be replaced and anyone who will request the
362/// `borrow` after the update will see the new value. The rest who keeps `borrow` would
363/// still use old value.
364#[derive(Debug)]
365pub struct CowTransactionGuard<'tra, ITEM: Send + fmt::Debug> 
366{
367    /// A reference to the base instance.
368    icow: &'tra InstanceCopyOnWrite<ITEM>,
369    
370    /// A copied or newly created instance.
371    new_inst: ITEM,
372
373    /// A guard to read only guard.
374    cloned_read: CowReadGuard<'tra, ITEM>,
375
376    /// No send, no sync
377    _p_thread_lock: PhantomData<*const ()>,
378}
379
380impl<'tra, ITEM: Send + fmt::Debug> Deref for CowTransactionGuard<'tra, ITEM>
381{
382    type Target = ITEM;
383
384    fn deref(&self) -> &Self::Target
385    {
386        return &self.new_inst;
387    }
388}
389
390impl<'tra, ITEM: Send + fmt::Debug> DerefMut for CowTransactionGuard<'tra, ITEM>
391{
392    fn deref_mut(&mut self) -> &mut Self::Target
393    {
394        return &mut self.new_inst;
395    }
396}
397
398
399impl<'tra, ITEM: Send + fmt::Debug> CowTransactionGuard<'tra, ITEM>
400{
401    /// Returns the previous reference to the item (old value) which will be replaced.
402    pub 
403    fn get_previous(&self) -> &ITEM
404    {
405        return &self.cloned_read;
406    }
407
408    /// Completes the transaction by attempting to replace the old `item` with new `item`
409    /// in the base. If argument `try_update` is set to `true`, the completed will not block,
410    /// but return an error to repeat the attempt later.
411    /// 
412    /// # Arguments
413    /// 
414    /// The instance is consumed.
415    /// 
416    /// `try_update` - if set to `true` does not block if exclusive lock is pending.
417    /// 
418    /// # Returns
419    /// 
420    /// A [Result] is returned with:
421    /// 
422    /// * [Result::Ok] with the guard is returned.
423    /// 
424    /// * [Result::Err] with the error is returned:
425    /// 
426    /// 
427    /// * [CowGuardError::Poisoned] - if the exclusive was poisoned i.e thread panicked.
428    /// 
429    /// * [CowGuardError::ExclusiveLockPending] - if the argument `try_borrow` is set to `true`.
430    pub 
431    fn completed(self, try_update: bool) -> Result<(),(Self, CowGuardError)>
432    {
433        let bkoff = Backoff::new();
434
435        loop
436        {
437            let status = 
438                self.icow.owner_lock.compare_exchange(CowLockStatus::Ok, CowLockStatus::Borrow);
439
440            match status
441            {
442                Ok(CowLockStatus::Ok) =>
443                {
444                    let boxed_inner = Box::new(InstanceCopyOnWriteClone::new(self.new_inst));
445
446                    let prev_inner = self.icow.owner_inner.swap(Box::leak(boxed_inner), Ordering::Relaxed);
447
448                    drop(unsafe { Box::from_raw(prev_inner) });
449
450                    let _ = self.icow.owner_lock.compare_exchange(CowLockStatus::Borrow, CowLockStatus::Ok);
451
452                    return Ok(());
453                },
454                Err(CowLockStatus::Poisoned) =>
455                {
456                    return Err((self, CowGuardError::Poisoned));
457                },
458                Err(CowLockStatus::Borrow) =>
459                {
460                    bkoff.snooze();
461                    continue;
462                },
463                Err(CowLockStatus::Park) =>
464                {
465                    if try_update == false
466                    {
467                        bkoff.snooze();
468                        continue;
469                    }
470                    else
471                    {
472                        // reject locked exclusivly.
473                        return Err((self, CowGuardError::ExclusiveLockPending));
474                    }
475                },
476                _ => 
477                    panic!("assertion trap: CowTransactionGuard::complete() unknwon status: {:?}", status)
478            }
479        }
480    }
481}
482
483/// An errors for exclusive lock i.e non-cow operation.
484#[derive(Clone, Copy, Debug, PartialEq, Eq)]
485pub enum NoCowGuardErr
486{
487    /// The instance is already exclusivly locked, so either try again later or
488    /// borrow. This can be used to prevent multiple update on failures.
489    AlreadyLocked,
490
491    /// The instance is borrowed (CoW read) by the calling thread already, so deadlock
492    /// prevented.
493    Borrowed,
494
495    /// The instance is poisoned.
496    Poisoned //todo
497}
498
499impl fmt::Display for NoCowGuardErr
500{
501    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
502    {
503        match self
504        {
505            NoCowGuardErr::AlreadyLocked => 
506                write!(f, "already locked"),
507            NoCowGuardErr::Borrowed => 
508                write!(f, "borrowed"),
509            NoCowGuardErr::Poisoned => 
510                write!(f, "poisoned"),
511        }
512    }
513}
514
515/// A guard which is assigned to the [NoCowGuard] for the execution flow
516/// control. 
517#[derive(Clone, Debug)]
518struct NoCowPanicGuard
519{
520    #[cfg(all(panic = "unwind"))]
521    panicking: bool,
522}
523
524#[cfg(all(panic = "unwind"))]
525impl Default for NoCowPanicGuard
526{
527    fn default() -> Self 
528    {
529        use std::thread;
530
531        Self { panicking: thread::panicking() }
532    }
533}
534
535
536/// Guards the exclusive lock. During this lock, any CoW operations are
537/// blocked. 
538/// 
539/// * The current thread must not borrow the locking instance.
540/// 
541/// * No other thread (except calling) should already hold exclusive lock.
542/// 
543/// * Must not be poisoned.
544#[derive(Debug)]
545pub struct NoCowGuard<'lock, ITEM: Send + fmt::Debug> 
546{
547    /// Poison detection.
548    poison_guard: NoCowPanicGuard,
549
550    /// The instance which is modified.
551    inst: InstanceCopyOnWriteClone<ITEM>,
552
553    /// A reference to base.
554    icow: &'lock InstanceCopyOnWrite<ITEM>,
555}
556
557impl<'lock, ITEM: Send + fmt::Debug> Drop for NoCowGuard<'lock, ITEM>
558{
559    fn drop(&mut self) 
560    {
561        // check panic and restore or set status lock
562        #[cfg(all(panic = "unwind"))]
563        let res = 
564            if self.poison_guard.panicking == false && std::thread::panicking() == true
565            {
566                self.icow.owner_lock.compare_exchange(CowLockStatus::Park, CowLockStatus::Poisoned)
567            }
568            else
569            {
570                self.icow.owner_lock.compare_exchange(CowLockStatus::Park, CowLockStatus::Ok)
571            };
572
573        #[cfg(not(all(panic = "unwind")))]
574        let res =
575            self.icow.owner_lock.compare_exchange(CowLockStatus::Park, CowLockStatus::Ok);
576
577
578        if let Err(e) = res
579        {
580            panic!("asserion trap: expected CowLockStatus::Ok, got {}", e);
581        }
582
583        loop
584        {
585            match self.icow.park_queue.steal()
586            {
587                Steal::Empty => 
588                    break,
589                Steal::Success(unp) => 
590                    unp.unpark(),
591                Steal::Retry => 
592                    {},
593            }
594        }
595
596        return;
597    }
598}
599
600impl<'lock, ITEM: Send + fmt::Debug> Deref for NoCowGuard<'lock, ITEM>
601{
602    type Target = ITEM;
603
604    fn deref(&self) -> &Self::Target
605    {
606        return & unsafe { self.inst.inst.as_ref() }.item;
607    }
608}
609
610impl<'lock, ITEM: Send + fmt::Debug> DerefMut for NoCowGuard<'lock, ITEM>
611{
612    fn deref_mut(&mut self) -> &mut Self::Target
613    {
614        return &mut unsafe { self.inst.inst.as_mut() }.item;
615    }
616}
617
618impl<'lock, ITEM: Send + fmt::Debug> NoCowGuard<'lock, ITEM>
619{
620    /// Creates new instance.
621    /// 
622    /// # Arguments 
623    /// 
624    /// * `depoison` - [bool] if set to true would attemt to accure lock even if the instance was
625    ///     poisoned.
626    /// 
627    /// # Returns
628    /// 
629    /// A [Result] is returned with:
630    /// 
631    /// * [Result::Ok] with the guard is returned.
632    /// 
633    /// * [Result::Err] with the error is returned:
634    /// 
635    /// 
636    /// * [NoCowGuardErr::Poisoned] - if the exclusive was poisoned i.e thread panicked.
637    /// 
638    /// * [NoCowGuardErr::Borrowed] - if the instance is borrowed by the current thread.
639    /// 
640    /// * [NoCowGuardErr::AlreadyLocked] - if the instance already exclusivly locked.
641    #[inline]
642    fn new(owner: &'lock InstanceCopyOnWrite<ITEM>, depoison: bool) -> Result<NoCowGuard<'lock, ITEM>, NoCowGuardErr>
643    {
644
645        let status = 
646            if depoison == false
647            {
648                CowLockStatus::Ok
649            }
650            else
651            {
652                CowLockStatus::Poisoned
653            };
654            
655        let poison_guard = NoCowPanicGuard::default();
656
657        let bkoff = Backoff::new();
658
659        loop
660        {
661            let status = 
662                owner.owner_lock.compare_exchange(status, CowLockStatus::Park);
663
664            if let Ok(CowLockStatus::Ok) = status
665            {
666                let ptr = owner.owner_inner.load(Ordering::Relaxed);
667                let ptr_ref = unsafe{ ptr.as_ref() }.unwrap();
668                
669                // check if thread borrows the variable
670                if 
671                    InstanceCopyOnWriteInner
672                        ::<ITEM>
673                        ::BORROWS
674                            .with_borrow(|v| 
675                                v.get(&ptr_ref.inst.as_ptr().addr()).map_or(true, |f| f.eq(&0))
676                            ) 
677                    == false
678                {
679                    let _ = owner.owner_lock.compare_exchange(CowLockStatus::Park, CowLockStatus::Ok);
680
681                    return Err(NoCowGuardErr::Borrowed);
682                }
683
684                let mut unparker_ptr: Option<*const ()> = None;
685
686                let p = Parker::new();
687
688                // locked, now wait until every any borrow still active
689                loop
690                {
691                    
692
693                    let ptr_refs = ptr_ref.load_refs();
694
695                   
696                    if ptr_refs == 1
697                    {
698                        break;
699                    }
700                    else if ptr_refs == 0
701                    {
702                        // (should not happen) return error
703                        panic!("assetion trap: ptr_rfs == 0");
704                    }
705
706                    if bkoff.is_completed() == true
707                    {
708                        
709                        // park the thread or return WouldBlock?
710
711                       if let None = unparker_ptr
712                       {
713                            let cloned_read: InstanceCopyOnWriteClone<ITEM> = ptr_ref.clone();
714
715                            let unpark_ptr = Unparker::into_raw(p.unparker().clone());
716
717                            unparker_ptr.replace(unpark_ptr);
718
719                            cloned_read.inner().wake_up_lock.store(unpark_ptr.cast_mut(), Ordering::Relaxed);
720                        }
721                      
722                        p.park_timeout(Duration::from_millis(10));
723                    }
724                    else
725                    {
726                        bkoff.snooze();
727                    }
728                }
729 
730                if let Some(_) = unparker_ptr
731                {
732                    let unpark_ptr = ptr_ref.inner().wake_up_lock.swap(ptr::null_mut(), Ordering::Relaxed).cast_const();
733
734                    if unpark_ptr.is_null() == false
735                    {
736                        drop( unsafe { Unparker::from_raw(unpark_ptr) });
737                    }
738                }
739
740                return Ok(
741                    Self
742                    {
743                        poison_guard: poison_guard,
744                        inst: ptr_ref.clone(),
745                        icow: owner,
746                    }
747                );
748            }
749            else if let Err(CowLockStatus::Poisoned) = status
750            {
751                return Err(NoCowGuardErr::Poisoned);
752            }
753            else if let Err(CowLockStatus::Borrow) = status
754            {
755                bkoff.snooze();
756                continue;
757            }
758            else
759            {
760                return Err(NoCowGuardErr::AlreadyLocked);
761            }
762        } // loop
763       
764    } 
765}
766
767/// An internal lock status.
768#[derive(Clone, Copy, Debug, PartialEq, Eq)]
769enum CowLockStatus
770{
771    Ok, Borrow, Park, Poisoned
772}
773
774impl fmt::Display for CowLockStatus
775{
776    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
777    {
778        match self
779        {
780            Self::Ok => 
781                write!(f, "OK"),
782            Self::Borrow => 
783                write!(f, "BORROW"),
784            Self::Park => 
785                write!(f, "PARK"),
786            Self::Poisoned =>
787                write!(f, "POISONED")
788        }
789    }
790}
791
792/// A base instance which is used to perform CoW and non-CoW operations on the inner value.
793/// 
794/// Borrow:
795/// 
796/// ```ignore
797/// let val = 
798///     InstanceCopyOnWrite::new(TestStruct::new(1, 2));
799/// 
800/// let test_borrow = val.borrow().unwrap();
801/// ```
802/// 
803/// CoW copy-on-write
804/// 
805/// ```ignore
806/// let val = 
807///     InstanceCopyOnWrite::new(TestStruct::new(1, 2));
808/// 
809/// let test_borrow = val.borrow().unwrap();
810/// ```
811/// 
812/// ```ignore
813/// let val = 
814///     InstanceCopyOnWrite::new(TestStruct::new(1, 2));
815/// 
816/// let mut transaction = val.start_copying().unwrap();
817/// 
818/// transaction.start = 5;
819/// transaction.stop = 6;
820/// 
821/// transaction.completed(false).unwrap();
822/// ```
823/// 
824/// Exclusive lock (non-CoW)
825/// 
826/// ```ignore
827/// let val = 
828///     InstanceCopyOnWrite::new(TestStruct::new(1, 2));
829/// 
830/// let lock = val.lock();
831/// 
832/// drop(lock);
833/// ```
834#[derive(Debug)]
835pub struct InstanceCopyOnWrite<ITEM: Send + fmt::Debug>
836{
837    /// A sync primitive based on the [AtomicCell]. Contains the current status.
838    owner_lock: AtomicCell<CowLockStatus>,
839
840    /// All threads which were awaiting the exclusive lock and parked.
841    park_queue: Injector<Unparker>,
842
843    /// Contains a raw [Box] value which must be destructed manually when the writing is
844    /// completed!
845    owner_inner: AtomicPtr<InstanceCopyOnWriteClone<ITEM>>,
846}
847
848impl<ITEM: Send + fmt::Debug> Drop for  InstanceCopyOnWrite<ITEM>
849{
850    fn drop(&mut self) 
851    {
852        let status = 
853            self.owner_lock.compare_exchange(CowLockStatus::Ok, CowLockStatus::Borrow);
854
855        if let Ok(CowLockStatus::Ok) = status
856        {
857            let ptr = self.owner_inner.swap(ptr::null_mut(), Ordering::Relaxed);
858
859            if ptr.is_null() == false
860            {
861                drop(unsafe { Box::from_raw(ptr) });
862            }
863
864            while let Steal::Success(s) = self.park_queue.steal() 
865            {
866                s.unpark();
867            }
868
869            return;
870        }
871        else 
872        {
873            panic!("assertion trap: destructing InstanceCopyOnWrite while borrowed");
874        }
875    }
876}
877
878impl<ITEM: Send + fmt::Debug> InstanceCopyOnWrite<ITEM>
879{
880    /// Cretaes new instance with the pre-initialized item.
881    pub 
882    fn new(item: ITEM) -> Self
883    {
884        let boxed_inner = Box::new(InstanceCopyOnWriteClone::new(item));
885
886        return 
887            Self
888            {
889                owner_lock: AtomicCell::new(CowLockStatus::Ok), 
890                park_queue: Injector::new(),
891                owner_inner: AtomicPtr::new( Box::leak(boxed_inner) ) 
892            };
893    }
894
895    /// Borrows the `ITEM` for read-only operations. The instance will remain
896    /// unchaned even after the writing using copy-on-write. As long as the
897    /// `borrow` exists, the exclusive lock is not possible.
898    /// 
899    /// # Returns 
900    /// 
901    /// Either a [Result::Ok] with [CowReadGuard] or [Result::Err] with [CowGuardError]
902    /// is returned.
903    #[inline]
904    pub 
905    fn borrow(&self) -> Result<CowReadGuard<'_, ITEM>, CowGuardError>
906    {
907        return CowReadGuard::new(self, false);    
908    }
909
910    /// Attempts to borrows the `ITEM` for read-only operations. If eclusive lock is
911    /// pending, the error will be returned see [CowReadGuard::new].
912    /// 
913    /// The instance will remain unchaned even after the writing using copy-on-write. 
914    /// As long as the `borrow` exists, the exclusive lock is not possible.
915    /// 
916    /// # Returns 
917    /// 
918    /// Either a [Result::Ok] with [CowReadGuard] or [Result::Err] with [CowGuardError]
919    /// is returned.
920    #[inline]
921    pub 
922    fn try_borrow(&self) -> Result<CowReadGuard<'_, ITEM>, CowGuardError>
923    {
924        return CowReadGuard::new(self, true);    
925    }
926
927    /// Makes the exclusive lock. See [NoCowGuard] for more information about 
928    /// pre-requests. See [NoCowGuard::new] for more info.
929    /// 
930    /// # Returns 
931    /// 
932    /// Either a [Result::Ok] with [NoCowGuard] or [Result::Err] with [NoCowGuardErr]
933    /// is returned.
934    #[inline]
935    pub 
936    fn lock(&self) -> Result<NoCowGuard<'_, ITEM>, NoCowGuardErr>
937    {
938        return NoCowGuard::new(self, false); 
939    }
940
941    /// Manually removes poison status by forcing the lock. (untested)
942    /// 
943    /// Does not check if any borrows.
944    /// 
945    /// See [NoCowGuard] for more info.
946    /// 
947    /// # Returns 
948    /// 
949    /// Either a [Result::Ok] with [NoCowGuard] or [Result::Err] with [NoCowGuardErr]
950    /// is returned.
951    pub 
952    fn remove_poison_lock(&self) -> Result<NoCowGuard<'_, ITEM>, NoCowGuardErr>
953    {
954        return NoCowGuard::new(self, true); 
955    }
956
957    /// Manually removes poison status by setting `new_inst` to the inner.  (untested)
958    /// 
959    /// Is safer than [Self::remove_poison_lock] because active borrows would not be affected.
960    /// 
961    /// See [NoCowGuard] for more info.
962    /// 
963    /// # Returns 
964    /// 
965    /// Either a [Result::Ok] with () or [Result::Err] with [NoCowGuardErr]
966    /// is returned.
967    /// 
968    /// * [NoCowGuardErr::AlreadyLocked] - if someone is already attempting to depoison.
969    /// 
970    /// * [NoCowGuardErr::Poisoned] - depoisoning have failed
971    pub 
972    fn remove_poison_write(&self, new_inst: ITEM) -> Result<(), NoCowGuardErr>
973    {
974        let Ok(_) = self.owner_lock.compare_exchange(CowLockStatus::Poisoned, CowLockStatus::Park)
975            else { return Err( NoCowGuardErr::AlreadyLocked )};
976
977        let boxed_inner = Box::new(InstanceCopyOnWriteClone::new(new_inst));
978
979        let prev_inner = self.owner_inner.swap(Box::leak(boxed_inner), Ordering::Relaxed);
980
981        drop(unsafe { Box::from_raw(prev_inner) });
982
983        let Ok(_) = self.owner_lock.compare_exchange(CowLockStatus::Park, CowLockStatus::Ok)
984            else { return Err(NoCowGuardErr::Poisoned) };
985
986        return Ok(());
987    }
988}
989
990impl<ITEM: Send + fmt::Debug + Copy>  InstanceCopyOnWrite<ITEM>
991{
992    /// Performing the copy-on-write by copying [Copy] the inner value `ITEM`.
993    /// 
994    /// See [CowTransactionGuard] for more info.
995    /// 
996    /// Either a [Result::Ok] with [CowTransactionGuard] or [Result::Err] with [CowGuardError]
997    /// is returned.
998    pub 
999    fn start_copying(&self) -> Result<CowTransactionGuard<'_, ITEM>, CowGuardError>
1000    {
1001        let cloned_read = self.borrow()?;
1002
1003        let new_inst = unsafe { cloned_read.inst.inst.as_ref()}.item;
1004
1005        return Ok(
1006            CowTransactionGuard
1007            {
1008                icow: self, 
1009                new_inst: new_inst,
1010                cloned_read: cloned_read,
1011                _p_thread_lock: PhantomData,
1012            }
1013        );
1014    }
1015
1016    /// Attempts to perform the copy-on-write by copying [Copy] the inner value `ITEM`.
1017    /// 
1018    /// See [CowTransactionGuard] for more info.
1019    /// 
1020    /// Either a [Result::Ok] with [CowTransactionGuard] or [Result::Err] with [CowGuardError]
1021    /// is returned.
1022    pub 
1023    fn try_start_copying(&self) -> Result<CowTransactionGuard<'_, ITEM>, CowGuardError>
1024    {
1025        let cloned_read = self.try_borrow()?;
1026
1027        let new_inst = unsafe { cloned_read.inst.inst.as_ref()}.item;
1028
1029        return Ok(
1030            CowTransactionGuard
1031            {
1032                icow: self, 
1033                new_inst: new_inst,
1034                cloned_read: cloned_read,
1035                _p_thread_lock: PhantomData,
1036            }
1037        );
1038    }
1039}
1040
1041impl<ITEM: Send + fmt::Debug + Clone>  InstanceCopyOnWrite<ITEM>
1042{
1043    /// Performing the copy-on-write by cloning [Clone] the inner value `ITEM`.
1044    /// 
1045    /// See [CowTransactionGuard] for more info.
1046    /// 
1047    /// Either a [Result::Ok] with [CowTransactionGuard] or [Result::Err] with [CowGuardError]
1048    /// is returned.
1049    pub 
1050    fn start_cloning(&self) -> Result<CowTransactionGuard<'_, ITEM>, CowGuardError>
1051    {
1052        let cloned_read = self.borrow()?;
1053
1054        let new_inst = unsafe { cloned_read.inst.inst.as_ref()}.item.clone();
1055
1056        return Ok(
1057            CowTransactionGuard
1058            {
1059                icow: self, 
1060                new_inst: new_inst,
1061                cloned_read: cloned_read,
1062                _p_thread_lock: PhantomData,
1063            }   
1064        );
1065    }
1066
1067    /// Attempts to perform the copy-on-write by copying [Clone] the inner value `ITEM`.
1068    /// 
1069    /// See [CowTransactionGuard] for more info.
1070    /// 
1071    /// Either a [Result::Ok] with [CowTransactionGuard] or [Result::Err] with [CowGuardError]
1072    /// is returned.
1073    pub 
1074    fn try_start_cloning(&self) -> Result<CowTransactionGuard<'_, ITEM>, CowGuardError>
1075    {
1076        let cloned_read = self.try_borrow()?;
1077
1078        let new_inst = unsafe { cloned_read.inst.inst.as_ref()}.item.clone();
1079
1080        return Ok(
1081            CowTransactionGuard
1082            {
1083                icow: self, 
1084                new_inst: new_inst,
1085                cloned_read: cloned_read,
1086                _p_thread_lock: PhantomData,
1087            }   
1088        );
1089    }
1090}
1091
1092impl<ITEM: Send + fmt::Debug + Default>  InstanceCopyOnWrite<ITEM>
1093{
1094    /// Performing the copy-on-write by creating the default [Default] of the inner value `ITEM`.
1095    /// 
1096    /// See [CowTransactionGuard] for more info.
1097    /// 
1098    /// Either a [Result::Ok] with [CowTransactionGuard] or [Result::Err] with [CowGuardError]
1099    /// is returned.
1100    pub 
1101    fn start_default(&self) -> Result<CowTransactionGuard<'_, ITEM>, CowGuardError>
1102    {   
1103        let cloned_read = self.borrow()?;
1104
1105        return Ok(
1106            CowTransactionGuard
1107            {
1108                icow: self, 
1109                new_inst: ITEM::default(),
1110                cloned_read: cloned_read,
1111                _p_thread_lock: PhantomData,
1112            }
1113        );
1114    }
1115
1116    /// Attempts to perform the copy-on-write by creating the default [Default] 
1117    /// of the inner value `ITEM`.
1118    /// 
1119    /// See [CowTransactionGuard] for more info.
1120    /// 
1121    /// Either a [Result::Ok] with [CowTransactionGuard] or [Result::Err] with [CowGuardError]
1122    /// is returned.
1123    pub 
1124    fn try_start_default(&self) -> Result<CowTransactionGuard<'_, ITEM>, CowGuardError>
1125    {
1126        let cloned_read = self.try_borrow()?;
1127
1128        return Ok(
1129            CowTransactionGuard
1130            {
1131                icow: self, 
1132                new_inst: ITEM::default(),
1133                cloned_read: cloned_read,
1134                _p_thread_lock: PhantomData,
1135            }
1136        );
1137    }
1138}
1139
1140impl<ITEM: Send + fmt::Debug>  InstanceCopyOnWrite<ITEM>
1141{
1142    /// Performing the copy-on-write from the provided instance of the inner value `ITEM`.
1143    /// 
1144    /// See [CowTransactionGuard] for more info.
1145    /// 
1146    /// Either a [Result::Ok] with [CowTransactionGuard] or [Result::Err] with [CowGuardError]
1147    /// is returned.
1148    pub 
1149    fn start_new(&self, new_inst: ITEM) -> Result<CowTransactionGuard<'_, ITEM>, CowGuardError>
1150    {
1151        let cloned_read = self.borrow()?;
1152        
1153        return Ok(
1154            CowTransactionGuard
1155            {
1156                icow: self, 
1157                new_inst: new_inst,
1158                cloned_read: cloned_read,
1159                _p_thread_lock: PhantomData,
1160            }
1161        );
1162    }
1163
1164    /// Attempting to perform the copy-on-write from the provided instance of the inner 
1165    /// value `ITEM`.
1166    /// 
1167    /// See [CowTransactionGuard] for more info.
1168    /// 
1169    /// Either a [Result::Ok] with [CowTransactionGuard] or [Result::Err] with [CowGuardError]
1170    /// is returned.
1171    pub 
1172    fn try_start_new(&self, new_inst: ITEM) -> Result<CowTransactionGuard<'_, ITEM>, CowGuardError>
1173    {
1174        let cloned_read = self.try_borrow()?;
1175        
1176        return Ok(
1177            CowTransactionGuard
1178            {
1179                icow: self, 
1180                new_inst: new_inst,
1181                cloned_read: cloned_read,
1182                _p_thread_lock: PhantomData,
1183            }
1184        );
1185    }
1186}
1187
1188#[cfg(test)]
1189mod tests
1190{
1191    use std::{sync::{atomic::Ordering, mpsc, LazyLock, Mutex}, time::{Duration, Instant}};
1192
1193
1194    use crate::{CowGuardError, InstanceCopyOnWrite, InstanceCopyOnWriteInner, NoCowGuardErr};
1195
1196    #[derive(Debug, Copy, Clone)]
1197    struct TestStruct
1198    {
1199        start: u64,
1200        stop: u64
1201    }
1202
1203    impl TestStruct
1204    {
1205        fn new(val: u64, val2: u64) -> Self
1206        {
1207            return Self{ start: val, stop: val2 };
1208        }
1209    }
1210
1211    #[test]
1212    fn test_bench()
1213    {
1214        let val = 
1215            InstanceCopyOnWrite::new(TestStruct::new(1, 2));
1216
1217        for _ in 0..10
1218        {
1219            let inst_glob = Instant::now();
1220            let test_borrow = val.borrow().unwrap();
1221
1222            let e_g = inst_glob.elapsed();
1223            println!("{:?}", e_g);
1224        }
1225
1226        println!("mux");
1227        
1228        let mux = Mutex::new(TestStruct::new(1, 2));
1229
1230        for _ in 0..10
1231        {
1232            let inst_glob = Instant::now();
1233            let test_borrow = val.lock().unwrap();
1234
1235            let e_g = inst_glob.elapsed();
1236            println!("{:?}", e_g);
1237        }
1238    }
1239
1240    #[test]
1241    fn test_simple_nocow()
1242    {
1243        
1244        let val = 
1245            InstanceCopyOnWrite::new(TestStruct::new(1, 2));
1246
1247        let test_borrow = val.borrow().unwrap().start;
1248
1249
1250        assert_eq!(test_borrow, 1);
1251
1252        let lock = val.lock();
1253
1254        assert_eq!(lock.is_ok(), true);
1255
1256        let mut lock = lock.unwrap();
1257
1258        let lock_dup = val.lock();
1259
1260        assert_eq!(lock_dup.is_err(), true);
1261
1262        lock.start = 2;
1263        lock.stop = 3;
1264
1265        drop(lock);
1266
1267        let borrow = val.borrow().unwrap();
1268
1269        assert_eq!(borrow.start, 2);
1270        assert_eq!(borrow.stop, 3);
1271
1272    }
1273
1274    #[test]
1275    fn test_simple_multithread_lock_parking_test()
1276    {
1277        static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> = 
1278            LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2))); 
1279
1280        let borrow1 = VAL.borrow().unwrap();
1281            assert_eq!(borrow1.start, 1);
1282            assert_eq!(borrow1.stop, 2);
1283
1284        let inst_glob = Instant::now();
1285
1286        let thread1 = 
1287                std::thread::spawn(move ||
1288                    {
1289                        let mut lock = VAL.lock().unwrap();
1290
1291                            
1292
1293                        lock.start = 5;
1294                        lock.stop = 6;
1295                        //let _ = mpsc_send.send(1);
1296
1297                        std::thread::sleep(Duration::from_millis(944));
1298
1299                        drop(lock);
1300                    }
1301                );
1302
1303        drop(borrow1);
1304
1305        std::thread::sleep(Duration::from_micros(1));
1306        let inst = Instant::now();
1307        
1308        let borrow2 = VAL.borrow().unwrap();
1309
1310        let e_g = inst_glob.elapsed();
1311        let e_b = inst.elapsed();    
1312
1313        println!("{:?} {:?}", e_g, e_b);  
1314
1315        let dur = e_g - e_b;
1316        println!("{}", dur.as_millis());
1317        assert_eq!(dur.as_millis(), 0);
1318    }
1319
1320    //fix e_g - e_th
1321    #[test]
1322    fn test_simple_multithread_lock_parking_test2()
1323    {
1324        static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> = 
1325            LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2))); 
1326
1327        let borrow1 = VAL.borrow().unwrap();
1328            assert_eq!(borrow1.start, 1);
1329            assert_eq!(borrow1.stop, 2);
1330
1331        
1332        let inst_glob = Instant::now();
1333        let thread1 = 
1334                std::thread::spawn(move ||
1335                    {
1336                        let inst_loc = Instant::now();
1337                        let mut lock = VAL.lock().unwrap();
1338                        let e_g = inst_loc.elapsed();
1339                            
1340
1341                        lock.start = 5;
1342                        lock.stop = 6;
1343                        //let _ = mpsc_send.send(1);
1344
1345                        
1346
1347                        drop(lock);
1348
1349                        return e_g;
1350                    }
1351                );
1352
1353        std::thread::sleep(Duration::from_millis(944));
1354        drop(borrow1);
1355        let e_g = inst_glob.elapsed();
1356        
1357        let e_th = thread1.join().unwrap();
1358        println!("{:?} {:?}", e_g, e_th);  
1359
1360        let dur = e_g - e_th;
1361        println!("{}", dur.as_millis());
1362        assert_eq!(dur.as_millis(), 0);
1363    }
1364
1365    //todo fix
1366    #[test]
1367    fn test_simple_multithread_lock_comp()
1368    {
1369        static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> = 
1370            LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2))); 
1371        
1372
1373            let borrow1 = VAL.borrow().unwrap();
1374            assert_eq!(borrow1.start, 1);
1375            assert_eq!(borrow1.stop, 2);
1376
1377            let (mpsc_send, mpsc_rcv) = mpsc::channel::<u64>();
1378            let (mpsc_send2, mpsc_rcv2) = mpsc::channel::<u64>();
1379
1380            let thread1 = 
1381                std::thread::spawn(move ||
1382                    {
1383                        for _ in 0..10000
1384                        {
1385                            let mut lock = 
1386                                loop
1387                                {
1388                                    let lock = VAL.lock();
1389
1390                                    if let Err(NoCowGuardErr::AlreadyLocked) = lock
1391                                    {
1392                                        std::thread::sleep(Duration::from_nanos(100));
1393                                        continue;
1394                                    }
1395
1396                                    break lock.unwrap();
1397                                };
1398
1399                            
1400
1401                            lock.start = 5;
1402                            lock.stop = 6;
1403                            
1404                           drop(lock);
1405                           /*let borrow2 = VAL.borrow().unwrap();
1406                            assert_eq!(borrow2.start, 5);
1407                            assert_eq!(borrow2.stop, 6);
1408                            drop(borrow2);*/
1409
1410                            let _ = mpsc_send.send(1);
1411
1412                            let _ = mpsc_rcv2.recv();
1413
1414                            std::thread::sleep(Duration::from_nanos(1000));
1415                        }
1416                    }
1417                );
1418            
1419            drop(borrow1);
1420
1421            for i in 0..10000
1422            {
1423                let val = mpsc_rcv.recv();
1424               // println!("i: {} {:?}", i, val);
1425
1426                
1427                
1428                let e_b =
1429                    {
1430                        let inst = Instant::now();
1431                    let borrow2 = VAL.borrow().unwrap();
1432
1433                    let e_b = inst.elapsed();
1434
1435                    assert_eq!(borrow2.start, 5);
1436                    assert_eq!(borrow2.stop, 6);
1437
1438                    drop(borrow2);
1439
1440                    e_b
1441                    };
1442                 let _ = mpsc_send2.send(1);
1443
1444                let inst = Instant::now();
1445                let mut lock = VAL.lock().unwrap();
1446                let e_l = inst.elapsed();
1447
1448                lock.start = 1;
1449                lock.stop = 2;
1450
1451                drop(lock);
1452
1453                println!("b: {:?} e: {:?}", e_b, e_l);
1454                assert!(e_b.as_millis() == 0);
1455                assert!(e_l.as_millis() == 0);
1456            }
1457            
1458            let borrow1 = VAL.borrow().unwrap();
1459            assert_eq!(borrow1.start, 1);
1460            assert_eq!(borrow1.stop, 2);
1461
1462            thread1.join().unwrap();        
1463
1464    }
1465
1466
1467    #[test]
1468    fn test_simple_copy()
1469    {
1470        let val = 
1471            InstanceCopyOnWrite::new(TestStruct::new(1, 2));
1472
1473        let s = Instant::now();
1474        let borrow1 = val.borrow().unwrap();
1475        let e = s.elapsed();
1476
1477        let s = Instant::now();
1478        let borrow2 = val.borrow().unwrap();
1479        let e2 = s.elapsed();
1480
1481        println!("{:?} {:?}", e, e2);
1482
1483        assert_eq!(borrow1.start, 1);
1484        assert_eq!(borrow1.stop, 2);
1485
1486        assert_eq!(borrow1.start, borrow2.start);
1487        assert_eq!(borrow1.stop, borrow2.stop);
1488
1489        let mut transaction = val.start_copying().unwrap();
1490
1491        transaction.start = 5;
1492        transaction.stop = 6;
1493
1494        assert_eq!(borrow1.start, 1);
1495        assert_eq!(borrow1.stop, 2);
1496
1497        transaction.completed(false).unwrap();
1498
1499        assert_eq!(borrow1.start, 1);
1500        assert_eq!(borrow1.stop, 2);
1501
1502        let borrow3 = val.borrow().unwrap();
1503
1504        assert_eq!(borrow3.start, 5);
1505        assert_eq!(borrow3.stop, 6);
1506
1507        drop(borrow1);
1508
1509        let refs = borrow2.inst.inner().refs.load(std::sync::atomic::Ordering::Relaxed);
1510        assert_eq!(refs, 1);
1511
1512        let weak_tag = borrow2.inst.inner().get_weak_tag();
1513
1514        {
1515            let arc_upg = weak_tag.upgrade();
1516            assert_eq!(arc_upg.is_some(), true);
1517        }
1518
1519        drop(borrow2);
1520
1521        {
1522            let arc_upg = weak_tag.upgrade();
1523            assert_eq!(arc_upg.is_none(), true);
1524        }
1525        
1526    }
1527
1528    #[derive(Debug, Default)]
1529    struct TestStructDef
1530    {
1531        start: Option<u64>,
1532        stop: Option<u64>,
1533    }
1534
1535    impl TestStructDef
1536    {
1537        fn new(val: u64, val2: u64) -> Self
1538        {
1539            return Self{ start: Some(val), stop: Some(val2) };
1540        }
1541    }
1542
1543
1544    #[test]
1545    fn test_simple_default()
1546    {
1547        let val = 
1548            InstanceCopyOnWrite::new(TestStructDef::new(1, 2));
1549
1550        let s = Instant::now();
1551        let borrow1 = val.borrow().unwrap();
1552        let e = s.elapsed();
1553
1554        for _ in 0..10
1555        {
1556        let s = Instant::now();
1557        let borrow2 = val.borrow().unwrap();
1558        let e2 = s.elapsed();
1559        println!("{:?} {:?}", e, e2);
1560
1561        }
1562
1563        let s = Instant::now();
1564        let borrow2 = val.borrow().unwrap();
1565        let e2 = s.elapsed();
1566        println!("{:?} {:?}", e, e2);
1567
1568        assert_eq!(borrow1.start, Some(1));
1569        assert_eq!(borrow1.stop, Some(2));
1570
1571        assert_eq!(borrow1.start, borrow2.start);
1572        assert_eq!(borrow1.stop, borrow2.stop);
1573
1574        let mut transaction = val.start_default().unwrap();
1575
1576        transaction.start = Some(5);
1577        transaction.stop = Some(6);
1578
1579        assert_eq!(borrow1.start, Some(1));
1580        assert_eq!(borrow1.stop, Some(2));
1581
1582        transaction.completed(false).unwrap();
1583
1584        assert_eq!(borrow1.start, Some(1));
1585        assert_eq!(borrow1.stop, Some(2));
1586
1587        let borrow3 = val.borrow().unwrap();
1588
1589        assert_eq!(borrow3.start, Some(5));
1590        assert_eq!(borrow3.stop, Some(6));
1591
1592        drop(borrow1);
1593
1594        let refs = borrow2.inst.inner().refs.load(std::sync::atomic::Ordering::Relaxed);
1595        assert_eq!(refs, 1);
1596
1597        let weak_tag = borrow2.inst.inner().get_weak_tag();
1598
1599        {
1600            let arc_upg = weak_tag.upgrade();
1601            assert_eq!(arc_upg.is_some(), true);
1602        }
1603
1604        drop(borrow2);
1605
1606        {
1607            let arc_upg = weak_tag.upgrade();
1608            assert_eq!(arc_upg.is_none(), true);
1609        }
1610        
1611    }
1612
1613    #[test]
1614    fn test_simple_multithread_clone()
1615    {
1616        static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> = 
1617            LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2))); 
1618        
1619
1620        let borrow1 = VAL.borrow().unwrap();
1621
1622        let thread1 = 
1623            std::thread::spawn(move ||
1624                {
1625                    let borrow1 = VAL.borrow().unwrap();
1626
1627                    let mut transaction = VAL.start_copying().unwrap();
1628
1629                    transaction.start = 5;
1630                    transaction.stop = 6;
1631
1632                    transaction.completed(false).unwrap();
1633
1634                    let borrow2 = VAL.borrow().unwrap();
1635
1636                    assert_eq!(borrow1.start, 1);
1637                    assert_eq!(borrow1.stop, 2);
1638
1639                    assert_eq!(borrow2.start, 5);
1640                    assert_eq!(borrow2.stop, 6);
1641                }
1642            );
1643        
1644        let borrow2 = VAL.borrow().unwrap();
1645        let borrow3 = VAL.borrow().unwrap();
1646        
1647        assert_eq!(borrow1.start, 1);
1648        assert_eq!(borrow1.stop, 2);
1649
1650        thread1.join().unwrap();
1651
1652        drop(borrow2);
1653        let weak_tag = borrow3.inst.inner().get_weak_tag();
1654        drop(borrow3);
1655
1656        {
1657            let arc_upg = weak_tag.upgrade();
1658            assert_eq!(arc_upg.is_some(), true);
1659        }
1660
1661        
1662    }
1663
1664    #[test]
1665    fn test_simple_multithread_clone_compl()
1666    {
1667        static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> = 
1668            LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2))); 
1669        
1670
1671        
1672        
1673        for _ in 0..100000
1674        {
1675            let borrow1 = VAL.borrow().unwrap();
1676            assert_eq!(borrow1.start, 1);
1677            assert_eq!(borrow1.stop, 2);
1678
1679            let (mpsc_send, mpsc_rcv) = mpsc::channel::<u64>();
1680
1681            let thread1 = 
1682                std::thread::spawn(move ||
1683                    {
1684                        let borrow1 = VAL.borrow().unwrap();
1685
1686                        let mut transaction = VAL.start_copying().unwrap();
1687
1688                        transaction.start = 5;
1689                        transaction.stop = 6;
1690
1691                        let _ = mpsc_send.send(1);
1692
1693                        std::thread::sleep(Duration::from_micros(1));
1694                        transaction.completed(false).unwrap();
1695
1696                        let borrow2 = VAL.borrow().unwrap();
1697
1698                        assert_eq!(borrow1.start, 1);
1699                        assert_eq!(borrow1.stop, 2);
1700
1701                        assert_eq!(borrow2.start, 5);
1702                        assert_eq!(borrow2.stop, 6);
1703                    }
1704                );
1705            
1706            let _ = mpsc_rcv.recv();
1707
1708            for _ in 0..100000000
1709            {
1710                let borrow2 = VAL.borrow().unwrap();
1711
1712                if borrow2.start == 1
1713                {
1714                    continue;
1715                }
1716                else
1717                {
1718                    break;
1719                }
1720            }
1721            
1722            let borrow1 = VAL.borrow().unwrap();
1723            assert_eq!(borrow1.start, 5);
1724            assert_eq!(borrow1.stop, 6);
1725
1726            thread1.join().unwrap();
1727
1728            let mut transaction = VAL.start_copying().unwrap();
1729            transaction.start = 1;
1730            transaction.stop = 2;
1731            transaction.completed(false).unwrap();
1732        }
1733
1734    }
1735
1736    #[test]
1737    fn test_simple_multithread_clone_compl_fast()
1738    {
1739        static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> = 
1740            LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2))); 
1741        
1742
1743        
1744        
1745        for i in 0..100000
1746        {
1747            let borrow1 = VAL.borrow().unwrap();
1748            assert_eq!(borrow1.start, 1);
1749            assert_eq!(borrow1.stop, 2);
1750
1751            let (mpsc_send, mpsc_rcv) = mpsc::channel::<u64>();
1752
1753            let thread1 = 
1754                std::thread::spawn(move ||
1755                    {
1756                        let borrow1 = VAL.borrow().unwrap();
1757
1758                        let mut transaction = VAL.start_copying().unwrap();
1759
1760                        transaction.start = 5;
1761                        transaction.stop = 6;
1762
1763                        let _ = mpsc_send.send(1);
1764
1765                        std::thread::sleep(Duration::from_nanos(100001-i));
1766                        transaction.completed(false).unwrap();
1767
1768                        let borrow2 = VAL.borrow().unwrap();
1769
1770                        assert_eq!(borrow1.start, 1);
1771                        assert_eq!(borrow1.stop, 2);
1772
1773                        assert_eq!(borrow2.start, 5);
1774                        assert_eq!(borrow2.stop, 6);
1775                    }
1776                );
1777            
1778            let _ = mpsc_rcv.recv();
1779
1780            for _ in 0..100000000
1781            {
1782                let borrow2 = VAL.borrow().unwrap();
1783
1784                if borrow2.start == 1
1785                {
1786                    continue;
1787                }
1788                else
1789                {
1790                    break;
1791                }
1792            }
1793            
1794            let borrow1 = VAL.borrow().unwrap();
1795            assert_eq!(borrow1.start, 5);
1796            assert_eq!(borrow1.stop, 6);
1797
1798            thread1.join().unwrap();
1799
1800            let mut transaction = VAL.start_copying().unwrap();
1801            transaction.start = 1;
1802            transaction.stop = 2;
1803            transaction.completed(false).unwrap();
1804        }
1805
1806    }
1807
1808    #[test]
1809    fn test_simple_multithread_clone_compl2()
1810    {
1811        static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> = 
1812            LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2))); 
1813        
1814
1815        
1816        
1817            let borrow1 = VAL.borrow().unwrap();
1818            assert_eq!(borrow1.start, 1);
1819            assert_eq!(borrow1.stop, 2);
1820
1821            let (mpsc_send, mpsc_rcv) = mpsc::channel::<u64>();
1822            let (mpsc_send2, mpsc_rcv2) = mpsc::channel::<u64>();
1823
1824            let thread1 = 
1825                std::thread::spawn(move ||
1826                    {
1827                        for _ in 0..1000
1828                        {
1829                            let _ = mpsc_rcv2.recv();
1830                            let borrow1 = VAL.borrow().unwrap();
1831
1832                            let mut transaction = VAL.start_copying().unwrap();
1833
1834                            transaction.start = 5;
1835                            transaction.stop = 6;
1836
1837                            
1838
1839                            std::thread::sleep(Duration::from_nanos(1001));
1840                            transaction.completed(false).unwrap();
1841
1842                            let borrow2 = VAL.borrow().unwrap();
1843                            
1844
1845                            assert_eq!(borrow1.start, 1);
1846                            assert_eq!(borrow1.stop, 2);
1847
1848                            assert_eq!(borrow2.start, 5);
1849                            assert_eq!(borrow2.stop, 6);
1850
1851                            let _ = mpsc_send.send(1);
1852                        }
1853                    }
1854                );
1855            
1856            
1857
1858            for x in 0..1000
1859            {
1860                println!("{}", x);
1861                mpsc_send2.send(1).unwrap();
1862                let _ = mpsc_rcv.recv();
1863
1864                let borrow1 = VAL.borrow().unwrap();
1865                assert_eq!(borrow1.start, 5);
1866                assert_eq!(borrow1.stop, 6);
1867
1868                let mut transaction = VAL.start_copying().unwrap();
1869                transaction.start = 1;
1870                transaction.stop = 2;
1871                transaction.completed(false).unwrap();
1872
1873                let borrow1 = VAL.borrow().unwrap();
1874                assert_eq!(borrow1.start, 1);
1875                assert_eq!(borrow1.stop, 2);
1876                
1877            }
1878            
1879            
1880
1881            thread1.join().unwrap();
1882
1883            
1884        }
1885
1886
1887    #[test]
1888    fn test_thread_local()
1889    {
1890        static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> = 
1891            LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2))); 
1892
1893        static VAL2: LazyLock<InstanceCopyOnWrite<TestStruct>> = 
1894            LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2))); 
1895
1896        static VAL3: LazyLock<InstanceCopyOnWrite<TestStruct>> = 
1897            LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2))); 
1898
1899        let borrow1 = VAL.borrow().unwrap();
1900            assert_eq!(borrow1.start, 1);
1901            assert_eq!(borrow1.stop, 2);
1902
1903        let borrow_ptr_0 = borrow1.inst.inst.as_ptr().addr();
1904
1905        let thread1 = 
1906                std::thread::spawn(move ||
1907                    {
1908                        let b = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| v.get(&borrow_ptr_0).map(|v| *v).clone());
1909
1910                        return b;
1911                    }
1912                );
1913        
1914        let thread_borrow = thread1.join().unwrap();
1915        
1916        let local_borrow = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| *(v.get(&borrow_ptr_0).unwrap()));
1917
1918        println!("tthread: {:?}, local: {}", thread_borrow, local_borrow);
1919
1920        assert_eq!(thread_borrow.is_none(), true);
1921        assert_eq!(local_borrow, 1);
1922
1923        drop(borrow1);
1924
1925        let local_borrow = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| *(v.get(&borrow_ptr_0).unwrap()));
1926
1927        println!("tthread: {:?}, local: {}", thread_borrow, local_borrow);
1928        assert_eq!(local_borrow, 0);
1929
1930
1931        // check deadlocks
1932        let borrow1 = VAL.borrow().unwrap();
1933            assert_eq!(borrow1.start, 1);
1934            assert_eq!(borrow1.stop, 2);
1935
1936        let res = VAL.lock();
1937        assert_eq!(Some(NoCowGuardErr::Borrowed), res.err());
1938
1939        drop(borrow1);
1940
1941        // check double lock
1942        let res1 = VAL2.lock();
1943        assert_eq!(true, res1.is_ok(), "{:?}", res1);
1944
1945        let borrow_ptr_1 = res1.as_ref().unwrap().inst.inst.as_ptr().addr();
1946
1947        let res2 = VAL2.lock();
1948        assert_eq!(Some(NoCowGuardErr::AlreadyLocked), res2.err());
1949
1950        // -----
1951        let thread1 = 
1952            std::thread::spawn(move ||
1953                {
1954                    let borrow1 = VAL2.try_borrow();
1955                    assert_eq!(borrow1.err(), Some(CowGuardError::WouldBlock));
1956
1957                    let borrow1 = VAL.borrow().unwrap();
1958                    assert_eq!(borrow1.start, 1);
1959                    assert_eq!(borrow1.stop, 2);
1960
1961                    let b = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| v.get(&borrow_ptr_0).map(|v| *v).clone());
1962
1963                    let mut clone = VAL3.start_cloning().unwrap();
1964
1965                    let borrow_ptr_2 = VAL3.owner_inner.load(Ordering::Relaxed).addr();
1966
1967                    clone.start = 3;
1968
1969                    clone.completed(false).unwrap();
1970
1971                    let b2 = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| v.get(&borrow_ptr_1).map(|v| *v).clone());
1972
1973                    let b3 = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| v.get(&borrow_ptr_2).map(|v| *v).clone());
1974
1975                    return (b, b2, b3);
1976                }
1977            );
1978
1979            
1980        let borrow_ptr_2 = VAL3.owner_inner.load(Ordering::Relaxed).addr();
1981
1982        let local_borrow1 = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| (v.get(&borrow_ptr_0).map(|v| *v).clone()));
1983        let local_borrow2 = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| (v.get(&borrow_ptr_1).map(|v| *v).clone()));
1984        let local_borrow3 = InstanceCopyOnWriteInner::<TestStruct>::BORROWS.with_borrow(|v| (v.get(&borrow_ptr_2).map(|v| *v).clone()));
1985
1986        let (thread_borrow1, thread_borrow2, thread_borrow3) = thread1.join().unwrap();
1987        drop(res1.unwrap());
1988
1989        assert_eq!(Some(0), local_borrow1);
1990        assert_eq!(Some(1), thread_borrow1);
1991
1992        assert_eq!(None, thread_borrow2);
1993        assert_eq!(None, local_borrow2);
1994
1995        assert_eq!(None, thread_borrow3);
1996        assert_eq!(None, local_borrow3);
1997    }
1998    
1999
2000    //todo poison test
2001
2002    #[test]
2003    #[should_panic(expected = "test panic1")]
2004    fn test_thread_poison()
2005    {
2006        static VAL: LazyLock<InstanceCopyOnWrite<TestStruct>> = 
2007            LazyLock::new(|| InstanceCopyOnWrite::new(TestStruct::new(1, 2))); 
2008
2009           
2010        let borrow1 = VAL.borrow().unwrap();
2011            assert_eq!(borrow1.start, 1);
2012            assert_eq!(borrow1.stop, 2);
2013
2014
2015        let thread1 = 
2016                std::thread::spawn(move ||
2017                    {
2018                        let mut lock = VAL.lock().unwrap();
2019                        lock.start = 2;
2020                        std::thread::sleep(Duration::from_micros(1));
2021
2022                        panic!("test panic1");
2023                    }
2024                );
2025
2026        drop(borrow1);
2027
2028        let thread_res = thread1.join();
2029
2030        let borrow = VAL.borrow();
2031        assert_eq!(Some(CowGuardError::Poisoned), borrow.err());
2032
2033        let lock = VAL.lock();
2034        assert_eq!(Some(NoCowGuardErr::Poisoned), lock.err());
2035
2036        let transaction = VAL.start_copying();
2037        assert_eq!(Some(CowGuardError::Poisoned), transaction.err());
2038
2039        println!("{:?}", thread_res);
2040
2041        panic!("test panic1");
2042    } 
2043
2044    #[test]
2045    fn test_main_drop()
2046    {
2047         let val = 
2048            InstanceCopyOnWrite::new(TestStruct::new(1, 2));
2049
2050        {
2051        let test_borrow = val.borrow().unwrap().start;
2052
2053        assert_eq!(test_borrow, 1);
2054        }
2055
2056        {
2057        let lock = val.lock();
2058
2059        assert_eq!(lock.is_ok(), true);
2060
2061        let mut lock = lock.unwrap();
2062
2063        let lock_dup = val.lock();
2064
2065        assert_eq!(lock_dup.is_err(), true);
2066
2067        lock.start = 2;
2068        lock.stop = 3;
2069
2070        drop(lock);
2071        }
2072
2073        {
2074        let borrow = val.borrow().unwrap();
2075
2076        drop(borrow);
2077        }
2078
2079        drop(val);
2080
2081        return;
2082    }
2083}
2084