1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#![no_std]

extern crate alloc;
extern crate spin;
extern crate dereffer;

use alloc::sync::{Arc, Weak};
use spin::{Mutex, MutexGuard};
use dereffer::{DerefsTo, DerefsToMut};

/// A special form of an `Arc` reference that uses two nested `Arc`s to support a 
/// mechanism similar to copy-on-write or clone-on-write.
/// 
/// Effectively, this type reduces to `Arc<Arc<Mutex<T>>>`.
/// 
/// Unlike regular `Arc`s, which do not permit mutability if there are multiple strong or weak references
/// to the data inside the `Arc`, the `CowArc` type can still allow interior mutability of the data `T`
/// when there are multiple strong or weak references to it. 
/// This works by treating the inner `Arc` reference as the actual reference count,
/// enabling it to differentiate between two states:     
/// * Exclusive:  only a single strong reference to the internal `Arc`, 
///   meaning that it is okay to mutate the data.
/// * Shared:  there are multiple strong references to the internal `Arc`,
///   meaning that it cannot be accessed mutably. 
/// 
/// The inner data `T` is protected by a `Mutex`, allowing it to be borrowed mutably 
/// when the `CowArc` is in the `Exclusive` state only. 
/// The inner data can be borrowed immutably in either state. 
/// 
/// This point of this data type is to encourage deeply copying data that's in the `Shared` state
/// in order to modify it, because deeply copying (cloning) `Shared` data will yield a new instance
/// that starts in the `Exclusive` state by default.
/// 
/// Finally, the `CowArc` type can be "cloned" in two ways:     
/// * using the regular `clone` function, which actually affects the shared state
///   by duplicating the inner reference, meaning that the `CowArc` will be in the shared state after invoking `clone`,
/// * using the [`clone_shallow`](#method.clone_shallow) function, which does not affect the shared state
///   and only duplicates the outer reference. 
#[derive(Debug)]
pub struct CowArc<T> {
    arc: Arc<InnerArc<T>>,
}
impl<T> CowArc<T> {
    /// Crates a new `CowArc` that wraps the given data. 
    /// The new `CowArc` will be in the `Exclusive` state, 
    /// that is, not shared. 
    pub fn new(data: T) -> CowArc<T> {
        CowArc {
            arc: Arc::new(InnerArc {
                inner_arc: Arc::new(Mutex::new(data)),
            })
        }
    }

    /// This acquires the lock on the inner `Mutex` wrapping the data `T`,
    /// and always succeeds because an `CowArc` always allows immutable access to the data,
    /// regardless of whether the data is `Shared` or `Exclusive`.
    /// 
    /// The returned value derefs to and can be used exactly like `&T`.
    pub fn lock_as_ref(&self) -> DerefsTo<MutexGuard<T>, T> {
        DerefsTo::new_default(self.arc.inner_arc.lock())
    }

    /// This attempts to acquire the lock on the inner `Mutex` wrapping the data `T`.
    /// 
    /// This returns `None` if the lock is currently held, 
    /// but will always succeed if the lock is not held
    /// because an `CowArc` always allows immutable access to the data,
    /// regardless of whether the data is `Shared` or `Exclusive`.
    /// 
    /// The returned value derefs to and can be used exactly like `&T`.
    pub fn try_lock_as_ref(&self) -> Option<DerefsTo<MutexGuard<T>, T>> {
        self.arc.inner_arc.try_lock().map(DerefsTo::new_default)
    }

    /// This acquires the lock on the inner `Mutex` wrapping the data `T` if it succeeds,
    /// which only occurs if this `CowArc` is in the `Shared` state, i.e., 
    /// only a single strong reference to the inner `Arc` is held.
    /// 
    /// The returned value derefs to and can be used exactly like `&mut T`.
    pub fn lock_as_mut(&self) -> Option<DerefsToMut<MutexGuard<T>, T>> {
        if self.is_shared() {
            // shared state, should not mutate 
            None
        }
        else {
            Some(DerefsToMut::new_default(self.arc.inner_arc.lock()))
        }
    }

    /// Downgrades this `CowArc` into a `CowWeak` weak reference.
    pub fn downgrade(this: &CowArc<T>) -> CowWeak<T> {
        CowWeak {
            weak: InnerWeak {
                inner_weak: Arc::downgrade(&this.arc.inner_arc)
            },
        }
    }

    /// Returns `true` if this `CowArc` is in the `Shared` state, 
    /// and `false` if it is in the `Exclusive` state.
    pub fn is_shared(&self) -> bool {
        Arc::strong_count(&self.arc.inner_arc) > 1
    }

    /// Returns true if the two `CowArc`s point to the same value
    /// (not just values that compare as equal).
    pub fn ptr_eq(&self, other: &Self) -> bool {
        Arc::ptr_eq(&self.arc, &other.arc)
    }


    /// Creates a shallow clone of this `CowArc` that **does not** affect its `Shared` state.
    /// This means that it will not change it to `Shared` if it was `Exclusive,
    /// nor will it increase the shared count if it was already `Shared`. 
    /// 
    /// Likewise, dropping the returned reference will not decrement the shared count
    /// nor potentially change its state from `Shared` back to `Exclusive`.
    /// 
    /// This is useful for passing around a duplicate reference 
    /// to the same instance (of the outer reference) 
    /// that will be used somewhere else temporarily, e.g., in the same context,
    /// without marking it as a totally separate shared instance. 
    /// 
    /// The fact that this is different from the [`CowArc::clone`] function 
    /// is what differentiates the behavior of `CowArc` from regular `Arc`.
    pub fn clone_shallow(&self) -> CowArc<T> {
        CowArc {
            arc: Arc::clone(&self.arc),
        }
    }
}

impl<T> Clone for CowArc<T> {
    /// Creates a shared reference to `this` `CowArc` 
    /// and returns that shared reference as a new `CowArc`
    /// whose internal reference points to the same data.
    /// 
    /// This increases the shared count of this `CowArc`, 
    /// and the returned new `CowArc` instance will have 
    /// the same shared count and reference the same data.
    fn clone(&self) -> CowArc<T> {
        CowArc {
            arc: Arc::new(
                InnerArc {
                    inner_arc: Arc::clone(&self.arc.inner_arc),
                }
            ),
        }
    }
}




/// A weak reference to a `CowArc`, just like a `Weak` is to an `Arc`.
#[derive(Debug)]
pub struct CowWeak<T> {
    /// This must be a weak reference to the `InnerArc` inside the `CowArc`
    weak: InnerWeak<T>,
}
impl<T> CowWeak<T> {
    /// Just like `Weak::upgrade()`, attempts to upgrade this `CowWeak`
    /// into a strong reference to the `CowArc` that it points to.
    pub fn upgrade(&self) -> Option<CowArc<T>> {
        self.weak.inner_weak.upgrade().map(|inner_arc| CowArc {
            arc: Arc::new(InnerArc{ inner_arc }),
        })
    }
}
impl<T> Clone for CowWeak<T> {
    fn clone(&self) -> CowWeak<T> {
        CowWeak {
            weak: InnerWeak { 
                inner_weak: self.weak.inner_weak.clone()
            },
        }
    }
}


/// The inner reference inside of a `CowArc`.
#[derive(Debug)]
struct InnerArc<T> {
    inner_arc: Arc<Mutex<T>>,
}

/// The inner reference inside of a `CowWeak`.
#[derive(Debug)]
struct InnerWeak<T> {
    inner_weak: Weak<Mutex<T>>,
}