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!(
106 TimerId,
107 TimerIdVec,
108 TimerIdVecDestructor,
109 TimerIdVecDestructorType
110);
111impl_vec_debug!(TimerId, TimerIdVec);
112impl_vec_clone!(TimerId, TimerIdVec, TimerIdVecDestructor);
113impl_vec_partialeq!(TimerId, TimerIdVec);
114impl_vec_partialord!(TimerId, TimerIdVec);
115
116static MAX_THREAD_ID: AtomicUsize = AtomicUsize::new(5);
117
118#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
120#[repr(C)]
121pub struct ThreadId {
122 id: usize,
123}
124
125impl_option!(
126 ThreadId,
127 OptionThreadId,
128 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
129);
130
131impl_vec!(
132 ThreadId,
133 ThreadIdVec,
134 ThreadIdVecDestructor,
135 ThreadIdVecDestructorType
136);
137impl_vec_debug!(ThreadId, ThreadIdVec);
138impl_vec_clone!(ThreadId, ThreadIdVec, ThreadIdVecDestructor);
139impl_vec_partialeq!(ThreadId, ThreadIdVec);
140impl_vec_partialord!(ThreadId, ThreadIdVec);
141
142impl ThreadId {
143 pub fn unique() -> Self {
145 ThreadId {
146 id: MAX_THREAD_ID.fetch_add(1, Ordering::SeqCst),
147 }
148 }
149}
150
151#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
155#[repr(C, u8)]
156pub enum Instant {
157 System(InstantPtr),
159 Tick(SystemTick),
161}
162
163#[cfg(feature = "std")]
164impl From<StdInstant> for Instant {
165 fn from(s: StdInstant) -> Instant {
166 Instant::System(s.into())
167 }
168}
169
170impl Instant {
171 #[cfg(feature = "std")]
176 pub fn now() -> Self {
177 StdInstant::now().into()
178 }
179
180 #[cfg(not(feature = "std"))]
182 pub fn now() -> Self {
183 Instant::Tick(SystemTick::new(0))
184 }
185
186 pub fn linear_interpolate(&self, mut start: Self, mut end: Self) -> f32 {
189 use core::mem;
190
191 if end < start {
192 mem::swap(&mut start, &mut end);
193 }
194
195 if *self < start {
196 return 0.0;
197 }
198 if *self > end {
199 return 1.0;
200 }
201
202 let duration_total = end.duration_since(&start);
203 let duration_current = self.duration_since(&start);
204
205 duration_current.div(&duration_total).max(0.0).min(1.0)
206 }
207
208 pub fn add_optional_duration(&self, duration: Option<&Duration>) -> Self {
211 match duration {
212 Some(d) => match (self, d) {
213 (Instant::System(i), Duration::System(d)) => {
214 #[cfg(feature = "std")]
215 {
216 let s: StdInstant = i.clone().into();
217 let d: StdDuration = d.clone().into();
218 let new: InstantPtr = (s + d).into();
219 Instant::System(new)
220 }
221 #[cfg(not(feature = "std"))]
222 {
223 unreachable!()
224 }
225 }
226 (Instant::Tick(s), Duration::Tick(d)) => Instant::Tick(SystemTick {
227 tick_counter: s.tick_counter + d.tick_diff,
228 }),
229 _ => {
230 panic!(
231 "invalid: trying to add a duration {:?} to an instant {:?}",
232 d, self
233 );
234 }
235 },
236 None => self.clone(),
237 }
238 }
239
240 #[cfg(feature = "std")]
242 pub fn into_std_instant(self) -> StdInstant {
243 match self {
244 Instant::System(s) => s.into(),
245 Instant::Tick(_) => unreachable!(),
246 }
247 }
248
249 pub fn duration_since(&self, earlier: &Instant) -> Duration {
254 match (earlier, self) {
255 (Instant::System(prev), Instant::System(now)) => {
256 #[cfg(feature = "std")]
257 {
258 let prev_instant: StdInstant = prev.clone().into();
259 let now_instant: StdInstant = now.clone().into();
260 Duration::System((now_instant.duration_since(prev_instant)).into())
261 }
262 #[cfg(not(feature = "std"))]
263 {
264 unreachable!() }
266 }
267 (
268 Instant::Tick(SystemTick { tick_counter: prev }),
269 Instant::Tick(SystemTick { tick_counter: now }),
270 ) => {
271 if prev > now {
272 panic!(
273 "illegal: subtraction 'Instant - Instant' would result in a negative \
274 duration"
275 )
276 } else {
277 Duration::Tick(SystemTickDiff {
278 tick_diff: now - prev,
279 })
280 }
281 }
282 _ => panic!(
283 "illegal: trying to calculate a Duration from a SystemTime and a Tick instant"
284 ),
285 }
286 }
287}
288
289#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
293#[repr(C)]
294pub struct SystemTick {
295 pub tick_counter: u64,
296}
297
298impl SystemTick {
299 pub const fn new(tick_counter: u64) -> Self {
301 Self { tick_counter }
302 }
303}
304
305#[repr(C)]
309pub struct InstantPtr {
310 #[cfg(feature = "std")]
311 pub ptr: Box<StdInstant>,
312 #[cfg(not(feature = "std"))]
313 pub ptr: *const c_void,
314 pub clone_fn: InstantPtrCloneCallback,
315 pub destructor: InstantPtrDestructorCallback,
316 pub run_destructor: bool,
317}
318
319pub type InstantPtrCloneCallbackType = extern "C" fn(*const InstantPtr) -> InstantPtr;
320#[repr(C)]
321pub struct InstantPtrCloneCallback {
322 pub cb: InstantPtrCloneCallbackType,
323}
324impl_callback_simple!(InstantPtrCloneCallback);
325
326pub type InstantPtrDestructorCallbackType = extern "C" fn(*mut InstantPtr);
327#[repr(C)]
328pub struct InstantPtrDestructorCallback {
329 pub cb: InstantPtrDestructorCallbackType,
330}
331impl_callback_simple!(InstantPtrDestructorCallback);
332
333#[cfg(feature = "std")]
335impl core::fmt::Debug for InstantPtr {
336 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
337 write!(f, "{:?}", self.get())
338 }
339}
340
341#[cfg(not(feature = "std"))]
342impl core::fmt::Debug for InstantPtr {
343 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
344 write!(f, "{:?}", self.ptr as usize)
345 }
346}
347
348#[cfg(feature = "std")]
349impl core::hash::Hash for InstantPtr {
350 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
351 self.get().hash(state);
352 }
353}
354
355#[cfg(not(feature = "std"))]
356impl core::hash::Hash for InstantPtr {
357 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
358 (self.ptr as usize).hash(state);
359 }
360}
361
362#[cfg(feature = "std")]
363impl PartialEq for InstantPtr {
364 fn eq(&self, other: &InstantPtr) -> bool {
365 self.get() == other.get()
366 }
367}
368
369#[cfg(not(feature = "std"))]
370impl PartialEq for InstantPtr {
371 fn eq(&self, other: &InstantPtr) -> bool {
372 (self.ptr as usize).eq(&(other.ptr as usize))
373 }
374}
375
376impl Eq for InstantPtr {}
377
378#[cfg(feature = "std")]
379impl PartialOrd for InstantPtr {
380 fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
381 Some((self.get()).cmp(&(other.get())))
382 }
383}
384
385#[cfg(not(feature = "std"))]
386impl PartialOrd for InstantPtr {
387 fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
388 Some((self.ptr as usize).cmp(&(other.ptr as usize)))
389 }
390}
391
392#[cfg(feature = "std")]
393impl Ord for InstantPtr {
394 fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
395 (self.get()).cmp(&(other.get()))
396 }
397}
398
399#[cfg(not(feature = "std"))]
400impl Ord for InstantPtr {
401 fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
402 (self.ptr as usize).cmp(&(other.ptr as usize))
403 }
404}
405
406#[cfg(feature = "std")]
407impl InstantPtr {
408 fn get(&self) -> StdInstant {
409 *(self.ptr).clone()
410 }
411}
412
413impl Clone for InstantPtr {
414 fn clone(&self) -> Self {
415 (self.clone_fn.cb)(self)
416 }
417}
418
419#[cfg(feature = "std")]
420extern "C" fn std_instant_clone(ptr: *const InstantPtr) -> InstantPtr {
421 let az_instant_ptr = unsafe { &*ptr };
422 InstantPtr {
423 ptr: az_instant_ptr.ptr.clone(),
424 clone_fn: az_instant_ptr.clone_fn.clone(),
425 destructor: az_instant_ptr.destructor.clone(),
426 run_destructor: true,
427 }
428}
429
430#[cfg(feature = "std")]
431impl From<StdInstant> for InstantPtr {
432 fn from(s: StdInstant) -> InstantPtr {
433 Self {
434 ptr: Box::new(s),
435 clone_fn: InstantPtrCloneCallback {
436 cb: std_instant_clone,
437 },
438 destructor: InstantPtrDestructorCallback {
439 cb: std_instant_drop,
440 },
441 run_destructor: true,
442 }
443 }
444}
445
446#[cfg(feature = "std")]
447impl From<InstantPtr> for StdInstant {
448 fn from(s: InstantPtr) -> StdInstant {
449 s.get()
450 }
451}
452
453impl Drop for InstantPtr {
454 fn drop(&mut self) {
455 self.run_destructor = false;
456 (self.destructor.cb)(self);
457 }
458}
459
460#[cfg(feature = "std")]
461extern "C" fn std_instant_drop(_: *mut InstantPtr) {}
462
463#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
470#[repr(C, u8)]
471pub enum Duration {
472 System(SystemTimeDiff),
474 Tick(SystemTickDiff),
476}
477
478impl core::fmt::Display for Duration {
479 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
480 match self {
481 #[cfg(feature = "std")]
482 Duration::System(s) => {
483 let s: StdDuration = s.clone().into();
484 write!(f, "{:?}", s)
485 }
486 #[cfg(not(feature = "std"))]
487 Duration::System(s) => write!(f, "({}s, {}ns)", s.secs, s.nanos),
488 Duration::Tick(tick) => write!(f, "{} ticks", tick.tick_diff),
489 }
490 }
491}
492
493#[cfg(feature = "std")]
494impl From<StdDuration> for Duration {
495 fn from(s: StdDuration) -> Self {
496 Duration::System(s.into())
497 }
498}
499
500impl Duration {
501 pub fn max() -> Self {
503 #[cfg(feature = "std")]
504 {
505 Duration::System(StdDuration::new(core::u64::MAX, NANOS_PER_SEC - 1).into())
506 }
507 #[cfg(not(feature = "std"))]
508 {
509 Duration::Tick(SystemTickDiff {
510 tick_diff: u64::MAX,
511 })
512 }
513 }
514
515 pub fn div(&self, other: &Self) -> f32 {
517 use self::Duration::*;
518 match (self, other) {
519 (System(s), System(s2)) => s.div(s2) as f32,
520 (Tick(t), Tick(t2)) => t.div(t2) as f32,
521 _ => 0.0,
522 }
523 }
524
525 pub fn min(self, other: Self) -> Self {
527 if self.smaller_than(&other) {
528 self
529 } else {
530 other
531 }
532 }
533
534 #[allow(unused_variables)]
536 pub fn greater_than(&self, other: &Self) -> bool {
537 match (self, other) {
538 (Duration::System(s), Duration::System(o)) => {
540 #[cfg(feature = "std")]
541 {
542 let s: StdDuration = s.clone().into();
543 let o: StdDuration = o.clone().into();
544 s > o
545 }
546 #[cfg(not(feature = "std"))]
547 {
548 unreachable!()
549 }
550 }
551 (Duration::Tick(s), Duration::Tick(o)) => s.tick_diff > o.tick_diff,
552 _ => {
553 panic!("illegal: trying to compare a SystemDuration with a TickDuration");
554 }
555 }
556 }
557
558 #[allow(unused_variables)]
560 pub fn smaller_than(&self, other: &Self) -> bool {
561 match (self, other) {
563 (Duration::System(s), Duration::System(o)) => {
565 #[cfg(feature = "std")]
566 {
567 let s: StdDuration = s.clone().into();
568 let o: StdDuration = o.clone().into();
569 s < o
570 }
571 #[cfg(not(feature = "std"))]
572 {
573 unreachable!()
574 }
575 }
576 (Duration::Tick(s), Duration::Tick(o)) => s.tick_diff < o.tick_diff,
577 _ => {
578 panic!("illegal: trying to compare a SystemDuration with a TickDuration");
579 }
580 }
581 }
582}
583
584#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
587#[repr(C)]
588pub struct SystemTickDiff {
589 pub tick_diff: u64,
590}
591
592impl SystemTickDiff {
593 pub fn div(&self, other: &Self) -> f64 {
595 self.tick_diff as f64 / other.tick_diff as f64
596 }
597}
598
599#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
601#[repr(C)]
602pub struct SystemTimeDiff {
603 pub secs: u64,
604 pub nanos: u32,
605}
606
607impl SystemTimeDiff {
608 pub fn div(&self, other: &Self) -> f64 {
610 self.as_secs_f64() / other.as_secs_f64()
611 }
612 fn as_secs_f64(&self) -> f64 {
613 (self.secs as f64) + ((self.nanos as f64) / (NANOS_PER_SEC as f64))
614 }
615}
616
617#[cfg(feature = "std")]
618impl From<StdDuration> for SystemTimeDiff {
619 fn from(d: StdDuration) -> SystemTimeDiff {
620 SystemTimeDiff {
621 secs: d.as_secs(),
622 nanos: d.subsec_nanos(),
623 }
624 }
625}
626
627#[cfg(feature = "std")]
628impl From<SystemTimeDiff> for StdDuration {
629 fn from(d: SystemTimeDiff) -> StdDuration {
630 StdDuration::new(d.secs, d.nanos)
631 }
632}
633
634const MILLIS_PER_SEC: u64 = 1_000;
635const NANOS_PER_MILLI: u32 = 1_000_000;
636const NANOS_PER_SEC: u32 = 1_000_000_000;
637
638impl SystemTimeDiff {
639 pub const fn from_secs(secs: u64) -> Self {
641 SystemTimeDiff { secs, nanos: 0 }
642 }
643 pub const fn from_millis(millis: u64) -> Self {
645 SystemTimeDiff {
646 secs: millis / MILLIS_PER_SEC,
647 nanos: ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI,
648 }
649 }
650 pub const fn from_nanos(nanos: u64) -> Self {
652 SystemTimeDiff {
653 secs: nanos / (NANOS_PER_SEC as u64),
654 nanos: (nanos % (NANOS_PER_SEC as u64)) as u32,
655 }
656 }
657 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
659 if let Some(mut secs) = self.secs.checked_add(rhs.secs) {
660 let mut nanos = self.nanos + rhs.nanos;
661 if nanos >= NANOS_PER_SEC {
662 nanos -= NANOS_PER_SEC;
663 if let Some(new_secs) = secs.checked_add(1) {
664 secs = new_secs;
665 } else {
666 return None;
667 }
668 }
669 Some(SystemTimeDiff { secs, nanos })
670 } else {
671 None
672 }
673 }
674
675 pub fn millis(&self) -> u64 {
677 (self.secs * MILLIS_PER_SEC) + (self.nanos / NANOS_PER_MILLI) as u64
678 }
679
680 #[cfg(feature = "std")]
682 pub fn get(&self) -> StdDuration {
683 (*self).into()
684 }
685}
686
687impl_option!(
688 Instant,
689 OptionInstant,
690 copy = false,
691 [Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
692);
693impl_option!(
694 Duration,
695 OptionDuration,
696 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
697);
698
699#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
703#[repr(C, u8)]
704pub enum ThreadSendMsg {
705 TerminateThread,
707 Tick,
709 Custom(RefAny),
711}
712
713impl_option!(
714 ThreadSendMsg,
715 OptionThreadSendMsg,
716 copy = false,
717 [Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash]
718);
719
720#[derive(Debug)]
724#[repr(C)]
725pub struct ThreadReceiver {
726 #[cfg(feature = "std")]
727 pub ptr: Box<Arc<Mutex<ThreadReceiverInner>>>,
728 #[cfg(not(feature = "std"))]
729 pub ptr: *const c_void,
730 pub run_destructor: bool,
731 pub ctx: OptionRefAny,
733}
734
735impl Clone for ThreadReceiver {
736 fn clone(&self) -> Self {
737 Self {
738 ptr: self.ptr.clone(),
739 run_destructor: true,
740 ctx: self.ctx.clone(),
741 }
742 }
743}
744
745impl Drop for ThreadReceiver {
746 fn drop(&mut self) {
747 self.run_destructor = false;
748 }
749}
750
751impl ThreadReceiver {
752 #[cfg(not(feature = "std"))]
754 pub fn new(t: ThreadReceiverInner) -> Self {
755 Self {
756 ptr: core::ptr::null(),
757 run_destructor: false,
758 ctx: OptionRefAny::None,
759 }
760 }
761
762 #[cfg(feature = "std")]
764 pub fn new(t: ThreadReceiverInner) -> Self {
765 Self {
766 ptr: Box::new(Arc::new(Mutex::new(t))),
767 run_destructor: true,
768 ctx: OptionRefAny::None,
769 }
770 }
771
772 pub fn get_ctx(&self) -> OptionRefAny {
774 self.ctx.clone()
775 }
776
777 #[cfg(not(feature = "std"))]
779 pub fn recv(&mut self) -> OptionThreadSendMsg {
780 None.into()
781 }
782
783 #[cfg(feature = "std")]
785 pub fn recv(&mut self) -> OptionThreadSendMsg {
786 let ts = match self.ptr.lock().ok() {
787 Some(s) => s,
788 None => return None.into(),
789 };
790 (ts.recv_fn.cb)(ts.ptr.as_ref() as *const _ as *const c_void)
791 }
792}
793
794#[derive(Debug)]
796#[cfg_attr(not(feature = "std"), derive(PartialEq, PartialOrd, Eq, Ord))]
797#[repr(C)]
798pub struct ThreadReceiverInner {
799 #[cfg(feature = "std")]
800 pub ptr: Box<Receiver<ThreadSendMsg>>,
801 #[cfg(not(feature = "std"))]
802 pub ptr: *const c_void,
803 pub recv_fn: ThreadRecvCallback,
804 pub destructor: ThreadReceiverDestructorCallback,
805}
806
807#[cfg(not(feature = "std"))]
808unsafe impl Send for ThreadReceiverInner {}
809
810#[cfg(feature = "std")]
811impl core::hash::Hash for ThreadReceiverInner {
812 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
813 (self.ptr.as_ref() as *const _ as usize).hash(state);
814 }
815}
816
817#[cfg(feature = "std")]
818impl PartialEq for ThreadReceiverInner {
819 fn eq(&self, other: &Self) -> bool {
820 (self.ptr.as_ref() as *const _ as usize) == (other.ptr.as_ref() as *const _ as usize)
821 }
822}
823
824#[cfg(feature = "std")]
825impl Eq for ThreadReceiverInner {}
826
827#[cfg(feature = "std")]
828impl PartialOrd for ThreadReceiverInner {
829 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
830 Some(
831 (self.ptr.as_ref() as *const _ as usize)
832 .cmp(&(other.ptr.as_ref() as *const _ as usize)),
833 )
834 }
835}
836
837#[cfg(feature = "std")]
838impl Ord for ThreadReceiverInner {
839 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
840 (self.ptr.as_ref() as *const _ as usize).cmp(&(other.ptr.as_ref() as *const _ as usize))
841 }
842}
843
844impl Drop for ThreadReceiverInner {
845 fn drop(&mut self) {
846 (self.destructor.cb)(self);
847 }
848}
849
850pub type GetSystemTimeCallbackType = extern "C" fn() -> Instant;
853#[repr(C)]
854pub struct GetSystemTimeCallback {
855 pub cb: GetSystemTimeCallbackType,
856}
857impl_callback_simple!(GetSystemTimeCallback);
858
859#[cfg(feature = "std")]
861pub extern "C" fn get_system_time_libstd() -> Instant {
862 StdInstant::now().into()
863}
864
865#[cfg(not(feature = "std"))]
867pub extern "C" fn get_system_time_libstd() -> Instant {
868 Instant::Tick(SystemTick::new(0))
869}
870
871pub type CheckThreadFinishedCallbackType =
873 extern "C" fn(*const c_void) -> bool;
874#[repr(C)]
876pub struct CheckThreadFinishedCallback {
877 pub cb: CheckThreadFinishedCallbackType,
878}
879impl_callback_simple!(CheckThreadFinishedCallback);
880
881pub type LibrarySendThreadMsgCallbackType =
883 extern "C" fn(*const c_void, ThreadSendMsg) -> bool;
884#[repr(C)]
886pub struct LibrarySendThreadMsgCallback {
887 pub cb: LibrarySendThreadMsgCallbackType,
888}
889impl_callback_simple!(LibrarySendThreadMsgCallback);
890
891pub type ThreadRecvCallbackType =
893 extern "C" fn(*const c_void) -> OptionThreadSendMsg;
894#[repr(C)]
896pub struct ThreadRecvCallback {
897 pub cb: ThreadRecvCallbackType,
898}
899impl_callback_simple!(ThreadRecvCallback);
900
901pub type ThreadReceiverDestructorCallbackType = extern "C" fn(*mut ThreadReceiverInner);
903#[repr(C)]
905pub struct ThreadReceiverDestructorCallback {
906 pub cb: ThreadReceiverDestructorCallbackType,
907}
908impl_callback_simple!(ThreadReceiverDestructorCallback);