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