From 4e1e14d4183d94dfb46c4401a856f417a688eb13 Mon Sep 17 00:00:00 2001 From: b1ek Date: Wed, 2 Aug 2023 21:47:55 +1000 Subject: [PATCH] init: solve_blocking, chunksize to POWSolver --- src/solver.rs | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/src/solver.rs b/src/solver.rs index 784886f..d5a5504 100644 --- a/src/solver.rs +++ b/src/solver.rs @@ -1,5 +1,8 @@ -use crate::gen::POWChallenge; +use std::{sync::{mpsc::{self, Receiver, SyncSender}, Arc, atomic::{AtomicBool, Ordering}}, thread::{self, JoinHandle}}; +use crate::{gen::POWChallenge, num::Num}; + +#[derive(Debug, Clone)] pub struct POWSolver { challenge: POWChallenge, result: Option @@ -60,6 +63,68 @@ impl POWSolver { return self.chunk_solve(self.challenge.range.min, self.challenge.range.max); } + pub fn chunksize(self: &POWSolver, threads: u8) -> u128 { + let range = self.challenge.range.max - self.challenge.range.min; + range / threads as u128 + } + + pub fn solve_blocking(self: &mut POWSolver, threads: u8, callback: Option) -> u128 { + let (send, recv) = mpsc::sync_channel::(1); + let mut thread_start: u128 = self.challenge.range.min; + + let size = self.chunksize(threads); + let mut handles: Vec> = vec![]; + let stop = Arc::new(AtomicBool::new(false)); + let range = self.challenge.range.max - self.challenge.range.min; + + for i in 0..threads { + let solver = self.clone(); + let send = send.clone(); + let stop = stop.clone(); + + let mut end = thread_start + size; + if end > range { + end -= end % range; + } + + handles.push( + thread::spawn(move || { + for j in thread_start..end { + if stop.load(Ordering::Relaxed) { break } + if callback.is_some() { + callback.unwrap()(j); + } + + if solver.challenge.check(Num::from(j as u128)) { + stop.store(true, Ordering::Relaxed); + send.send(j as u128).unwrap(); + } + } + } + ) + ); + + thread_start = thread_start + size + 1; + } + + let result = recv.recv().unwrap(); + stop.load(Ordering::Relaxed); + + loop { + let mut all_finished = true; + for handle in handles.iter() { + if !handle.is_finished() { + all_finished = false + } + } + if all_finished { break } + } + + self.result = Some(result); + + result + } + pub fn new(challenge: POWChallenge) -> POWSolver { POWSolver { challenge, result: None } }