1#![allow(non_snake_case)]
2#![allow(unused_parens)]
3
4mod thread;
5mod r#loop;
6
7#[cfg(feature = "thread-priority")]
8extern crate thread_priority;
9
10use std::sync::Arc;
11use std::thread::{sleep, JoinHandle};
12use std::time::{Duration, Instant};
13use parking_lot::Mutex;
14#[cfg(feature = "thread-priority")]
15use thread_priority::{ThreadPriority, ThreadPriorityValue};
16use crate::r#loop::Loop;
17use crate::thread::Thread;
18
19pub struct SingletonThread
20{
21 _thread: Option<JoinHandle<()>>,
22 _threadName: Option<String>,
23 #[cfg(feature = "thread-priority")]
24 _threadPriority: ThreadPriority,
25 _threadFunc: Arc<Mutex<Box<dyn FnMut() + Send + Sync + 'static>>>,
26 _filterPrefunc: Box<dyn FnMut() -> bool + Send + Sync + 'static>,
27 _durationmin: Arc<Mutex<Duration>>,
28 _loop: Arc<Mutex<Loop>>,
29}
30
31impl SingletonThread
32{
33 pub fn new(mainFn: impl Fn() + Send + Sync + 'static) -> Self
35 {
36 return Self::newFiltered(mainFn,||{true});
37 }
38
39 pub fn newFiltered(mainFn: impl Fn() + Send + Sync + 'static, filterFn: impl Fn() -> bool + Send + Sync + 'static) -> Self
43 {
44 return SingletonThread {
45 _thread: None,
46 _threadName: None,
47 #[cfg(feature = "thread-priority")]
48 _threadPriority: ThreadPriority::Crossplatform(ThreadPriorityValue::default()),
49 _threadFunc: Arc::new(Mutex::new(Box::new(mainFn))),
50 _filterPrefunc: Box::new(filterFn),
51 _durationmin: Arc::new(Mutex::new(Duration::from_nanos(1))),
52 _loop: Arc::new(Mutex::new(Loop::NO)),
53 };
54 }
55
56 pub fn thread_launch(&mut self) -> bool
59 {
60 return self.internal_thread_launch(false);
61 }
62
63 pub fn thread_launch_delayabe(&mut self)
66 {
67 self.internal_thread_launch(true);
68 }
69
70 pub fn duration_set(&mut self, duration: Duration)
72 {
73 *self._durationmin.lock() = duration;
74 }
75
76 pub fn duration_setFPS(&mut self, fps: u8)
78 {
79 let durationmillis = 1000/fps.max(1) as u64;
80 *self._durationmin.lock() = Duration::from_millis(durationmillis);
81 }
82
83 pub fn loop_set(&mut self, canLoop: bool)
86 {
87 *self._loop.lock() = canLoop.into();
88 }
89
90 pub fn thread_setName(&mut self, name: impl Into<String>)
93 {
94 self._threadName = Some(name.into());
95 }
96
97 pub fn thread_getName(&mut self) -> &Option<String>
99 {
100 return &self._threadName;
101 }
102
103 #[cfg(feature = "thread-priority")]
105 pub fn thread_setPriority(&mut self, priority: ThreadPriority)
106 {
107 self._threadPriority = priority;
108 }
109
110 pub fn wait(&mut self) -> std::thread::Result<()> {
113 self.loop_set(false);
114
115 if let Some(threadinfo) = self._thread.take() {
116 return threadinfo.join().map(|_| ());
117 }
118
119 return Ok(());
120 }
121
122 fn internal_thread_launch(&mut self,delayabe: bool) -> bool
126 {
127 let mut canLaunch = match &self._thread {
128 None => true,
129 Some(threadinfo) => {
130 threadinfo.is_finished()
131 }
132 };
133
134 if (canLaunch)
135 {
136 let tmp = &mut self._filterPrefunc;
137 canLaunch = tmp();
138 }
139
140 if (!canLaunch)
141 {
142 if(delayabe)
143 {
144 let mut tmp = self._loop.lock();
145 match *tmp
146 {
147 Loop::NO => {*tmp = Loop::ONE}
148 _ => {}
149 }
150 }
151 return false;
152 }
153
154 let arced = self._threadFunc.clone();
155 let arcloop = self._loop.clone();
156 let durationtowait = self._durationmin.clone();
157 let spawnfunc = move ||
158 {
159 Self::InternalThreadFunc(arced, arcloop, durationtowait);
160 };
161
162 let mut innerthread = Thread::default();
163 innerthread.name_set(self._threadName.clone());
164 #[cfg(feature = "thread-priority")]
165 {
166 innerthread.priority_set(self._threadPriority);
167 }
168 if let Ok(spawned) = innerthread.build(spawnfunc)
169 {
170 self._thread = Some(spawned);
171 return true;
172 }
173
174 return false;
175 }
176
177 fn InternalThreadFunc(arced: Arc<Mutex<Box<dyn FnMut() + Send + Sync>>>, arcloop: Arc<Mutex<Loop>>, durationtowait: Arc<Mutex<Duration>>)
178 {
179 loop
180 {
181 let instant = Instant::now();
182 {
183 let tmp = &mut arced.lock();
184 tmp();
185 }
186
187 let timeelapsed = instant.elapsed();
188 let durationtowait = durationtowait.lock().clone();
189 if(timeelapsed<durationtowait)
190 {
191 sleep(durationtowait - timeelapsed);
192 }
193
194 let mut tmp = arcloop.lock();
195 match *tmp
196 {
197 Loop::NO => {return;}
198 Loop::ONE => {
199 *tmp=Loop::NO;
200 }
201 Loop::YES => {}
202 }
203 }
204 }
205}
206
207#[cfg(feature = "drop")]
208impl Drop for SingletonThread
211{
212 fn drop(&mut self) {
213 let _ = self.wait();
214 }
215}