1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use std::cell::Cell;
use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use std::sync::Arc;
use std::sync::atomic;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
use crate::{Epoch, Epochs, Inner, USIZE_MSB};
pub struct ReadHandle<T> {
inner: Arc<AtomicPtr<Inner<T>>>,
epochs: Epochs,
global_epoch: Epoch,
local_epoch: AtomicUsize,
_not_sync: PhantomData<Cell<()>>,
}
impl<T> ReadHandle<T> {
pub(crate) fn new(inner: Arc<AtomicPtr<Inner<T>>>, epochs: Epochs) -> Self {
let global_epoch = Arc::new(AtomicUsize::new(0));
epochs.lock().unwrap().push(Arc::downgrade(&global_epoch));
Self {
inner,
epochs,
global_epoch,
local_epoch: AtomicUsize::new(0),
_not_sync: PhantomData,
}
}
pub fn read(&'_ self) -> ReadHandleGuard<'_, T> {
let epoch = self.local_epoch.fetch_add(1, Ordering::Relaxed) + 1;
self.global_epoch.store(epoch, Ordering::Release);
atomic::fence(Ordering::SeqCst);
let pointer = self.inner.load(Ordering::Acquire);
ReadHandleGuard {
handle: self,
pointer,
epoch,
}
}
pub fn factory(&self) -> ReadHandleFactory<T> {
ReadHandleFactory {
inner: Arc::clone(&self.inner),
epochs: Arc::clone(&self.epochs),
}
}
}
impl<T> Drop for ReadHandle<T> {
fn drop(&mut self) {
if Arc::strong_count(&self.inner) == 1 {
let readers_inner = self.inner.load(Ordering::Relaxed);
mem::drop(unsafe { Box::from_raw(readers_inner) });
}
}
}
impl<T> Clone for ReadHandle<T> {
fn clone(&self) -> Self{
ReadHandle::new(Arc::clone(&self.inner), Arc::clone(&self.epochs))
}
}
pub struct ReadHandleFactory<T> {
inner: Arc<AtomicPtr<Inner<T>>>,
epochs: Epochs,
}
impl<T> ReadHandleFactory<T> {
pub fn handle(&self) -> ReadHandle<T> {
ReadHandle::new(Arc::clone(&self.inner), Arc::clone(&self.epochs))
}
}
pub struct ReadHandleGuard<'a, T> {
handle: &'a ReadHandle<T>,
epoch: usize,
pointer: *const Inner<T>,
}
impl<T> Deref for ReadHandleGuard<'_, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &(*self.pointer).value }
}
}
impl<T> Drop for ReadHandleGuard<'_, T> {
fn drop(&mut self) {
self.handle.global_epoch.store(self.epoch | USIZE_MSB, Ordering::Release);
}
}