From 792db000bb42ae1004063bf9780541be7e741b23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Marcos=20P=2E=20Bezerra?= Date: Fri, 15 Mar 2024 17:09:53 -0300 Subject: [PATCH] move `spawn_logger_thread` to logger module and create another module inside of the logger module to reorganize things --- src/commands/mod.rs | 38 +--------- src/utils/logger.rs | 177 +++++++++++++++++++++++++++----------------- 2 files changed, 112 insertions(+), 103 deletions(-) diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 05e38e1..d303f57 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -22,7 +22,7 @@ use crate::{ list::ListOptions, utils::{ self, - logger::{info_accessible, map_message, setup_channel, warning, LogReceiver}, + logger::{info_accessible, setup_channel, spawn_logger_thread, warning}, to_utf, EscapedPathDisplay, FileVisibilityPolicy, }, CliArgs, QuestionPolicy, @@ -252,39 +252,3 @@ fn run_cmd( } } } - -fn spawn_logger_thread(log_receiver: LogReceiver, synchronization_pair: Arc<(Mutex, Condvar)>) { - rayon::spawn(move || { - const BUFFER_CAPACITY: usize = 10; - let mut buffer = Vec::::with_capacity(BUFFER_CAPACITY); - - loop { - let msg = log_receiver.recv().expect("Failed to receive log message"); - - let is_shutdown_message = msg.is_none(); - - // Append message to buffer - if let Some(msg) = msg.as_ref().and_then(map_message) { - buffer.push(msg); - } - - let should_flush = buffer.len() == BUFFER_CAPACITY || is_shutdown_message; - - if should_flush { - let text = buffer.join("\n"); - eprintln!("{text}"); - buffer.clear(); - } - - if is_shutdown_message { - break; - } - } - - // Wake up the main thread - let (lock, cvar) = &*synchronization_pair; - let mut flushed = lock.lock().unwrap(); - *flushed = true; - cvar.notify_one(); - }); -} diff --git a/src/utils/logger.rs b/src/utils/logger.rs index 8f0ff8d..22ac039 100644 --- a/src/utils/logger.rs +++ b/src/utils/logger.rs @@ -1,58 +1,10 @@ -use std::sync::{mpsc, OnceLock}; +use std::sync::{mpsc, Arc, Condvar, Mutex, OnceLock}; + +pub use logger_thread::{setup_channel, spawn_logger_thread}; use super::colors::{ORANGE, RESET, YELLOW}; use crate::accessible::is_running_in_accessible_mode; -pub type LogReceiver = mpsc::Receiver>; -type LogSender = mpsc::Sender>; - -static SENDER: OnceLock = OnceLock::new(); - -pub fn setup_channel() -> (LogReceiver, LoggerDropper) { - let (tx, rx) = mpsc::channel(); - SENDER.set(tx).expect("`setup_channel` should only be called once"); - (rx, LoggerDropper) -} - -#[track_caller] -fn get_sender() -> &'static LogSender { - SENDER.get().expect("No sender, you need to call `setup_channel` first") -} - -/// Message object used for sending logs from worker threads to a logging thread via channels. -/// See -#[derive(Debug)] -pub struct PrintMessage { - contents: String, - accessible: bool, - level: MessageLevel, -} - -pub fn map_message(msg: &PrintMessage) -> Option { - match msg.level { - MessageLevel::Info => { - if msg.accessible { - if is_running_in_accessible_mode() { - Some(format!("{}Info:{} {}", *YELLOW, *RESET, msg.contents)) - } else { - Some(format!("{}[INFO]{} {}", *YELLOW, *RESET, msg.contents)) - } - } else if !is_running_in_accessible_mode() { - Some(format!("{}[INFO]{} {}", *YELLOW, *RESET, msg.contents)) - } else { - None - } - } - MessageLevel::Warning => { - if is_running_in_accessible_mode() { - Some(format!("{}Warning:{} ", *ORANGE, *RESET)) - } else { - Some(format!("{}[WARNING]{} ", *ORANGE, *RESET)) - } - } - } -} - /// An `[INFO]` log to be displayed if we're not running accessibility mode. /// /// Same as `.info_accessible()`, but only displayed if accessibility mode @@ -78,7 +30,7 @@ pub fn info_accessible(contents: String) { #[track_caller] fn info_with_accessibility(contents: String, accessible: bool) { - send_log_message(PrintMessage { + logger_thread::send_log_message(PrintMessage { contents, accessible, level: MessageLevel::Info, @@ -86,7 +38,7 @@ fn info_with_accessibility(contents: String, accessible: bool) { } pub fn warning(contents: String) { - send_log_message(PrintMessage { + logger_thread::send_log_message(PrintMessage { contents, // Warnings are important and unlikely to flood, so they should be displayed accessible: true, @@ -94,26 +46,119 @@ pub fn warning(contents: String) { }); } +/// Message object used for sending logs from worker threads to a logging thread via channels. +/// See +#[derive(Debug)] +pub struct PrintMessage { + contents: String, + accessible: bool, + level: MessageLevel, +} + +impl PrintMessage { + fn to_processed_message(&self) -> Option { + match self.level { + MessageLevel::Info => { + if self.accessible { + if is_running_in_accessible_mode() { + Some(format!("{}Info:{} {}", *YELLOW, *RESET, self.contents)) + } else { + Some(format!("{}[INFO]{} {}", *YELLOW, *RESET, self.contents)) + } + } else if !is_running_in_accessible_mode() { + Some(format!("{}[INFO]{} {}", *YELLOW, *RESET, self.contents)) + } else { + None + } + } + MessageLevel::Warning => { + if is_running_in_accessible_mode() { + Some(format!("{}Warning:{} ", *ORANGE, *RESET)) + } else { + Some(format!("{}[WARNING]{} ", *ORANGE, *RESET)) + } + } + } + } +} + #[derive(Debug, PartialEq)] -pub enum MessageLevel { +enum MessageLevel { Info, Warning, } -#[track_caller] -fn send_log_message(msg: PrintMessage) { - send_message(Some(msg)); -} +mod logger_thread { + use super::*; -#[track_caller] -fn send_message(msg: Option) { - get_sender().send(msg).expect("Failed to send internal message"); -} + type LogReceiver = mpsc::Receiver>; + type LogSender = mpsc::Sender>; -pub struct LoggerDropper; + static SENDER: OnceLock = OnceLock::new(); -impl Drop for LoggerDropper { - fn drop(&mut self) { - send_message(None); + #[track_caller] + pub fn setup_channel() -> (LogReceiver, LoggerDropper) { + let (tx, rx) = mpsc::channel(); + SENDER.set(tx).expect("`setup_channel` should only be called once"); + (rx, LoggerDropper) + } + + #[track_caller] + fn get_sender() -> &'static LogSender { + SENDER.get().expect("No sender, you need to call `setup_channel` first") + } + + pub fn spawn_logger_thread(log_receiver: LogReceiver, synchronization_pair: Arc<(Mutex, Condvar)>) { + rayon::spawn(move || { + const BUFFER_CAPACITY: usize = 10; + let mut buffer = Vec::::with_capacity(BUFFER_CAPACITY); + + loop { + let msg = log_receiver.recv().expect("Failed to receive log message"); + + let is_shutdown_message = msg.is_none(); + + // Append message to buffer + if let Some(msg) = msg.as_ref().and_then(PrintMessage::to_processed_message) { + buffer.push(msg); + } + + let should_flush = buffer.len() == BUFFER_CAPACITY || is_shutdown_message; + + if should_flush { + let text = buffer.join("\n"); + eprintln!("{text}"); + buffer.clear(); + } + + if is_shutdown_message { + break; + } + } + + // Wake up the main thread + let (lock, cvar) = &*synchronization_pair; + let mut flushed = lock.lock().unwrap(); + *flushed = true; + cvar.notify_one(); + }); + } + + #[track_caller] + pub fn send_log_message(msg: PrintMessage) { + send_message(Some(msg)); + } + + #[track_caller] + fn send_message(msg: Option) { + get_sender().send(msg).expect("Failed to send internal message"); + } + + pub struct LoggerDropper; + + impl Drop for LoggerDropper { + fn drop(&mut self) { + send_message(None); + } } }