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