From 309727e61aab2196cb001cb4fb439448db3c844a Mon Sep 17 00:00:00 2001 From: Paul Tsouchlos Date: Thu, 21 Nov 2024 15:36:22 -0500 Subject: [PATCH] refactor: simplify the input hander Removed the worker thread and instead moved just the necessary functionality into `InputHandler` directly. bench: 2577543 --- src/bin/byte-knight/input_handler.rs | 65 +++++++++------------ src/bin/byte-knight/main.rs | 1 - src/bin/byte-knight/worker_thread.rs | 87 ---------------------------- 3 files changed, 26 insertions(+), 127 deletions(-) delete mode 100644 src/bin/byte-knight/worker_thread.rs diff --git a/src/bin/byte-knight/input_handler.rs b/src/bin/byte-knight/input_handler.rs index 7e470bc..a89ae84 100644 --- a/src/bin/byte-knight/input_handler.rs +++ b/src/bin/byte-knight/input_handler.rs @@ -15,16 +15,21 @@ use std::{ io::{stdin, BufRead}, str::FromStr, - sync::mpsc::{self, Receiver, Sender}, + sync::{ + atomic::{AtomicBool, Ordering}, + mpsc::{self, Receiver}, + Arc, + }, + thread::JoinHandle, }; use uci_parser::UciCommand; -use crate::worker_thread::WorkerThread; - #[derive(Debug)] pub(crate) struct InputHandler { - worker: WorkerThread, + handle: Option>, + stop_flag: Arc, + receiver: Receiver, } impl InputHandler { @@ -49,8 +54,10 @@ impl InputHandler { /// ``` /// pub(crate) fn new() -> InputHandler { + let stop_flag = Arc::new(AtomicBool::new(false)); + let stop_flag_clone = stop_flag.clone(); let (sender, receiver) = mpsc::channel(); - let worker = WorkerThread::new(sender.clone(), receiver, move |stop_flag| { + let worker = std::thread::spawn(move || { let stdin = stdin(); let mut input = stdin.lock().lines(); while !stop_flag.load(std::sync::atomic::Ordering::Relaxed) { @@ -71,48 +78,28 @@ impl InputHandler { } } }); - InputHandler { worker } + InputHandler { + handle: Some(worker), + stop_flag: stop_flag_clone, + receiver, + } } - fn sender(&self) -> Sender { - self.worker.sender() + pub fn stop(&mut self) { + self.stop_flag.store(true, Ordering::Relaxed); + + if let Some(handle) = self.handle.take() { + handle.join().unwrap(); + } } - /// Returns a reference to the receiver end of the channel. - /// - /// # Returns - /// - /// A reference to the receiver end of the channel. - pub(crate) fn receiver(&self) -> &Receiver { - self.worker.receiver() + pub fn receiver(&self) -> &Receiver { + &self.receiver } /// Signal to the worker thread that it should stop. This method does not block the calling /// thread. pub(crate) fn exit(&mut self) { - self.worker.stop(); - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_input_handler() { - let input_handler = InputHandler::new(); - let sender = input_handler.sender(); - - sender.send(UciCommand::Uci).unwrap(); - sender.send(UciCommand::IsReady).unwrap(); - sender.send(UciCommand::UciNewGame).unwrap(); - - let receiver = input_handler.receiver(); - let inputs: Vec = receiver.iter().take(3).collect(); - - assert_eq!( - inputs, - vec![UciCommand::Uci, UciCommand::IsReady, UciCommand::UciNewGame] - ); + self.stop(); } } diff --git a/src/bin/byte-knight/main.rs b/src/bin/byte-knight/main.rs index 5d4e86e..621456a 100644 --- a/src/bin/byte-knight/main.rs +++ b/src/bin/byte-knight/main.rs @@ -22,7 +22,6 @@ mod score; mod search; mod search_thread; mod tt_table; -mod worker_thread; use defs::About; use engine::ByteKnight; diff --git a/src/bin/byte-knight/worker_thread.rs b/src/bin/byte-knight/worker_thread.rs deleted file mode 100644 index 0137604..0000000 --- a/src/bin/byte-knight/worker_thread.rs +++ /dev/null @@ -1,87 +0,0 @@ -/* - * worker_thread.rs - * Part of the byte-knight project - * Created Date: Thursday, November 21st 2024 - * Author: Paul Tsouchlos (DeveloperPaul123) (developer.paul.123@gmail.com) - * ----- - * Last Modified: Thu Nov 21 2024 - * ----- - * Copyright (c) 2024 Paul Tsouchlos (DeveloperPaul123) - * GNU General Public License v3.0 or later - * https://www.gnu.org/licenses/gpl-3.0-standalone.html - * - */ - -use std::{ - sync::{ - atomic::{AtomicBool, Ordering}, - mpsc::{self, Receiver, Sender}, - Arc, - }, - thread::JoinHandle, -}; - -/// WorkerThread is a wrapper around a thread that runs a worker function. The worker function is -/// passed to the constructor and is executed in a loop until the worker thread is stopped. -/// -/// The worker function is passed an `Arc` that can be used to check if the worker -/// thread should stop. -/// -#[derive(Debug)] -pub(crate) struct WorkerThread { - handle: Option>, - sender: Sender, - receiver: Receiver, - stop_flag: Arc, -} - -impl WorkerThread { - /// . - /// - /// # Panics - /// - /// Panics if . - pub fn new(sender: Sender, receiver: Receiver, worker: F) -> WorkerThread - where - F: Fn(Arc) + Send + 'static, - { - let stop_flag = Arc::new(AtomicBool::new(false)); - let stop_flag_clone = stop_flag.clone(); - let handle = Some(std::thread::spawn(move || { - worker(stop_flag_clone.clone()); - })); - - WorkerThread { - handle, - sender, - receiver, - stop_flag, - } - } - - pub fn send(&self, data: T) -> Result<(), mpsc::SendError> { - self.sender.send(data) - } - - pub fn sender(&self) -> Sender { - self.sender.clone() - } - - pub fn receiver(&self) -> &Receiver { - &self.receiver - } - - pub fn stop(&mut self) { - self.stop_flag.store(true, Ordering::Relaxed); - - if let Some(handle) = self.handle.take() { - handle.join().unwrap(); - } - } -} - -impl Drop for WorkerThread { - fn drop(&mut self) { - self.stop(); - } -}