instance_copy_on_write/
lib.rs1#[derive(Copy, Clone, Debug, PartialEq, Eq)]
16 pub enum ICoWLockTypes
17 {
18 Atomic,
20
21 RwLock,
23 }
24
25impl fmt::Display for ICoWLockTypes
26{
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
28 {
29 match self
30 {
31 Self::Atomic =>
32 write!(f, "atomic"),
33 Self::RwLock =>
34 write!(f, "rwlock"),
35 }
36 }
37}
38
39#[derive(Copy, Clone, Debug, PartialEq, Eq)]
41pub enum ICoWError
42{
43 ExclusiveLockPending,
46
47 WouldBlock,
49
50 AlreadyUpdated,
52}
53
54impl fmt::Display for ICoWError
55{
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
57 {
58 match self
59 {
60 Self::ExclusiveLockPending =>
61 write!(f, "already exlcusivly locked"),
62 Self::WouldBlock =>
63 write!(f, "cannot perform try operation due to blocking"),
64 Self::AlreadyUpdated =>
65 write!(f, "the value has been updated before the current thread"),
66 }
67 }
68}
69
70extern crate crossbeam_utils;
71extern crate crossbeam_deque;
72
73#[cfg(all(target_has_atomic = "ptr", feature = "prefer_atomic"))]
75pub mod cow;
76
77#[cfg(any(not(target_has_atomic = "ptr"), not(feature = "prefer_atomic")))]
79pub mod cow_mutex;
80
81use std::fmt;
82
83#[cfg(all(target_has_atomic = "ptr", feature = "prefer_atomic"))]
84pub use cow::{ICoW, ICoWRead, ICoWCopy, ICoWLock};
85
86#[cfg(any(not(target_has_atomic = "ptr"), not(feature = "prefer_atomic")))]
87pub use cow_mutex::{ICoW, ICoWRead, ICoWCopy, ICoWLock};
88
89
90#[cfg(test)]
91mod test
92{
93 use std::{sync::{mpsc, Arc, LazyLock}, time::{Duration, Instant}};
94
95 use super::*;
96
97
98
99
100 #[test]
101 fn test_3()
102 {
103 #[derive(Debug, Clone)]
104 struct Test { s: String };
105
106 let icow = ICoW::new(Test{ s: "test".into() });
107
108 for _ in 0..10
109 {
110 let s = Instant::now();
111
112 let read0 = icow.read();
113
114 let e = s.elapsed();
115
116 println!("{:?}", e);
117 }
118
119 }
120
121 #[test]
122 fn test_33()
123 {
124 #[derive(Debug, Clone)]
125 struct Test { s: String };
126
127 let icow = ICoW::new(Test{ s: "test".into() });
128
129 let write_ex = icow.try_clone_exclusivly().unwrap();
130
131 {
132 let write_ex_err = icow.try_clone_exclusivly();
133 assert_eq!(write_ex_err.is_none(), true);
134 }
135
136 let write_ex_err = icow.try_clone();
137 assert_eq!(write_ex_err.is_none(), true);
138
139 let read1 = icow.try_read();
140 assert_eq!(read1.is_none(), true);
141
142 drop(write_ex);
143
144 drop(icow);
145
146 }
147
148 #[test]
149 fn test_4()
150 {
151 #[derive(Debug, Clone)]
152 struct Test { s: u32 }
153
154 let icow = ICoW::new(Test{ s: 1 });
155
156 let read0 = icow.read();
157 let read1 = icow.read();
158
159 let mut excl_write = icow.try_clone_exclusivly().unwrap();
160
161 excl_write.item.s = 5;
162
163
164 excl_write.commit();
165
166 assert_eq!(read0.item.s, 1);
167
168 let read3 = icow.read();
169 assert_eq!(read3.item.s, 5);
170
171 let mut writing = icow.try_clone().unwrap();
172 writing.s = 4;
173
174 writing.commit().unwrap();
175
176 assert_eq!(read0.item.s, 1);
177 assert_eq!(read3.item.s, 5);
178
179 let read4 = icow.read();
180 assert_eq!(read4.s, 4);
181 }
182
183 #[test]
184 fn test_5()
185 {
186 #[derive(Debug, Clone)]
187 struct Test { s: u32 }
188
189 let icow = Arc::new(ICoW::new(Test{ s: 1 }));
190
191 let read0 = icow.read();
192 let read2 = icow.read();
193
194 let c_icow = icow.clone();
195
196 let (se, rc) = mpsc::channel::<()>();
197 let handler0 =
198 std::thread::spawn(move ||
199 {
200 let mut lock0 = c_icow.try_clone_exclusivly().unwrap();
201
202 se.send(()).unwrap();
203
204 lock0.item.s = 5;
205
206 std::thread::sleep(Duration::from_micros(2));
207
208 lock0.commit();
209 }
210 );
211
212 rc.recv().unwrap();
213
214 let s = Instant::now();
215
216 let read1 = icow.read();
217
218 let e = s.elapsed();
219
220 println!("{:?}", e);
221
222
223 assert_eq!(read1.item.s, 5);
224 assert_eq!(read0.item.s, 1);
225
226 handler0.join().unwrap();
227
228 let weak0 = read0.weak();
229 let weak1 = read1.weak();
230
231 drop(read0);
232 drop(read1);
233
234 assert_eq!(weak0.upgrade().is_some(), true);
235 assert_eq!(weak1.upgrade().is_some(), true);
236
237 drop(read2);
238 assert_eq!(weak0.upgrade().is_none(), true);
239 assert_eq!(weak1.upgrade().is_some(), true);
240 }
241
242
243 #[test]
244 fn test_6()
245 {
246 #[derive(Debug, Clone)]
247 struct Test { s: u32 }
248
249 let icow = Arc::new(ICoW::new(Test{ s: 1 }));
250
251 let read0 = icow.read();
252 let read2 = icow.read();
253
254 let c_icow = icow.clone();
255
256 let (se, rc) = mpsc::channel::<()>();
257 let handler0 =
258 std::thread::spawn(move ||
259 {
260 let read2 = c_icow.read();
261
262 let mut lock0 = c_icow.try_clone_exclusivly().unwrap();
263
264 se.send(()).unwrap();
265
266 lock0.item.s = 5;
267
268 std::thread::sleep(Duration::from_nanos(50));
269 lock0.commit();
270
271 let read3 = c_icow.read();
272
273 assert_eq!(read2.item.s, 1);
274 assert_eq!(read3.item.s, 5);
275 }
276 );
277
278 rc.recv().unwrap();
279
280 for _ in 0..100000000
281 {
282 let read1 = icow.read();
283
284 if read1.item.s == 1
285 {
286 continue;
287 }
288 else
289 {
290 break;
291 }
292 }
293
294 let read1 = icow.read();
295 assert_eq!(read1.item.s, 5);
296
297 handler0.join().unwrap();
298
299 return;
300 }
301
302
303 #[test]
304 fn test_7()
305 {
306 #[derive(Debug, Clone)]
307 struct TestStruct { s: u32 }
308
309 impl TestStruct
310 {
311 fn new(s: u32) -> Self
312 {
313 return Self{ s: s };
314 }
315 }
316
317 static VAL: LazyLock<ICoW<TestStruct>> =
318 LazyLock::new(|| ICoW::new(TestStruct::new(1)));
319
320
321
322
323 let borrow1 = VAL.read();
324 assert_eq!(borrow1.item.s, 1);
325
326 let (mpsc_send, mpsc_rcv) = mpsc::channel::<u64>();
327 let (mpsc_send2, mpsc_rcv2) = mpsc::channel::<u64>();
328
329 let thread1 =
330 std::thread::spawn(move ||
331 {
332 for _ in 0..1000
333 {
334 let _ = mpsc_rcv2.recv();
335 let borrow1 = VAL.read();
336
337 let mut transaction = VAL.try_clone_exclusivly().unwrap();
338
339 transaction.item.s = 5;
340
341
342
343 std::thread::sleep(Duration::from_nanos(1001));
344 transaction.commit();
345 let borrow2 = VAL.read();
346
347
348 assert_eq!(borrow1.item.s, 1);
349
350 assert_eq!(borrow2.item.s, 5);
351
352 let _ = mpsc_send.send(1);
353 }
354 }
355 );
356
357
358
359 for x in 0..1000
360 {
361 println!("{}", x);
362 mpsc_send2.send(1).unwrap();
363 let _ = mpsc_rcv.recv();
364
365 let borrow1 = VAL.read();
366 assert_eq!(borrow1.item.s, 5);
367
368 let mut transaction = VAL.try_clone_exclusivly().unwrap();
369 transaction.item.s = 1;
370 transaction.commit();
371
372 let borrow1 = VAL.read();
373 assert_eq!(borrow1.item.s, 1);
374
375 }
376
377
378
379 thread1.join().unwrap();
380
381
382 }
383
384
385 #[test]
386 fn test_8()
387 {
388 #[derive(Debug, Clone)]
389 struct Test { s: u32 }
390
391 let icow = Arc::new(ICoW::new(Test{ s: 1 }));
392
393 for _ in 0..20
394 {
395 let read0 = icow.read();
396 let read2 = icow.read();
397
398 let c_icow = icow.clone();
399
400 let handler0 =
402 std::thread::spawn(move ||
403 {
404 let read2 = c_icow.read();
405
406 let mut lock0 = c_icow.try_clone().unwrap();
407
408 lock0.s = 5;
411
412 std::thread::sleep(Duration::from_micros(1));
413 lock0.commit_blocking().unwrap();
414
415 let read3 = c_icow.read();
416
417 assert_eq!(read2.item.s, 1);
418 assert_eq!(read3.item.s, 5);
419 }
420 );
421
422 for i in 0..1000000000
425 {
426 let read1 = icow.read();
427
428 if read1.item.s == 1
429 {
430 continue;
431 }
432 else
433 {
434 println!("{}", i);
435 break;
436 }
437 }
438
439 let read1 = icow.read();
440 assert_eq!(read1.item.s, 5);
441
442 handler0.join().unwrap();
443
444 let mut lock0 = icow.try_clone().unwrap();
445 lock0.s = 1;
446 lock0.commit_blocking().unwrap();
447 }
448
449 return;
450 }
451}