finality_grandpa/
bridge_state.rs1use crate::round::State as RoundState;
18use futures::task;
19use parking_lot::{RwLock, RwLockReadGuard};
20use std::{sync::Arc, task::Context};
21
22struct Bridged<H, N> {
24 inner: RwLock<RoundState<H, N>>,
25 waker: task::AtomicWaker,
26}
27
28impl<H, N> Bridged<H, N> {
29 fn new(inner: RwLock<RoundState<H, N>>) -> Self {
30 Bridged { inner, waker: task::AtomicWaker::new() }
31 }
32}
33
34pub(crate) struct PriorView<H, N>(Arc<Bridged<H, N>>);
36
37impl<H, N> PriorView<H, N> {
38 pub(crate) fn update(&self, new: RoundState<H, N>) {
40 *self.0.inner.write() = new;
41 self.0.waker.wake();
42 }
43}
44
45pub(crate) struct LatterView<H, N>(Arc<Bridged<H, N>>);
47
48impl<H, N> LatterView<H, N> {
49 pub(crate) fn get(&self, cx: &mut Context) -> RwLockReadGuard<RoundState<H, N>> {
51 self.0.waker.register(cx.waker());
52 self.0.inner.read()
53 }
54}
55
56pub(crate) fn bridge_state<H, N>(initial: RoundState<H, N>) -> (PriorView<H, N>, LatterView<H, N>) {
64 let inner = Arc::new(Bridged::new(RwLock::new(initial)));
65 (PriorView(inner.clone()), LatterView(inner))
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71 use std::{sync::Barrier, task::Poll};
72
73 #[test]
74 fn bridging_state() {
75 let initial =
76 RoundState { prevote_ghost: None, finalized: None, estimate: None, completable: false };
77
78 let (prior, latter) = bridge_state(initial);
79 let waits_for_finality = ::futures::future::poll_fn(move |cx| -> Poll<()> {
80 if latter.get(cx).finalized.is_some() {
81 Poll::Ready(())
82 } else {
83 Poll::Pending
84 }
85 });
86
87 let barrier = Arc::new(Barrier::new(2));
88 let barrier_other = barrier.clone();
89 ::std::thread::spawn(move || {
90 barrier_other.wait();
91 prior.update(RoundState {
92 prevote_ghost: Some(("5", 5)),
93 finalized: Some(("1", 1)),
94 estimate: Some(("3", 3)),
95 completable: true,
96 });
97 });
98
99 barrier.wait();
100 futures::executor::block_on(waits_for_finality);
101 }
102}