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