1#[cfg(not(feature = "std"))]
10use alloc::string::{String, ToString};
11use alloc::{
12 boxed::Box,
13 collections::btree_map::BTreeMap,
14 sync::{Arc, Weak},
15 vec::Vec,
16};
17use core::{
18 ffi::c_void,
19 fmt,
20 sync::atomic::{AtomicUsize, Ordering},
21};
22#[cfg(feature = "std")]
23use std::sync::mpsc::{Receiver, Sender};
24#[cfg(feature = "std")]
25use std::sync::Mutex;
26#[cfg(feature = "std")]
27use std::thread::{self, JoinHandle};
28#[cfg(feature = "std")]
29use std::time::Duration as StdDuration;
30#[cfg(feature = "std")]
31use std::time::Instant as StdInstant;
32
33use azul_css::{props::property::CssProperty, AzString};
34use rust_fontconfig::FcFontCache;
35
36use crate::{
37 callbacks::{FocusTarget, TimerCallbackReturn, Update},
38 dom::{DomId, DomNodeId, OptionDomNodeId},
39 geom::{LogicalPosition, OptionLogicalPosition},
40 gl::OptionGlContextPtr,
41 hit_test::ScrollPosition,
42 id::NodeId,
43 refany::{OptionRefAny, RefAny},
44 resources::{ImageCache, ImageMask, ImageRef},
45 styled_dom::NodeHierarchyItemId,
46 window::RawWindowHandle,
47 FastBTreeSet, FastHashMap,
48};
49
50#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
52#[repr(C)]
53pub enum TerminateTimer {
54 Terminate,
56 Continue,
58}
59
60pub const CURSOR_BLINK_TIMER_ID: TimerId = TimerId { id: 0x0001 };
68pub const SCROLL_MOMENTUM_TIMER_ID: TimerId = TimerId { id: 0x0002 };
70pub const DRAG_AUTOSCROLL_TIMER_ID: TimerId = TimerId { id: 0x0003 };
72pub const TOOLTIP_DELAY_TIMER_ID: TimerId = TimerId { id: 0x0004 };
74pub const DOUBLE_CLICK_TIMER_ID: TimerId = TimerId { id: 0x0005 };
76
77pub const USER_TIMER_ID_START: usize = 0x0100;
79
80static MAX_TIMER_ID: AtomicUsize = AtomicUsize::new(USER_TIMER_ID_START);
82
83#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
85#[repr(C)]
86pub struct TimerId {
87 pub id: usize,
88}
89
90impl TimerId {
91 pub fn unique() -> Self {
93 TimerId {
94 id: MAX_TIMER_ID.fetch_add(1, Ordering::SeqCst),
95 }
96 }
97}
98
99impl_option!(
100 TimerId,
101 OptionTimerId,
102 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
103);
104
105impl_vec!(TimerId, TimerIdVec, TimerIdVecDestructor, TimerIdVecDestructorType, TimerIdVecSlice, OptionTimerId);
106impl_vec_debug!(TimerId, TimerIdVec);
107impl_vec_clone!(TimerId, TimerIdVec, TimerIdVecDestructor);
108impl_vec_partialeq!(TimerId, TimerIdVec);
109impl_vec_partialord!(TimerId, TimerIdVec);
110
111static MAX_THREAD_ID: AtomicUsize = AtomicUsize::new(5);
112
113#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
115#[repr(C)]
116pub struct ThreadId {
117 id: usize,
118}
119
120impl_option!(
121 ThreadId,
122 OptionThreadId,
123 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
124);
125
126impl_vec!(ThreadId, ThreadIdVec, ThreadIdVecDestructor, ThreadIdVecDestructorType, ThreadIdVecSlice, OptionThreadId);
127impl_vec_debug!(ThreadId, ThreadIdVec);
128impl_vec_clone!(ThreadId, ThreadIdVec, ThreadIdVecDestructor);
129impl_vec_partialeq!(ThreadId, ThreadIdVec);
130impl_vec_partialord!(ThreadId, ThreadIdVec);
131
132impl ThreadId {
133 pub fn unique() -> Self {
135 ThreadId {
136 id: MAX_THREAD_ID.fetch_add(1, Ordering::SeqCst),
137 }
138 }
139}
140
141#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
145#[repr(C, u8)]
146pub enum Instant {
147 System(InstantPtr),
149 Tick(SystemTick),
151}
152
153#[cfg(feature = "std")]
154impl From<StdInstant> for Instant {
155 fn from(s: StdInstant) -> Instant {
156 Instant::System(s.into())
157 }
158}
159
160impl Instant {
161 #[cfg(feature = "std")]
166 pub fn now() -> Self {
167 StdInstant::now().into()
168 }
169
170 #[cfg(not(feature = "std"))]
172 pub fn now() -> Self {
173 Instant::Tick(SystemTick::new(0))
174 }
175
176 pub fn linear_interpolate(&self, mut start: Self, mut end: Self) -> f32 {
179 use core::mem;
180
181 if end < start {
182 mem::swap(&mut start, &mut end);
183 }
184
185 if *self < start {
186 return 0.0;
187 }
188 if *self > end {
189 return 1.0;
190 }
191
192 let duration_total = end.duration_since(&start);
193 let duration_current = self.duration_since(&start);
194
195 duration_current.div(&duration_total).max(0.0).min(1.0)
196 }
197
198 pub fn add_optional_duration(&self, duration: Option<&Duration>) -> Self {
201 match duration {
202 Some(d) => match (self, d) {
203 (Instant::System(i), Duration::System(d)) => {
204 #[cfg(feature = "std")]
205 {
206 let s: StdInstant = i.clone().into();
207 let d: StdDuration = d.clone().into();
208 let new: InstantPtr = (s + d).into();
209 Instant::System(new)
210 }
211 #[cfg(not(feature = "std"))]
212 {
213 unreachable!()
214 }
215 }
216 (Instant::Tick(s), Duration::Tick(d)) => Instant::Tick(SystemTick {
217 tick_counter: s.tick_counter + d.tick_diff,
218 }),
219 _ => {
220 panic!(
221 "invalid: trying to add a duration {:?} to an instant {:?}",
222 d, self
223 );
224 }
225 },
226 None => self.clone(),
227 }
228 }
229
230 #[cfg(feature = "std")]
232 pub fn into_std_instant(self) -> StdInstant {
233 match self {
234 Instant::System(s) => s.into(),
235 Instant::Tick(_) => unreachable!(),
236 }
237 }
238
239 pub fn duration_since(&self, earlier: &Instant) -> Duration {
244 match (earlier, self) {
245 (Instant::System(prev), Instant::System(now)) => {
246 #[cfg(feature = "std")]
247 {
248 let prev_instant: StdInstant = prev.clone().into();
249 let now_instant: StdInstant = now.clone().into();
250 Duration::System((now_instant.duration_since(prev_instant)).into())
251 }
252 #[cfg(not(feature = "std"))]
253 {
254 unreachable!() }
256 }
257 (
258 Instant::Tick(SystemTick { tick_counter: prev }),
259 Instant::Tick(SystemTick { tick_counter: now }),
260 ) => {
261 if prev > now {
262 panic!(
263 "illegal: subtraction 'Instant - Instant' would result in a negative \
264 duration"
265 )
266 } else {
267 Duration::Tick(SystemTickDiff {
268 tick_diff: now - prev,
269 })
270 }
271 }
272 _ => panic!(
273 "illegal: trying to calculate a Duration from a SystemTime and a Tick instant"
274 ),
275 }
276 }
277}
278
279#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
283#[repr(C)]
284pub struct SystemTick {
285 pub tick_counter: u64,
286}
287
288impl SystemTick {
289 pub const fn new(tick_counter: u64) -> Self {
291 Self { tick_counter }
292 }
293}
294
295#[repr(C)]
299pub struct InstantPtr {
300 #[cfg(feature = "std")]
301 pub ptr: Box<StdInstant>,
302 #[cfg(not(feature = "std"))]
303 pub ptr: *const c_void,
304 pub clone_fn: InstantPtrCloneCallback,
305 pub destructor: InstantPtrDestructorCallback,
306 pub run_destructor: bool,
307}
308
309pub type InstantPtrCloneCallbackType = extern "C" fn(*const InstantPtr) -> InstantPtr;
310#[repr(C)]
311pub struct InstantPtrCloneCallback {
312 pub cb: InstantPtrCloneCallbackType,
313}
314impl_callback_simple!(InstantPtrCloneCallback);
315
316pub type InstantPtrDestructorCallbackType = extern "C" fn(*mut InstantPtr);
317#[repr(C)]
318pub struct InstantPtrDestructorCallback {
319 pub cb: InstantPtrDestructorCallbackType,
320}
321impl_callback_simple!(InstantPtrDestructorCallback);
322
323#[cfg(feature = "std")]
325impl core::fmt::Debug for InstantPtr {
326 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
327 write!(f, "{:?}", self.get())
328 }
329}
330
331#[cfg(not(feature = "std"))]
332impl core::fmt::Debug for InstantPtr {
333 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
334 write!(f, "{:?}", self.ptr as usize)
335 }
336}
337
338#[cfg(feature = "std")]
339impl core::hash::Hash for InstantPtr {
340 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
341 self.get().hash(state);
342 }
343}
344
345#[cfg(not(feature = "std"))]
346impl core::hash::Hash for InstantPtr {
347 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
348 (self.ptr as usize).hash(state);
349 }
350}
351
352#[cfg(feature = "std")]
353impl PartialEq for InstantPtr {
354 fn eq(&self, other: &InstantPtr) -> bool {
355 self.get() == other.get()
356 }
357}
358
359#[cfg(not(feature = "std"))]
360impl PartialEq for InstantPtr {
361 fn eq(&self, other: &InstantPtr) -> bool {
362 (self.ptr as usize).eq(&(other.ptr as usize))
363 }
364}
365
366impl Eq for InstantPtr {}
367
368#[cfg(feature = "std")]
369impl PartialOrd for InstantPtr {
370 fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
371 Some((self.get()).cmp(&(other.get())))
372 }
373}
374
375#[cfg(not(feature = "std"))]
376impl PartialOrd for InstantPtr {
377 fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
378 Some((self.ptr as usize).cmp(&(other.ptr as usize)))
379 }
380}
381
382#[cfg(feature = "std")]
383impl Ord for InstantPtr {
384 fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
385 (self.get()).cmp(&(other.get()))
386 }
387}
388
389#[cfg(not(feature = "std"))]
390impl Ord for InstantPtr {
391 fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
392 (self.ptr as usize).cmp(&(other.ptr as usize))
393 }
394}
395
396#[cfg(feature = "std")]
397impl InstantPtr {
398 fn get(&self) -> StdInstant {
399 *(self.ptr).clone()
400 }
401}
402
403impl Clone for InstantPtr {
404 fn clone(&self) -> Self {
405 (self.clone_fn.cb)(self)
406 }
407}
408
409#[cfg(feature = "std")]
410extern "C" fn std_instant_clone(ptr: *const InstantPtr) -> InstantPtr {
411 let az_instant_ptr = unsafe { &*ptr };
412 InstantPtr {
413 ptr: az_instant_ptr.ptr.clone(),
414 clone_fn: az_instant_ptr.clone_fn.clone(),
415 destructor: az_instant_ptr.destructor.clone(),
416 run_destructor: true,
417 }
418}
419
420#[cfg(feature = "std")]
421impl From<StdInstant> for InstantPtr {
422 fn from(s: StdInstant) -> InstantPtr {
423 Self {
424 ptr: Box::new(s),
425 clone_fn: InstantPtrCloneCallback {
426 cb: std_instant_clone,
427 },
428 destructor: InstantPtrDestructorCallback {
429 cb: std_instant_drop,
430 },
431 run_destructor: true,
432 }
433 }
434}
435
436#[cfg(feature = "std")]
437impl From<InstantPtr> for StdInstant {
438 fn from(s: InstantPtr) -> StdInstant {
439 s.get()
440 }
441}
442
443impl Drop for InstantPtr {
444 fn drop(&mut self) {
445 self.run_destructor = false;
446 (self.destructor.cb)(self);
447 }
448}
449
450#[cfg(feature = "std")]
451extern "C" fn std_instant_drop(_: *mut InstantPtr) {}
452
453#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
460#[repr(C, u8)]
461pub enum Duration {
462 System(SystemTimeDiff),
464 Tick(SystemTickDiff),
466}
467
468impl core::fmt::Display for Duration {
469 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
470 match self {
471 #[cfg(feature = "std")]
472 Duration::System(s) => {
473 let s: StdDuration = s.clone().into();
474 write!(f, "{:?}", s)
475 }
476 #[cfg(not(feature = "std"))]
477 Duration::System(s) => write!(f, "({}s, {}ns)", s.secs, s.nanos),
478 Duration::Tick(tick) => write!(f, "{} ticks", tick.tick_diff),
479 }
480 }
481}
482
483#[cfg(feature = "std")]
484impl From<StdDuration> for Duration {
485 fn from(s: StdDuration) -> Self {
486 Duration::System(s.into())
487 }
488}
489
490impl Duration {
491 pub fn max() -> Self {
493 #[cfg(feature = "std")]
494 {
495 Duration::System(StdDuration::new(core::u64::MAX, NANOS_PER_SEC - 1).into())
496 }
497 #[cfg(not(feature = "std"))]
498 {
499 Duration::Tick(SystemTickDiff {
500 tick_diff: u64::MAX,
501 })
502 }
503 }
504
505 pub fn div(&self, other: &Self) -> f32 {
507 use self::Duration::*;
508 match (self, other) {
509 (System(s), System(s2)) => s.div(s2) as f32,
510 (Tick(t), Tick(t2)) => t.div(t2) as f32,
511 _ => 0.0,
512 }
513 }
514
515 pub fn min(self, other: Self) -> Self {
517 if self.smaller_than(&other) {
518 self
519 } else {
520 other
521 }
522 }
523
524 #[allow(unused_variables)]
526 pub fn greater_than(&self, other: &Self) -> bool {
527 match (self, other) {
528 (Duration::System(s), Duration::System(o)) => {
530 #[cfg(feature = "std")]
531 {
532 let s: StdDuration = s.clone().into();
533 let o: StdDuration = o.clone().into();
534 s > o
535 }
536 #[cfg(not(feature = "std"))]
537 {
538 unreachable!()
539 }
540 }
541 (Duration::Tick(s), Duration::Tick(o)) => s.tick_diff > o.tick_diff,
542 _ => {
543 panic!("illegal: trying to compare a SystemDuration with a TickDuration");
544 }
545 }
546 }
547
548 #[allow(unused_variables)]
550 pub fn smaller_than(&self, other: &Self) -> bool {
551 match (self, other) {
553 (Duration::System(s), Duration::System(o)) => {
555 #[cfg(feature = "std")]
556 {
557 let s: StdDuration = s.clone().into();
558 let o: StdDuration = o.clone().into();
559 s < o
560 }
561 #[cfg(not(feature = "std"))]
562 {
563 unreachable!()
564 }
565 }
566 (Duration::Tick(s), Duration::Tick(o)) => s.tick_diff < o.tick_diff,
567 _ => {
568 panic!("illegal: trying to compare a SystemDuration with a TickDuration");
569 }
570 }
571 }
572}
573
574#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
577#[repr(C)]
578pub struct SystemTickDiff {
579 pub tick_diff: u64,
580}
581
582impl SystemTickDiff {
583 pub fn div(&self, other: &Self) -> f64 {
585 self.tick_diff as f64 / other.tick_diff as f64
586 }
587}
588
589#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
591#[repr(C)]
592pub struct SystemTimeDiff {
593 pub secs: u64,
594 pub nanos: u32,
595}
596
597impl SystemTimeDiff {
598 pub fn div(&self, other: &Self) -> f64 {
600 self.as_secs_f64() / other.as_secs_f64()
601 }
602 fn as_secs_f64(&self) -> f64 {
603 (self.secs as f64) + ((self.nanos as f64) / (NANOS_PER_SEC as f64))
604 }
605}
606
607#[cfg(feature = "std")]
608impl From<StdDuration> for SystemTimeDiff {
609 fn from(d: StdDuration) -> SystemTimeDiff {
610 SystemTimeDiff {
611 secs: d.as_secs(),
612 nanos: d.subsec_nanos(),
613 }
614 }
615}
616
617#[cfg(feature = "std")]
618impl From<SystemTimeDiff> for StdDuration {
619 fn from(d: SystemTimeDiff) -> StdDuration {
620 StdDuration::new(d.secs, d.nanos)
621 }
622}
623
624const MILLIS_PER_SEC: u64 = 1_000;
625const NANOS_PER_MILLI: u32 = 1_000_000;
626const NANOS_PER_SEC: u32 = 1_000_000_000;
627
628impl SystemTimeDiff {
629 pub const fn from_secs(secs: u64) -> Self {
631 SystemTimeDiff { secs, nanos: 0 }
632 }
633 pub const fn from_millis(millis: u64) -> Self {
635 SystemTimeDiff {
636 secs: millis / MILLIS_PER_SEC,
637 nanos: ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI,
638 }
639 }
640 pub const fn from_nanos(nanos: u64) -> Self {
642 SystemTimeDiff {
643 secs: nanos / (NANOS_PER_SEC as u64),
644 nanos: (nanos % (NANOS_PER_SEC as u64)) as u32,
645 }
646 }
647 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
649 if let Some(mut secs) = self.secs.checked_add(rhs.secs) {
650 let mut nanos = self.nanos + rhs.nanos;
651 if nanos >= NANOS_PER_SEC {
652 nanos -= NANOS_PER_SEC;
653 if let Some(new_secs) = secs.checked_add(1) {
654 secs = new_secs;
655 } else {
656 return None;
657 }
658 }
659 Some(SystemTimeDiff { secs, nanos })
660 } else {
661 None
662 }
663 }
664
665 pub fn millis(&self) -> u64 {
667 (self.secs * MILLIS_PER_SEC) + (self.nanos / NANOS_PER_MILLI) as u64
668 }
669
670 #[cfg(feature = "std")]
672 pub fn get(&self) -> StdDuration {
673 (*self).into()
674 }
675}
676
677impl_option!(
678 Instant,
679 OptionInstant,
680 copy = false,
681 [Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
682);
683impl_option!(
684 Duration,
685 OptionDuration,
686 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
687);
688
689#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
693#[repr(C, u8)]
694pub enum ThreadSendMsg {
695 TerminateThread,
697 Tick,
699 Custom(RefAny),
701}
702
703impl_option!(
704 ThreadSendMsg,
705 OptionThreadSendMsg,
706 copy = false,
707 [Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash]
708);
709
710#[derive(Debug)]
714#[repr(C)]
715pub struct ThreadReceiver {
716 #[cfg(feature = "std")]
717 pub ptr: Box<Arc<Mutex<ThreadReceiverInner>>>,
718 #[cfg(not(feature = "std"))]
719 pub ptr: *const c_void,
720 pub run_destructor: bool,
721 pub ctx: OptionRefAny,
723}
724
725impl Clone for ThreadReceiver {
726 fn clone(&self) -> Self {
727 Self {
728 ptr: self.ptr.clone(),
729 run_destructor: true,
730 ctx: self.ctx.clone(),
731 }
732 }
733}
734
735impl Drop for ThreadReceiver {
736 fn drop(&mut self) {
737 self.run_destructor = false;
738 }
739}
740
741impl ThreadReceiver {
742 #[cfg(not(feature = "std"))]
744 pub fn new(t: ThreadReceiverInner) -> Self {
745 Self {
746 ptr: core::ptr::null(),
747 run_destructor: false,
748 ctx: OptionRefAny::None,
749 }
750 }
751
752 #[cfg(feature = "std")]
754 pub fn new(t: ThreadReceiverInner) -> Self {
755 Self {
756 ptr: Box::new(Arc::new(Mutex::new(t))),
757 run_destructor: true,
758 ctx: OptionRefAny::None,
759 }
760 }
761
762 pub fn get_ctx(&self) -> OptionRefAny {
764 self.ctx.clone()
765 }
766
767 #[cfg(not(feature = "std"))]
769 pub fn recv(&mut self) -> OptionThreadSendMsg {
770 None.into()
771 }
772
773 #[cfg(feature = "std")]
775 pub fn recv(&mut self) -> OptionThreadSendMsg {
776 let ts = match self.ptr.lock().ok() {
777 Some(s) => s,
778 None => return None.into(),
779 };
780 (ts.recv_fn.cb)(ts.ptr.as_ref() as *const _ as *const c_void)
781 }
782}
783
784#[derive(Debug)]
786#[cfg_attr(not(feature = "std"), derive(PartialEq, PartialOrd, Eq, Ord))]
787#[repr(C)]
788pub struct ThreadReceiverInner {
789 #[cfg(feature = "std")]
790 pub ptr: Box<Receiver<ThreadSendMsg>>,
791 #[cfg(not(feature = "std"))]
792 pub ptr: *const c_void,
793 pub recv_fn: ThreadRecvCallback,
794 pub destructor: ThreadReceiverDestructorCallback,
795}
796
797#[cfg(not(feature = "std"))]
798unsafe impl Send for ThreadReceiverInner {}
799
800#[cfg(feature = "std")]
801impl core::hash::Hash for ThreadReceiverInner {
802 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
803 (self.ptr.as_ref() as *const _ as usize).hash(state);
804 }
805}
806
807#[cfg(feature = "std")]
808impl PartialEq for ThreadReceiverInner {
809 fn eq(&self, other: &Self) -> bool {
810 (self.ptr.as_ref() as *const _ as usize) == (other.ptr.as_ref() as *const _ as usize)
811 }
812}
813
814#[cfg(feature = "std")]
815impl Eq for ThreadReceiverInner {}
816
817#[cfg(feature = "std")]
818impl PartialOrd for ThreadReceiverInner {
819 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
820 Some(
821 (self.ptr.as_ref() as *const _ as usize)
822 .cmp(&(other.ptr.as_ref() as *const _ as usize)),
823 )
824 }
825}
826
827#[cfg(feature = "std")]
828impl Ord for ThreadReceiverInner {
829 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
830 (self.ptr.as_ref() as *const _ as usize).cmp(&(other.ptr.as_ref() as *const _ as usize))
831 }
832}
833
834impl Drop for ThreadReceiverInner {
835 fn drop(&mut self) {
836 (self.destructor.cb)(self);
837 }
838}
839
840pub type GetSystemTimeCallbackType = extern "C" fn() -> Instant;
843#[repr(C)]
844pub struct GetSystemTimeCallback {
845 pub cb: GetSystemTimeCallbackType,
846}
847impl_callback_simple!(GetSystemTimeCallback);
848
849#[cfg(all(feature = "std", not(target_arch = "wasm32")))]
854pub extern "C" fn get_system_time_libstd() -> Instant {
855 StdInstant::now().into()
856}
857
858#[cfg(any(not(feature = "std"), target_arch = "wasm32"))]
860pub extern "C" fn get_system_time_libstd() -> Instant {
861 Instant::Tick(SystemTick::new(0))
862}
863
864pub type CheckThreadFinishedCallbackType =
866 extern "C" fn(*const c_void) -> bool;
867#[repr(C)]
869pub struct CheckThreadFinishedCallback {
870 pub cb: CheckThreadFinishedCallbackType,
871}
872impl_callback_simple!(CheckThreadFinishedCallback);
873
874pub type LibrarySendThreadMsgCallbackType =
876 extern "C" fn(*const c_void, ThreadSendMsg) -> bool;
877#[repr(C)]
879pub struct LibrarySendThreadMsgCallback {
880 pub cb: LibrarySendThreadMsgCallbackType,
881}
882impl_callback_simple!(LibrarySendThreadMsgCallback);
883
884pub type ThreadRecvCallbackType =
886 extern "C" fn(*const c_void) -> OptionThreadSendMsg;
887#[repr(C)]
889pub struct ThreadRecvCallback {
890 pub cb: ThreadRecvCallbackType,
891}
892impl_callback_simple!(ThreadRecvCallback);
893
894pub type ThreadReceiverDestructorCallbackType = extern "C" fn(*mut ThreadReceiverInner);
896#[repr(C)]
898pub struct ThreadReceiverDestructorCallback {
899 pub cb: ThreadReceiverDestructorCallbackType,
900}
901impl_callback_simple!(ThreadReceiverDestructorCallback);