1#[cfg(feature = "std")]
7use alloc::sync::Arc;
8#[cfg(feature = "std")]
9use core::sync::atomic::AtomicBool;
10#[cfg(feature = "std")]
11use core::sync::atomic::Ordering;
12#[cfg(feature = "std")]
13use std::sync::{
14 mpsc::{channel, Receiver, Sender},
15 Mutex,
16};
17#[cfg(feature = "std")]
18use std::thread::{self, JoinHandle};
19
20use azul_core::{
21 callbacks::Update,
22 refany::{OptionRefAny, RefAny},
23 task::{
24 CheckThreadFinishedCallback, CheckThreadFinishedCallbackType, LibrarySendThreadMsgCallback,
25 LibrarySendThreadMsgCallbackType, OptionThreadSendMsg, ThreadId, ThreadReceiver,
26 ThreadReceiverDestructorCallback, ThreadReceiverInner, ThreadRecvCallback, ThreadSendMsg,
27 },
28};
29
30use crate::callbacks::CallbackInfo;
31
32#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
36#[repr(C, u8)]
37pub enum ThreadReceiveMsg {
38 WriteBack(ThreadWriteBackMsg),
39 Update(Update),
40}
41
42#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
43#[repr(C, u8)]
44pub enum OptionThreadReceiveMsg {
45 None,
46 Some(ThreadReceiveMsg),
47}
48
49impl From<Option<ThreadReceiveMsg>> for OptionThreadReceiveMsg {
50 fn from(inner: Option<ThreadReceiveMsg>) -> Self {
51 match inner {
52 None => OptionThreadReceiveMsg::None,
53 Some(v) => OptionThreadReceiveMsg::Some(v),
54 }
55 }
56}
57
58impl OptionThreadReceiveMsg {
59 pub fn into_option(self) -> Option<ThreadReceiveMsg> {
60 match self {
61 OptionThreadReceiveMsg::None => None,
62 OptionThreadReceiveMsg::Some(v) => Some(v),
63 }
64 }
65
66 pub fn as_ref(&self) -> Option<&ThreadReceiveMsg> {
67 match self {
68 OptionThreadReceiveMsg::None => None,
69 OptionThreadReceiveMsg::Some(v) => Some(v),
70 }
71 }
72}
73
74#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
76#[repr(C)]
77pub struct ThreadWriteBackMsg {
78 pub refany: RefAny,
79 pub callback: WriteBackCallback,
80}
81
82impl ThreadWriteBackMsg {
83 pub fn new<C: Into<WriteBackCallback>>(callback: C, data: RefAny) -> Self {
84 Self {
85 refany: data,
86 callback: callback.into(),
87 }
88 }
89}
90
91#[derive(Debug)]
93#[repr(C)]
94pub struct ThreadSender {
95 #[cfg(feature = "std")]
96 pub ptr: alloc::boxed::Box<Arc<Mutex<ThreadSenderInner>>>,
97 #[cfg(not(feature = "std"))]
98 pub ptr: *const core::ffi::c_void,
99 pub run_destructor: bool,
100 pub ctx: OptionRefAny,
102}
103
104impl Clone for ThreadSender {
105 fn clone(&self) -> Self {
106 Self {
107 ptr: self.ptr.clone(),
108 run_destructor: true,
109 ctx: self.ctx.clone(),
110 }
111 }
112}
113
114impl Drop for ThreadSender {
115 fn drop(&mut self) {
116 self.run_destructor = false;
117 }
118}
119
120impl ThreadSender {
121 #[cfg(not(feature = "std"))]
122 pub fn new(_t: ThreadSenderInner) -> Self {
123 Self {
124 ptr: core::ptr::null(),
125 run_destructor: false,
126 ctx: OptionRefAny::None,
127 }
128 }
129
130 #[cfg(feature = "std")]
131 pub fn new(t: ThreadSenderInner) -> Self {
132 Self {
133 ptr: alloc::boxed::Box::new(Arc::new(Mutex::new(t))),
134 run_destructor: true,
135 ctx: OptionRefAny::None,
136 }
137 }
138
139 pub fn get_ctx(&self) -> OptionRefAny {
141 self.ctx.clone()
142 }
143
144 #[cfg(not(feature = "std"))]
145 pub fn send(&mut self, _msg: ThreadReceiveMsg) -> bool {
146 false
147 }
148
149 #[cfg(feature = "std")]
150 pub fn send(&mut self, msg: ThreadReceiveMsg) -> bool {
151 let ts = match self.ptr.lock().ok() {
152 Some(s) => s,
153 None => return false,
154 };
155 (ts.send_fn.cb)(ts.ptr.as_ref() as *const _ as *const core::ffi::c_void, msg)
156 }
157}
158
159#[derive(Debug)]
160#[cfg_attr(not(feature = "std"), derive(PartialEq, PartialOrd, Eq, Ord))]
161#[repr(C)]
162pub struct ThreadSenderInner {
163 #[cfg(feature = "std")]
164 pub ptr: alloc::boxed::Box<Sender<ThreadReceiveMsg>>,
165 #[cfg(not(feature = "std"))]
166 pub ptr: *const core::ffi::c_void,
167 pub send_fn: ThreadSendCallback,
168 pub destructor: ThreadSenderDestructorCallback,
169}
170
171#[cfg(not(feature = "std"))]
172unsafe impl Send for ThreadSenderInner {}
173
174#[cfg(feature = "std")]
175impl core::hash::Hash for ThreadSenderInner {
176 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
177 (self.ptr.as_ref() as *const _ as usize).hash(state);
178 }
179}
180
181#[cfg(feature = "std")]
182impl PartialEq for ThreadSenderInner {
183 fn eq(&self, other: &Self) -> bool {
184 (self.ptr.as_ref() as *const _ as usize) == (other.ptr.as_ref() as *const _ as usize)
185 }
186}
187
188#[cfg(feature = "std")]
189impl Eq for ThreadSenderInner {}
190
191#[cfg(feature = "std")]
192impl PartialOrd for ThreadSenderInner {
193 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
194 Some(
195 (self.ptr.as_ref() as *const _ as usize)
196 .cmp(&(other.ptr.as_ref() as *const _ as usize)),
197 )
198 }
199}
200
201#[cfg(feature = "std")]
202impl Ord for ThreadSenderInner {
203 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
204 (self.ptr.as_ref() as *const _ as usize).cmp(&(other.ptr.as_ref() as *const _ as usize))
205 }
206}
207
208impl Drop for ThreadSenderInner {
209 fn drop(&mut self) {
210 (self.destructor.cb)(self);
211 }
212}
213
214pub type ThreadSendCallbackType = extern "C" fn(*const core::ffi::c_void, ThreadReceiveMsg) -> bool;
216
217#[repr(C)]
218pub struct ThreadSendCallback {
219 pub cb: ThreadSendCallbackType,
220}
221
222impl core::fmt::Debug for ThreadSendCallback {
223 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
224 write!(f, "ThreadSendCallback {{ cb: {:p} }}", self.cb as *const ())
225 }
226}
227
228impl Clone for ThreadSendCallback {
229 fn clone(&self) -> Self {
230 Self { cb: self.cb }
231 }
232}
233
234impl PartialEq for ThreadSendCallback {
235 fn eq(&self, other: &Self) -> bool {
236 self.cb as usize == other.cb as usize
237 }
238}
239
240impl Eq for ThreadSendCallback {}
241
242impl PartialOrd for ThreadSendCallback {
243 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
244 Some(self.cmp(other))
245 }
246}
247
248impl Ord for ThreadSendCallback {
249 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
250 (self.cb as usize).cmp(&(other.cb as usize))
251 }
252}
253
254pub type ThreadSenderDestructorCallbackType = extern "C" fn(*mut ThreadSenderInner);
256
257#[repr(C)]
258pub struct ThreadSenderDestructorCallback {
259 pub cb: ThreadSenderDestructorCallbackType,
260}
261
262impl core::fmt::Debug for ThreadSenderDestructorCallback {
263 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
264 write!(
265 f,
266 "ThreadSenderDestructorCallback {{ cb: {:p} }}",
267 self.cb as *const ()
268 )
269 }
270}
271
272impl Clone for ThreadSenderDestructorCallback {
273 fn clone(&self) -> Self {
274 Self { cb: self.cb }
275 }
276}
277
278impl PartialEq for ThreadSenderDestructorCallback {
279 fn eq(&self, other: &Self) -> bool {
280 self.cb as usize == other.cb as usize
281 }
282}
283
284impl Eq for ThreadSenderDestructorCallback {}
285
286impl PartialOrd for ThreadSenderDestructorCallback {
287 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
288 Some(self.cmp(other))
289 }
290}
291
292impl Ord for ThreadSenderDestructorCallback {
293 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
294 (self.cb as usize).cmp(&(other.cb as usize))
295 }
296}
297
298pub type WriteBackCallbackType = extern "C" fn(
305 RefAny,
306 RefAny,
307 CallbackInfo,
308) -> Update;
309
310#[repr(C)]
312pub struct WriteBackCallback {
313 pub cb: WriteBackCallbackType,
314 pub ctx: OptionRefAny,
317}
318
319impl WriteBackCallback {
320 pub fn new(cb: WriteBackCallbackType) -> Self {
322 Self {
323 cb,
324 ctx: OptionRefAny::None,
325 }
326 }
327
328 pub fn invoke(
330 &self,
331 thread_data: RefAny,
332 writeback_data: RefAny,
333 callback_info: CallbackInfo,
334 ) -> Update {
335 (self.cb)(thread_data, writeback_data, callback_info)
336 }
337}
338
339impl core::fmt::Debug for WriteBackCallback {
340 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
341 write!(f, "WriteBackCallback {{ cb: {:p} }}", self.cb as *const ())
342 }
343}
344
345impl Clone for WriteBackCallback {
346 fn clone(&self) -> Self {
347 Self {
348 cb: self.cb,
349 ctx: self.ctx.clone(),
350 }
351 }
352}
353
354impl From<WriteBackCallbackType> for WriteBackCallback {
355 fn from(cb: WriteBackCallbackType) -> Self {
356 Self {
357 cb,
358 ctx: OptionRefAny::None,
359 }
360 }
361}
362
363impl PartialEq for WriteBackCallback {
364 fn eq(&self, other: &Self) -> bool {
365 self.cb as usize == other.cb as usize
366 }
367}
368
369impl Eq for WriteBackCallback {}
370
371impl PartialOrd for WriteBackCallback {
372 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
373 (self.cb as usize).partial_cmp(&(other.cb as usize))
374 }
375}
376
377impl Ord for WriteBackCallback {
378 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
379 (self.cb as usize).cmp(&(other.cb as usize))
380 }
381}
382
383impl core::hash::Hash for WriteBackCallback {
384 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
385 (self.cb as usize).hash(state);
386 }
387}
388
389pub type ThreadCallbackType = extern "C" fn(RefAny, ThreadSender, ThreadReceiver);
391
392#[repr(C)]
393pub struct ThreadCallback {
394 pub cb: ThreadCallbackType,
395 pub ctx: OptionRefAny,
398}
399
400impl ThreadCallback {
401 pub fn new(cb: ThreadCallbackType) -> Self {
403 Self {
404 cb,
405 ctx: OptionRefAny::None,
406 }
407 }
408}
409
410impl core::fmt::Debug for ThreadCallback {
411 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
412 write!(f, "ThreadCallback {{ cb: {:p} }}", self.cb as *const ())
413 }
414}
415
416impl Clone for ThreadCallback {
417 fn clone(&self) -> Self {
418 Self {
419 cb: self.cb,
420 ctx: self.ctx.clone(),
421 }
422 }
423}
424
425impl From<ThreadCallbackType> for ThreadCallback {
426 fn from(cb: ThreadCallbackType) -> Self {
427 Self {
428 cb,
429 ctx: OptionRefAny::None,
430 }
431 }
432}
433
434impl PartialEq for ThreadCallback {
435 fn eq(&self, other: &Self) -> bool {
436 self.cb as usize == other.cb as usize
437 }
438}
439
440impl Eq for ThreadCallback {}
441
442impl PartialOrd for ThreadCallback {
443 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
444 (self.cb as usize).partial_cmp(&(other.cb as usize))
445 }
446}
447
448impl Ord for ThreadCallback {
449 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
450 (self.cb as usize).cmp(&(other.cb as usize))
451 }
452}
453
454impl core::hash::Hash for ThreadCallback {
455 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
456 (self.cb as usize).hash(state);
457 }
458}
459
460pub type LibraryReceiveThreadMsgCallbackType =
461 extern "C" fn(*const core::ffi::c_void) -> OptionThreadReceiveMsg;
462
463#[repr(C)]
464pub struct LibraryReceiveThreadMsgCallback {
465 pub cb: LibraryReceiveThreadMsgCallbackType,
466}
467
468impl core::fmt::Debug for LibraryReceiveThreadMsgCallback {
469 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
470 write!(
471 f,
472 "LibraryReceiveThreadMsgCallback {{ cb: {:p} }}",
473 self.cb as *const ()
474 )
475 }
476}
477
478impl Clone for LibraryReceiveThreadMsgCallback {
479 fn clone(&self) -> Self {
480 Self { cb: self.cb }
481 }
482}
483
484pub type ThreadDestructorCallbackType = extern "C" fn(*mut ThreadInner);
485
486#[repr(C)]
487pub struct ThreadDestructorCallback {
488 pub cb: ThreadDestructorCallbackType,
489}
490
491impl core::fmt::Debug for ThreadDestructorCallback {
492 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
493 write!(
494 f,
495 "ThreadDestructorCallback {{ cb: {:p} }}",
496 self.cb as *const ()
497 )
498 }
499}
500
501impl Clone for ThreadDestructorCallback {
502 fn clone(&self) -> Self {
503 Self { cb: self.cb }
504 }
505}
506
507#[derive(Debug)]
509#[repr(C)]
510pub struct Thread {
511 #[cfg(feature = "std")]
512 pub ptr: alloc::boxed::Box<Arc<Mutex<ThreadInner>>>,
513 #[cfg(not(feature = "std"))]
514 pub ptr: *const core::ffi::c_void,
515 pub run_destructor: bool,
516}
517
518impl Clone for Thread {
519 fn clone(&self) -> Self {
520 Self {
521 ptr: self.ptr.clone(),
522 run_destructor: true,
523 }
524 }
525}
526
527impl Drop for Thread {
528 fn drop(&mut self) {
529 self.run_destructor = false;
530 }
531}
532
533impl Thread {
534 #[cfg(feature = "std")]
535 pub fn new(ti: ThreadInner) -> Self {
536 Self {
537 ptr: alloc::boxed::Box::new(Arc::new(Mutex::new(ti))),
538 run_destructor: true,
539 }
540 }
541
542 #[cfg(not(feature = "std"))]
543 pub fn new(_ti: ThreadInner) -> Self {
544 Self {
545 ptr: core::ptr::null(),
546 run_destructor: false,
547 }
548 }
549
550 pub fn create<C: Into<ThreadCallback>>(
560 thread_initialize_data: RefAny,
561 writeback_data: RefAny,
562 callback: C,
563 ) -> Self {
564 create_thread_libstd(thread_initialize_data, writeback_data, callback.into())
565 }
566}
567
568#[derive(Debug)]
574#[repr(C)]
575pub struct ThreadInner {
576 #[cfg(feature = "std")]
577 pub thread_handle: alloc::boxed::Box<Option<JoinHandle<()>>>,
578 #[cfg(not(feature = "std"))]
579 pub thread_handle: *const core::ffi::c_void,
580
581 #[cfg(feature = "std")]
582 pub sender: alloc::boxed::Box<Sender<ThreadSendMsg>>,
583 #[cfg(not(feature = "std"))]
584 pub sender: *const core::ffi::c_void,
585
586 #[cfg(feature = "std")]
587 pub receiver: alloc::boxed::Box<Receiver<ThreadReceiveMsg>>,
588 #[cfg(not(feature = "std"))]
589 pub receiver: *const core::ffi::c_void,
590
591 #[cfg(feature = "std")]
592 pub dropcheck: alloc::boxed::Box<alloc::sync::Weak<()>>,
593 #[cfg(not(feature = "std"))]
594 pub dropcheck: *const core::ffi::c_void,
595
596 pub writeback_data: RefAny,
597 pub check_thread_finished_fn: CheckThreadFinishedCallback,
598 pub send_thread_msg_fn: LibrarySendThreadMsgCallback,
599 pub receive_thread_msg_fn: LibraryReceiveThreadMsgCallback,
600 pub thread_destructor_fn: ThreadDestructorCallback,
601}
602
603#[cfg(feature = "std")]
604impl ThreadInner {
605 pub fn is_finished(&self) -> bool {
607 (self.check_thread_finished_fn.cb)(
608 self.dropcheck.as_ref() as *const _ as *const core::ffi::c_void
609 )
610 }
611
612 pub fn sender_send(&mut self, msg: ThreadSendMsg) -> bool {
614 (self.send_thread_msg_fn.cb)(
615 self.sender.as_ref() as *const _ as *const core::ffi::c_void,
616 msg,
617 )
618 }
619
620 pub fn receiver_try_recv(&mut self) -> OptionThreadReceiveMsg {
622 (self.receive_thread_msg_fn.cb)(
623 self.receiver.as_ref() as *const _ as *const core::ffi::c_void
624 )
625 }
626}
627
628#[cfg(not(feature = "std"))]
629impl ThreadInner {
630 pub fn is_finished(&self) -> bool {
632 true
633 }
634
635 pub fn sender_send(&mut self, _msg: ThreadSendMsg) -> bool {
637 false
638 }
639
640 pub fn receiver_try_recv(&mut self) -> OptionThreadReceiveMsg {
642 None.into()
643 }
644}
645
646impl Drop for ThreadInner {
647 fn drop(&mut self) {
648 (self.thread_destructor_fn.cb)(self);
649 }
650}
651
652#[cfg(feature = "std")]
654extern "C" fn default_thread_destructor_fn(thread: *mut ThreadInner) {
655 let thread = unsafe { &mut *thread };
656
657 if let Some(thread_handle) = thread.thread_handle.take() {
658 let _ = thread.sender.send(ThreadSendMsg::TerminateThread);
659 let _ = thread_handle.join(); }
661}
662
663#[cfg(not(feature = "std"))]
664extern "C" fn default_thread_destructor_fn(_thread: *mut ThreadInner) {}
665
666#[cfg(feature = "std")]
667extern "C" fn library_send_thread_msg_fn(
668 sender: *const core::ffi::c_void,
669 msg: ThreadSendMsg,
670) -> bool {
671 unsafe { &*(sender as *const Sender<ThreadSendMsg>) }
672 .send(msg)
673 .is_ok()
674}
675
676#[cfg(not(feature = "std"))]
677extern "C" fn library_send_thread_msg_fn(
678 _sender: *const core::ffi::c_void,
679 _msg: ThreadSendMsg,
680) -> bool {
681 false
682}
683
684#[cfg(feature = "std")]
685extern "C" fn library_receive_thread_msg_fn(
686 receiver: *const core::ffi::c_void,
687) -> OptionThreadReceiveMsg {
688 unsafe { &*(receiver as *const Receiver<ThreadReceiveMsg>) }
689 .try_recv()
690 .ok()
691 .into()
692}
693
694#[cfg(not(feature = "std"))]
695extern "C" fn library_receive_thread_msg_fn(
696 _receiver: *const core::ffi::c_void,
697) -> OptionThreadReceiveMsg {
698 None.into()
699}
700
701#[cfg(feature = "std")]
702extern "C" fn default_send_thread_msg_fn(
703 sender: *const core::ffi::c_void,
704 msg: ThreadReceiveMsg,
705) -> bool {
706 unsafe { &*(sender as *const Sender<ThreadReceiveMsg>) }
707 .send(msg)
708 .is_ok()
709}
710
711#[cfg(not(feature = "std"))]
712extern "C" fn default_send_thread_msg_fn(
713 _sender: *const core::ffi::c_void,
714 _msg: ThreadReceiveMsg,
715) -> bool {
716 false
717}
718
719#[cfg(feature = "std")]
720extern "C" fn default_receive_thread_msg_fn(
721 receiver: *const core::ffi::c_void,
722) -> OptionThreadSendMsg {
723 unsafe { &*(receiver as *const Receiver<ThreadSendMsg>) }
724 .try_recv()
725 .ok()
726 .into()
727}
728
729#[cfg(not(feature = "std"))]
730extern "C" fn default_receive_thread_msg_fn(
731 _receiver: *const core::ffi::c_void,
732) -> OptionThreadSendMsg {
733 None.into()
734}
735
736#[cfg(feature = "std")]
737extern "C" fn default_check_thread_finished(dropcheck: *const core::ffi::c_void) -> bool {
738 let weak = unsafe { &*(dropcheck as *const alloc::sync::Weak<()>) };
739 weak.upgrade().is_none()
740}
741
742#[cfg(not(feature = "std"))]
743extern "C" fn default_check_thread_finished(_dropcheck: *const core::ffi::c_void) -> bool {
744 true
745}
746
747#[cfg(feature = "std")]
748extern "C" fn thread_sender_drop(_: *mut ThreadSenderInner) {}
749
750#[cfg(not(feature = "std"))]
751extern "C" fn thread_sender_drop(_: *mut ThreadSenderInner) {}
752
753#[cfg(feature = "std")]
754extern "C" fn thread_receiver_drop(_: *mut ThreadReceiverInner) {}
755
756#[cfg(not(feature = "std"))]
757extern "C" fn thread_receiver_drop(_: *mut ThreadReceiverInner) {}
758
759pub type CreateThreadCallbackType = extern "C" fn(RefAny, RefAny, ThreadCallback) -> Thread;
761
762#[repr(C)]
763pub struct CreateThreadCallback {
764 pub cb: CreateThreadCallbackType,
765}
766
767impl core::fmt::Debug for CreateThreadCallback {
768 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
769 write!(
770 f,
771 "CreateThreadCallback {{ cb: {:p} }}",
772 self.cb as *const ()
773 )
774 }
775}
776
777impl Clone for CreateThreadCallback {
778 fn clone(&self) -> Self {
779 Self { cb: self.cb }
780 }
781}
782
783impl Copy for CreateThreadCallback {}
784
785impl PartialEq for CreateThreadCallback {
786 fn eq(&self, other: &Self) -> bool {
787 self.cb as usize == other.cb as usize
788 }
789}
790
791impl Eq for CreateThreadCallback {}
792
793impl PartialOrd for CreateThreadCallback {
794 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
795 (self.cb as usize).partial_cmp(&(other.cb as usize))
796 }
797}
798
799impl Ord for CreateThreadCallback {
800 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
801 (self.cb as usize).cmp(&(other.cb as usize))
802 }
803}
804
805impl core::hash::Hash for CreateThreadCallback {
806 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
807 (self.cb as usize).hash(state);
808 }
809}
810
811#[cfg(feature = "std")]
813pub extern "C" fn create_thread_libstd(
814 thread_initialize_data: RefAny,
815 writeback_data: RefAny,
816 callback: ThreadCallback,
817) -> Thread {
818 let (sender_receiver, receiver_receiver) = channel::<ThreadReceiveMsg>();
819 let mut sender_receiver = ThreadSender::new(ThreadSenderInner {
820 ptr: alloc::boxed::Box::new(sender_receiver),
821 send_fn: ThreadSendCallback {
822 cb: default_send_thread_msg_fn,
823 },
824 destructor: ThreadSenderDestructorCallback {
825 cb: thread_sender_drop,
826 },
827 });
828 sender_receiver.ctx = callback.ctx.clone();
830
831 let (sender_sender, receiver_sender) = channel::<ThreadSendMsg>();
832 let mut receiver_sender = ThreadReceiver::new(ThreadReceiverInner {
833 ptr: alloc::boxed::Box::new(receiver_sender),
834 recv_fn: ThreadRecvCallback {
835 cb: default_receive_thread_msg_fn,
836 },
837 destructor: ThreadReceiverDestructorCallback {
838 cb: thread_receiver_drop,
839 },
840 });
841 receiver_sender.ctx = callback.ctx.clone();
843
844 let thread_check = Arc::new(());
845 let dropcheck = Arc::downgrade(&thread_check);
846
847 let thread_handle = Some(thread::spawn(move || {
848 let _thread_check_guard = thread_check;
851 (callback.cb)(thread_initialize_data, sender_receiver, receiver_sender);
852 }));
854
855 let thread_handle: alloc::boxed::Box<Option<JoinHandle<()>>> =
856 alloc::boxed::Box::new(thread_handle);
857 let sender: alloc::boxed::Box<Sender<ThreadSendMsg>> = alloc::boxed::Box::new(sender_sender);
858 let receiver: alloc::boxed::Box<Receiver<ThreadReceiveMsg>> =
859 alloc::boxed::Box::new(receiver_receiver);
860 let dropcheck: alloc::boxed::Box<alloc::sync::Weak<()>> = alloc::boxed::Box::new(dropcheck);
861
862 Thread::new(ThreadInner {
863 thread_handle,
864 sender,
865 receiver,
866 writeback_data,
867 dropcheck,
868 thread_destructor_fn: ThreadDestructorCallback {
869 cb: default_thread_destructor_fn,
870 },
871 check_thread_finished_fn: CheckThreadFinishedCallback {
872 cb: default_check_thread_finished,
873 },
874 send_thread_msg_fn: LibrarySendThreadMsgCallback {
875 cb: library_send_thread_msg_fn,
876 },
877 receive_thread_msg_fn: LibraryReceiveThreadMsgCallback {
878 cb: library_receive_thread_msg_fn,
879 },
880 })
881}
882
883#[cfg(not(feature = "std"))]
884pub extern "C" fn create_thread_libstd(
885 _thread_initialize_data: RefAny,
886 _writeback_data: RefAny,
887 _callback: ThreadCallback,
888) -> Thread {
889 Thread {
890 ptr: core::ptr::null(),
891 run_destructor: false,
892 }
893}
894
895#[cfg(test)]
896mod tests {
897 use super::*;
898
899 extern "C" fn test_writeback_callback(
900 _thread_data: RefAny,
901 _writeback_data: RefAny,
902 _callback_info: CallbackInfo,
903 ) -> Update {
904 Update::DoNothing
905 }
906
907 #[test]
908 fn test_writeback_callback_creation() {
909 let callback = WriteBackCallback::new(test_writeback_callback);
910 assert_eq!(callback.cb as usize, test_writeback_callback as usize);
911 }
912
913 #[test]
914 fn test_writeback_callback_clone() {
915 let callback = WriteBackCallback::new(test_writeback_callback);
916 let cloned = callback.clone();
917 assert_eq!(callback, cloned);
918 }
919}
920
921#[derive(Debug, Clone)]
923#[repr(C, u8)]
924pub enum OptionThread {
925 None,
926 Some(Thread),
927}
928
929impl From<Option<Thread>> for OptionThread {
930 fn from(o: Option<Thread>) -> Self {
931 match o {
932 None => OptionThread::None,
933 Some(t) => OptionThread::Some(t),
934 }
935 }
936}
937
938impl OptionThread {
939 pub fn into_option(self) -> Option<Thread> {
940 match self {
941 OptionThread::None => None,
942 OptionThread::Some(t) => Some(t),
943 }
944 }
945}
946
947#[cfg(feature = "std")]
958pub fn thread_sleep_ms(milliseconds: u64) -> azul_css::corety::Void {
959 std::thread::sleep(std::time::Duration::from_millis(milliseconds));
960 azul_css::corety::Void::new()
961}
962
963#[cfg(not(feature = "std"))]
965pub fn thread_sleep_ms(_milliseconds: u64) -> azul_css::corety::Void {
966 azul_css::corety::Void::new()
968}
969
970#[cfg(feature = "std")]
975pub fn thread_sleep_us(microseconds: u64) -> azul_css::corety::Void {
976 std::thread::sleep(std::time::Duration::from_micros(microseconds));
977 azul_css::corety::Void::new()
978}
979
980#[cfg(not(feature = "std"))]
982pub fn thread_sleep_us(_microseconds: u64) -> azul_css::corety::Void {
983 azul_css::corety::Void::new()
985}
986
987#[cfg(feature = "std")]
992pub fn thread_sleep_ns(nanoseconds: u64) -> azul_css::corety::Void {
993 std::thread::sleep(std::time::Duration::from_nanos(nanoseconds));
994 azul_css::corety::Void::new()
995}
996
997#[cfg(not(feature = "std"))]
999pub fn thread_sleep_ns(_nanoseconds: u64) -> azul_css::corety::Void {
1000 azul_css::corety::Void::new()
1002}