1use std::fmt;
8use std::sync::Arc;
9use std::sync::atomic::{AtomicBool, Ordering};
10
11macro_rules! task {
12 ($name:ident: |$($field:ident: $field_type:ty$(,)*)*| $body:tt) => {{
13 #[allow(non_camel_case_types)]
14 struct $name<F> {
15 $($field: $field_type,)*
16 task: F,
17 }
18 #[allow(unsafe_code)]
19 unsafe impl<F> crate::JSTraceable for $name<F> {
20 #[allow(unsafe_code)]
21 unsafe fn trace(&self, tracer: *mut ::js::jsapi::JSTracer) {
22 $(self.$field.trace(tracer);)*
23 }
27 }
28 impl<F> crate::task::NonSendTaskOnce for $name<F>
29 where
30 F: ::std::ops::FnOnce($($field_type,)*),
31 {
32 fn run_once(self) {
33 (self.task)($(self.$field,)*);
34 }
35 }
36 $name {
37 $($field,)*
38 task: |$($field: $field_type,)*| $body,
39 }
40 }};
41
42 ($name:ident: move || $body:tt) => {{
43 #[allow(non_camel_case_types)]
44 struct $name<F>(F);
45 impl<F> crate::task::TaskOnce for $name<F>
46 where
47 F: ::std::ops::FnOnce() + Send,
48 {
49 fn name(&self) -> &'static str {
50 stringify!($name)
51 }
52
53 fn run_once(self) {
54 (self.0)();
55 }
56 }
57 $name(move || $body)
58 }};
59}
60
61pub(crate) trait TaskOnce: Send {
64 fn name(&self) -> &'static str {
65 ::std::any::type_name::<Self>()
66 }
67
68 fn run_once(self);
69}
70
71pub(crate) trait NonSendTaskOnce: crate::JSTraceable {
73 fn run_once(self);
74}
75
76pub(crate) trait TaskBox: Send {
78 fn name(&self) -> &'static str;
79
80 fn run_box(self: Box<Self>);
81}
82
83pub(crate) trait NonSendTaskBox: crate::JSTraceable {
85 fn run_box(self: Box<Self>);
86}
87
88impl<T> NonSendTaskBox for T
89where
90 T: NonSendTaskOnce,
91{
92 fn run_box(self: Box<Self>) {
93 self.run_once()
94 }
95}
96
97impl<T> TaskBox for T
98where
99 T: TaskOnce,
100{
101 fn name(&self) -> &'static str {
102 TaskOnce::name(self)
103 }
104
105 fn run_box(self: Box<Self>) {
106 self.run_once()
107 }
108}
109
110impl fmt::Debug for dyn TaskBox {
111 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
112 fmt.debug_tuple(self.name())
113 .field(&format_args!("..."))
114 .finish()
115 }
116}
117
118#[derive(Clone, Default, JSTraceable, MallocSizeOf)]
120pub(crate) struct TaskCanceller {
121 #[conditional_malloc_size_of]
122 pub(crate) cancelled: Arc<AtomicBool>,
123}
124
125impl TaskCanceller {
126 pub(crate) fn wrap_task<T>(&self, task: T) -> impl TaskOnce + use<T>
128 where
129 T: TaskOnce,
130 {
131 CancellableTask {
132 canceller: self.clone(),
133 inner: task,
134 }
135 }
136
137 pub(crate) fn cancelled(&self) -> bool {
138 self.cancelled.load(Ordering::SeqCst)
139 }
140}
141
142pub(crate) struct CancellableTask<T: TaskOnce> {
144 canceller: TaskCanceller,
145 inner: T,
146}
147
148impl<T: TaskOnce> TaskOnce for CancellableTask<T> {
149 fn name(&self) -> &'static str {
150 self.inner.name()
151 }
152
153 fn run_once(self) {
154 if !self.canceller.cancelled() {
155 self.inner.run_once()
156 }
157 }
158}