1use std::io::Write;
2use crate::RingBuffer;
3use std::path::Path;
4use crossbeam_channel::*;
5use std::thread;
6
7enum Msg {
8 Clear,
9 Dump,
10 Msg(String),
11}
12
13pub struct RingFile {
17 tx: Sender<Msg>,
18 res: Receiver<std::io::Result<()>>,
19 _th: thread::JoinHandle<()>,
20}
21
22struct RingFileBackend {
23 file_path: Box<Path>,
24 buffer: RingBuffer,
25 rx: Receiver<Msg>,
26 res: Sender<std::io::Result<()>>,
27}
28
29impl RingFileBackend {
30
31 #[inline(always)]
32 fn process(&mut self, msg: Msg) {
33 match msg {
34 Msg::Clear=>{
35 self.buffer.clear();
36 }
37 Msg::Dump=>{
38 let res = self.buffer.dump(self.file_path.as_ref());
39 self.res.send(res).expect("send res");
40 }
41 Msg::Msg(line)=>{
42 let _ = self.buffer.write_all(line.as_bytes());
43 }
44 }
45 }
46
47 fn run(&mut self) {
48 loop {
49 match self.rx.recv() {
50 Ok(msg)=>{
51 self.process(msg);
52 while let Ok(msg) = self.rx.try_recv() {
53 self.process(msg);
54 }
55 }
56 Err(_)=>{
57 return;
58 }
59 }
60 }
61 }
62}
63
64impl RingFile {
65 pub fn new(buf_size: i32, file_path: Box<Path>) -> Self {
71 let (tx, rx) = crossbeam_channel::unbounded();
72 let (res_tx, res_rx) = crossbeam_channel::bounded(1);
73 let mut backend = RingFileBackend {
74 file_path,
75 buffer: RingBuffer::new(buf_size),
76 rx,
77 res: res_tx,
78 };
79 let _th = thread::spawn(move || backend.run());
80 Self{
81 tx,
82 _th,
83 res: res_rx,
84 }
85 }
86
87 pub fn dump(&self) -> std::io::Result<()> {
89 self.tx.send(Msg::Dump).expect("send");
90 self.res.recv().unwrap()
91 }
92
93 #[inline(always)]
94 pub fn write(&self, content: String) {
95 self.tx.send(Msg::Msg(content)).expect("send");
96 }
97
98 pub fn clear(&self) {
100 self.tx.send(Msg::Clear).expect("send");
101 }
102}