#![allow(unused)]
use crate::ConnectionManager;
use rand::seq::SliceRandom;
use rand::Rng;
use safe_nd::{Request, Response};
use std::rc::Rc;
use std::sync::{Arc, Condvar, Mutex};
use unwrap::unwrap;
#[derive(Clone)]
pub struct Synchronizer<T: Rng> {
inner: Arc<Inner<T>>,
}
impl<T: Clone + Rng> Synchronizer<T> {
pub fn new(rng: &mut T) -> Self {
Self {
inner: Arc::new(Inner {
state: Mutex::new(State::new(rng)),
condvar: Condvar::new(),
}),
}
}
pub fn hook(&self, mut cm: ConnectionManager) -> ConnectionManager {
cm
}
}
struct Hook<T: Clone + Rng> {
id: usize,
inner: Arc<Inner<T>>,
}
impl<T: Clone + Rng> Hook<T> {
fn new(inner: Arc<Inner<T>>) -> Self {
let id = inner.register_id();
Self { id, inner }
}
fn request(&self, _req: &Request) -> Option<Response> {
self.inner.wait(self.id);
None
}
fn response(&self, res: Response) -> Response {
self.inner.sleep();
res
}
}
impl<T: Clone + Rng> Drop for Hook<T> {
fn drop(&mut self) {
self.inner.unregister_id(self.id);
}
}
struct Inner<T> {
state: Mutex<State<T>>,
condvar: Condvar,
}
impl<T: Clone + Rng> Inner<T> {
fn register_id(&self) -> usize {
let mut state = unwrap!(self.state.lock());
state.register_id()
}
fn unregister_id(&self, id: usize) {
let mut state = unwrap!(self.state.lock());
state.unregister_id(id);
self.condvar.notify_all();
}
fn wait(&self, id: usize) {
let mut state = unwrap!(self.state.lock());
while state.awake != id {
state = unwrap!(self.condvar.wait(state));
}
}
fn sleep(&self) {
let mut state = unwrap!(self.state.lock());
state.wake_next();
self.condvar.notify_all();
}
}
struct State<T> {
rng: T,
all: Vec<usize>,
next: usize,
awake: usize,
}
impl<T: Clone + Rng> State<T> {
fn new(rng: &mut T) -> Self {
Self {
rng: rng.clone(),
all: Vec::new(),
next: 0,
awake: 0,
}
}
fn register_id(&mut self) -> usize {
let id = self.next;
self.next += 1;
self.all.push(id);
self.awake = id;
id
}
fn unregister_id(&mut self, id: usize) {
if let Some(index) = self.all.iter().position(|other| *other == id) {
let _ = self.all.remove(index);
}
if self.awake == id {
self.wake_next();
}
}
fn wake_next(&mut self) {
if !self.all.is_empty() {
self.awake = *unwrap!(self.all.choose(&mut self.rng));
}
}
}