comfy_print_sync/
sync_impl.rs

1use super::utils;
2use super::utils::Message;
3use parking_lot::FairMutex;
4
5static QUEUE: FairMutex<Vec<Message>> = FairMutex::new(Vec::new());
6use std::sync::atomic::{AtomicBool, Ordering};
7
8static IS_PRINTING: AtomicBool = AtomicBool::new(false);
9
10#[allow(unused_must_use)]
11pub fn _comfy_print_sync(msg: Message) {
12	let mut queue_guard = QUEUE.lock();
13	
14	if queue_guard.len() == 0 {
15		drop(queue_guard);
16		write_first_in_line(msg);
17	} else {
18		queue_guard.push(msg);
19		drop(queue_guard);
20		if let Ok(_) = IS_PRINTING.compare_exchange(false, true, Ordering::AcqRel, Ordering::Relaxed) {
21			write_until_empty();
22		}
23	}
24}
25
26fn write_until_empty() {
27	loop {
28		let mut queue_guard = QUEUE.lock();
29		
30		if queue_guard.len() == 0 {
31			drop(queue_guard);
32			break;
33		}
34		
35		let msg = queue_guard.remove(0);
36		drop(queue_guard);
37		let msg_str: &str = msg.str();
38		let output_kind = msg.output_kind();
39
40		let write_result = utils::try_write(&msg_str, output_kind);
41		
42		if let Err(err) = write_result {
43			let mut queue_guard = QUEUE.lock();
44			queue_guard.insert(0, Message::error(format!(
45				"comfy_print::write_until_empty(): Failed to print first message in queue, it was pushed to the front again.\n\
46				Error: {err}\n\
47				Message: {msg_str}\n\
48				Target output: {output_kind:?}")));
49
50			queue_guard.insert(1, msg);
51			drop(queue_guard);
52			break;
53		}
54	}
55	
56	IS_PRINTING.store(false, Ordering::Relaxed); // signal other threads that we are no longer printing.
57}
58
59/// On fail: Inserts error in front of the queue, original message on 2nd spot.
60fn write_first_in_line(msg: Message) {
61	let msg_str: &str = msg.str();
62	
63	if let Err(err) = utils::try_write(&msg_str, msg.output_kind()) {
64		let mut queue_guard = QUEUE.lock();
65		queue_guard.insert(0, Message::error(format!(
66			"comfy_print::blocking_write_first_in_line(): Failed to print first message in queue, it was pushed to the front again.\n\
67			Error: {err}\n\
68			Message: {msg_str}")));
69		
70		queue_guard.insert(1, msg);
71		drop(queue_guard);
72	}
73}
74
75pub fn _println(mut input: String) {
76	input.push('\n');
77	_comfy_print_sync(Message::standard(input));
78}
79
80pub fn _print(input: String) {
81	_comfy_print_sync(Message::standard(input));
82}
83
84pub fn _eprint(input: String) {
85	_comfy_print_sync(Message::error(input));
86}
87
88pub fn _eprintln(mut input: String) {
89	input.push('\n');
90	_comfy_print_sync(Message::error(input));
91}
92
93#[macro_export]
94macro_rules! comfy_print {
95    ($($arg:tt)*) => {{
96        $crate::sync_impl::_print(std::format!($($arg)*));
97    }};
98}
99
100#[macro_export]
101macro_rules! comfy_println {
102    () => {
103        $crate::sync_impl::_println("\n")
104    };
105    ($($arg:tt)*) => {{
106        $crate::sync_impl::_println(std::format!($($arg)*));
107    }};
108}
109
110#[macro_export]
111macro_rules! comfy_eprint {
112	($($arg:tt)*) => {{
113		$crate::sync_impl::_eprint(std::format!($($arg)*));
114	}};
115}
116
117#[macro_export]
118macro_rules! comfy_eprintln {
119	() => {
120		$crate::sync_impl::_eprintln("\n")
121	};
122	($($arg:tt)*) => {{
123		$crate::sync_impl::_eprintln(std::format!($($arg)*));
124	}};
125}