instance_copy_on_write/cow_refcell.rs
1/*-
2 * instance-copy-on-write - a synchronization primitive based on copy-on-write.
3 *
4 * Copyright (C) 2025 Aleksandr Morozov alex@4neko.org
5 *
6 * The instance-copy-on-write crate can be redistributed and/or modified
7 * under the terms of either of the following licenses:
8 *
9 * 1. The MIT License (MIT)
10 */
11
12
13use std::
14{
15 cell::RefCell, fmt, ops::{Deref, DerefMut}, rc::{Rc, Weak}
16};
17
18use crate::{ICoWLockTypes, ICowType};
19
20/// A Single thread realization.
21
22/// A read only guard. Implements [Deref] only. The guarded value is valid
23/// all the time, even if the inner value was updated. The updated value
24/// will not be visible in the current instance until `re-read` is
25/// performed.
26#[derive(Debug)]
27pub struct ICoWRead<'read, ITEM: Sized>
28{
29 /// Guarded value.
30 pub(crate) item: Rc<ITEM>,
31
32 /// A bind to base.
33 bind: &'read ICoW<ITEM>
34}
35
36impl<'read, ITEM: Sized> Deref for ICoWRead<'read, ITEM>
37{
38 type Target = ITEM;
39
40 fn deref(&self) -> &Self::Target
41 {
42 return &self.item;
43 }
44}
45
46impl<'read, ITEM: Sized> ICoWRead<'read, ITEM>
47{
48 /// Consumes the itance and returns the read-only value.
49 pub
50 fn into_inner(self) -> Rc<ITEM>
51 {
52 return self.item;
53 }
54
55 /// Returns the weak reference.
56 pub
57 fn weak(&self) -> Weak<ITEM>
58 {
59 return Rc::downgrade(&self.item);
60 }
61}
62
63impl<'read, ITEM: Sized + fmt::Debug + Copy> ICoWRead<'read, ITEM>
64{
65 /// Upgrades from [ICoWRead] `the self` to copy [ICoWCopy] which can
66 /// be commited to mainstream by using [Copy].
67 pub
68 fn upgrade_copy(self) -> ICoWCopy<'read, ITEM>
69 {
70 let new_item = *self.item;
71 let bind = self.bind;
72
73 return
74 ICoWCopy
75 {
76 prev_item: self,
77 new_item: new_item,
78 inst: bind
79 };
80 }
81}
82
83impl<'read, ITEM: Sized + fmt::Debug + Clone> ICoWRead<'read, ITEM>
84{
85 /// Upgrades from [ICoWRead] `the self` to copy [ICoWCopy] which can
86 /// be commited to mainstream by using [Clone].
87 pub
88 fn upgrade_clone_copy(self) -> ICoWCopy<'read, ITEM>
89 {
90 let new_item = self.item.as_ref().clone();
91 let bind = self.bind;
92
93 return
94 ICoWCopy
95 {
96 prev_item: self,
97 new_item: new_item,
98 inst: bind
99 };
100 }
101}
102
103impl<'read, ITEM: Sized + fmt::Debug + Default> ICoWRead<'read, ITEM>
104{
105 /// Upgrades from [ICoWRead] `the self` to copy [ICoWCopy] which can
106 /// be commited to mainstream by using [Default].
107 pub
108 fn upgrade_default(self) -> ICoWCopy<'read, ITEM>
109 {
110 let new_item = ITEM::default();
111 let bind = self.bind;
112
113 return
114 ICoWCopy
115 {
116 prev_item: self,
117 new_item: new_item,
118 inst: bind
119 };
120 }
121}
122
123/// A write-guard which holds new value to which the new data is written. And
124/// previous value too. This type of guard is not exclusive, so multiple
125/// CoW operations may be performed in parallel which is not normally needed.
126///
127/// The changes made in the current instance becomes visible for the rest
128/// of the threads only after commit.
129#[derive(Debug)]
130pub struct ICoWCopy<'copy, ITEM: Sized>
131{
132 /// A reference to previous value
133 prev_item: ICoWRead<'copy, ITEM>,
134
135 /// A freshly createc/copied/clonned item
136 new_item: ITEM,
137
138 /// A reference to base to avoid Send.
139 inst: &'copy ICoW<ITEM>
140}
141
142impl<'copy, ITEM: Sized> Deref for ICoWCopy<'copy, ITEM>
143{
144 type Target = ITEM;
145
146 fn deref(&self) -> &Self::Target
147 {
148 return &self.new_item;
149 }
150}
151
152impl<'copy, ITEM: Sized> DerefMut for ICoWCopy<'copy, ITEM>
153{
154 fn deref_mut(&mut self) -> &mut Self::Target
155 {
156 return &mut self.new_item
157 }
158}
159
160impl<'copy, ITEM: Sized> ICoWCopy<'copy, ITEM>
161{
162 /// Returns a reference to previous value. To access modified version use
163 /// [Deref] or [DerefMut].
164 pub
165 fn prev_val(&self) -> &ITEM
166 {
167 return &self.prev_item;
168 }
169
170 /// Commits the changes made in the guarded variable. A non-blocking
171 /// function. It will not block the thread completly and returns the
172 /// [ICoWError::WouldBlock] if attempt to grab the pointer atomically
173 /// fails in reasonable time. for blocking `commit` use
174 /// [Self::commit_blocking].
175 pub
176 fn commit(self)
177 {
178 *self.inst.inner.borrow_mut() = Rc::new(self.new_item);
179
180 return;
181 }
182
183 /// Drops the instance without commiting changes returning
184 /// a copy, clone, default, or new i.e what was in the `new` field
185 /// of the instance.
186 pub
187 fn into_inner(self) -> ITEM
188 {
189 return self.new_item;
190 }
191}
192
193/// A main structure which implements CoW approach based on [RwLock]. The object
194/// stored inside can be read directly, but modifying the `inner` value is
195/// performed using `CoW` copy-on-write approach.
196///
197/// The `read` operations are faster than `write`, because in order to `write` a
198/// more operations needs to be performed.
199///
200/// This is for Mutlithreading environment only. It will be usedless when using
201/// in single-thread programs. For the single thread, use a `SICoW` which would
202/// improve the performance.
203///
204/// The inner value must be either [Copy], [Clone], [Default], or provide
205/// new value manually. The copied value is modified and stored back either
206/// shared or exclusive method. The exclusive lock prevents other CoW operations
207/// guaranteeing the uniq write access.
208///
209/// ```ignore
210/// #[derive(Debug, Clone)]
211/// struct TestStruct { s: u32 }
212///
213/// let cow_val = ICoW::new(TestStruct{ s: 2 });
214///
215/// // read
216/// let read0 = cow_val.read().unwrap();
217/// // ...
218/// drop(read0);
219///
220/// // write new non-exclusivly
221/// let mut write0 = cow_val.try_clone_copy().unwrap();
222/// write0.s = 3;
223///
224/// write0.commit().unwrap();
225///
226/// // write new exclusivly
227/// let mut write0 = cow_val.try_clone_copy_exclusivly().unwrap();
228/// write0.s = 3;
229///
230/// write0.commit().unwrap();
231///
232/// ```
233#[derive(Debug)]
234pub struct ICoW<ITEM: Sized>
235{
236 /// A rwlock protected CoW.
237 inner: RefCell<Rc<ITEM>>,
238}
239
240impl<ITEM> ICowType for ICoW<ITEM>
241{
242 fn get_lock_type() -> ICoWLockTypes
243 {
244 return ICoWLockTypes::RwLock;
245 }
246}
247
248impl<ITEM> ICoW<ITEM>
249{
250 /// Initalizes a new instance.
251 pub
252 fn new(item: ITEM) -> Self
253 {
254 return
255 Self
256 {
257 inner:
258 RefCell::new(Rc::new(item)),
259 }
260 }
261
262 /// Attempts to read the inner value returning the guard. This function
263 /// blocks the current thread until the value becomes available. This
264 /// can happen if exclusive copy-on-write is in progress.
265 ///
266 /// # Returns
267 ///
268 /// An instance with clonned reference is returned.
269 pub
270 fn read(&self) -> ICoWRead<'_, ITEM>
271 {
272 let lock =
273 self
274 .inner
275 .borrow();
276
277 return ICoWRead{ item: lock.clone(), bind: self };
278 }
279
280 /// Updates old value to new value for the inner.
281 pub
282 fn new_inplace(&self, new_item: ITEM)
283 {
284 let read = self.read();
285
286 let ret =
287 ICoWCopy
288 {
289 prev_item: read,
290 new_item: new_item,
291 inst: self
292 };
293
294 ret.commit();
295
296 return;
297 }
298}
299
300impl<ITEM: fmt::Debug + Copy> ICoW<ITEM>
301{
302 /// Performs the copy of the inner value for writing.
303 ///
304 /// Blocking function i.e always retruns the result.
305 ///
306 /// # Returns
307 ///
308 /// An [ICoWCopy] is returned.
309 pub
310 fn copy(&self) -> ICoWCopy<'_, ITEM>
311 {
312 let read = self.read();
313
314 let new_item = *read.item.as_ref();
315
316 let ret =
317 ICoWCopy
318 {
319 prev_item: read,
320 new_item: new_item,
321 inst: self
322 };
323
324 return ret;
325 }
326}
327
328impl<ITEM: fmt::Debug + Clone> ICoW<ITEM>
329{
330 /// > [!IMPORTANT]
331 /// > Previously `clone()`. renamed to `clone_copy()` due to the
332 /// > conflict with [Clone].
333 ///
334 /// Attempts to perform the clone of the inner value for writing.
335 ///
336 /// Blocking function i.e always retruns the result.
337 ///
338 /// # Returns
339 ///
340 /// An [ICoWCopy] is returned.
341 pub
342 fn clone_copy(&self) -> ICoWCopy<'_, ITEM>
343 {
344 let read = self.read();
345
346 let new_item = read.item.as_ref().clone();
347
348 let ret =
349 ICoWCopy
350 {
351 prev_item: read,
352 new_item: new_item,
353 inst: self
354 };
355
356 return ret;
357 }
358}
359
360impl<ITEM: fmt::Debug + Default> ICoW<ITEM>
361{
362 /// Construct the guard from the [Default] of the inner value for writing.
363 ///
364 /// Blocking function i.e always retruns the result.
365 ///
366 /// # Returns
367 ///
368 /// An [Option] is returned where the [Option::None] is returned if
369 /// it failed.
370 pub
371 fn from_default(&self) -> ICoWCopy<'_, ITEM>
372 {
373 let read = self.read();
374
375 let new_item = ITEM::default();
376
377 let ret =
378 ICoWCopy
379 {
380 prev_item: read,
381 new_item: new_item,
382 inst: self
383 };
384
385 return ret;
386 }
387}
388
389
390#[cfg(test)]
391mod test
392{
393 // mutex based specific tests goes there
394}