Last active
October 16, 2020 17:35
-
-
Save masonforest/4174e75f45781e4448a9eb95caf421cb to your computer and use it in GitHub Desktop.
Mining Future
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[macro_use] | |
extern crate lazy_static; | |
use async_std::task; | |
use rand::{ | |
distributions::{Distribution, Standard}, | |
Rng, | |
}; | |
use std::{ | |
future::Future, | |
pin::Pin, | |
sync::{Arc, Mutex}, | |
task::{Context, Poll, Waker}, | |
time::Duration, | |
}; | |
#[derive(Clone)] | |
pub struct MiningFuture { | |
state: Arc<Mutex<(Poll<State>, Option<Waker>)>>, | |
} | |
#[derive(Clone, Debug)] | |
pub enum State { | |
Mining, | |
OtherMinerIsMining(String), | |
} | |
impl Distribution<State> for Standard { | |
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> State { | |
match rng.gen_range(0, 2) { | |
0 => State::Mining, | |
_ => State::OtherMinerIsMining("miner2".to_string()), | |
} | |
} | |
} | |
impl MiningFuture { | |
pub fn new() -> Self { | |
let state: Arc<Mutex<(Poll<State>, Option<Waker>)>> = | |
Arc::new(Mutex::new((Poll::Pending, None))); | |
MiningFuture { state } | |
} | |
async fn choose_next_miner(self) { | |
let mut state = self.state.lock().unwrap(); | |
state.0 = if rand::random() { | |
Poll::Ready(rand::random()) | |
} else { | |
Poll::Pending | |
}; | |
println!("chose {:?}", state.0); | |
if let Some(waker) = state.1.take() { | |
waker.wake() | |
} | |
} | |
} | |
impl Future for MiningFuture { | |
type Output = (); | |
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | |
let mut state = self.state.lock().unwrap(); | |
if matches!(state.0, Poll::Ready(State::Mining)) { | |
Poll::Ready(()) | |
} else { | |
state.1 = Some(cx.waker().clone()); | |
Poll::Pending | |
} | |
} | |
} | |
lazy_static! { | |
pub static ref MINING_FUTURE: MiningFuture = MiningFuture::new(); | |
} | |
#[async_std::main] | |
async fn main() { | |
task::spawn(async { | |
loop { | |
task::sleep(Duration::from_secs(1)).await; | |
MINING_FUTURE.clone().choose_next_miner().await; | |
} | |
}); | |
task::block_on(async { | |
loop { | |
MINING_FUTURE.clone().await; | |
println!("processing transactions"); | |
task::sleep(Duration::from_millis(100)).await; | |
} | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment