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
104
105
106
107
108
109
110
111
112
use crate::round::State as RoundState;
use futures::task;
use parking_lot::{RwLock, RwLockReadGuard};
use std::sync::Arc;
use std::task::Context;
struct Bridged<H, N> {
inner: RwLock<RoundState<H, N>>,
waker: task::AtomicWaker,
}
impl<H, N> Bridged<H, N> {
fn new(inner: RwLock<RoundState<H, N>>) -> Self {
Bridged {
inner,
waker: task::AtomicWaker::new(),
}
}
}
pub(crate) struct PriorView<H, N>(Arc<Bridged<H, N>>);
impl<H, N> PriorView<H, N> {
pub(crate) fn update(&self, new: RoundState<H, N>) {
*self.0.inner.write() = new;
self.0.waker.wake();
}
}
pub(crate) struct LatterView<H, N>(Arc<Bridged<H, N>>);
impl<H, N> LatterView<H, N> {
pub(crate) fn get(&self, cx: &mut Context) -> RwLockReadGuard<RoundState<H, N>> {
self.0.waker.register(cx.waker());
self.0.inner.read()
}
}
pub(crate) fn bridge_state<H, N>(initial: RoundState<H, N>) -> (PriorView<H, N>, LatterView<H, N>) {
let inner = Arc::new(Bridged::new(RwLock::new(initial)));
(
PriorView(inner.clone()), LatterView(inner)
)
}
#[cfg(test)]
mod tests {
use std::{sync::Barrier, task::Poll};
use super::*;
#[test]
fn bridging_state() {
let initial = RoundState {
prevote_ghost: None,
finalized: None,
estimate: None,
completable: false,
};
let (prior, latter) = bridge_state(initial);
let waits_for_finality = ::futures::future::poll_fn(move |cx| -> Poll<()> {
if latter.get(cx).finalized.is_some() {
Poll::Ready(())
} else {
Poll::Pending
}
});
let barrier = Arc::new(Barrier::new(2));
let barrier_other = barrier.clone();
::std::thread::spawn(move || {
barrier_other.wait();
prior.update(RoundState {
prevote_ghost: Some(("5", 5)),
finalized: Some(("1", 1)),
estimate: Some(("3", 3)),
completable: true,
});
});
barrier.wait();
futures::executor::block_on(waits_for_finality);
}
}