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