1
1
use std:: cell:: Cell ;
2
- use std:: fmt:: Arguments ;
3
- use std:: mem;
4
2
use std:: ptr;
5
3
use std:: thread;
6
4
7
5
use crossbeam_channel:: { unbounded, Sender } ;
8
6
use lazy_static:: lazy_static;
9
7
8
+ use super :: log_utils;
10
9
use super :: task;
11
10
use super :: { JoinHandle , Task } ;
12
11
use crate :: future:: Future ;
13
12
use crate :: io;
13
+ use crate :: utils:: abort_on_panic;
14
14
15
15
/// Returns a handle to the current task.
16
16
///
64
64
F : Future < Output = T > + Send + ' static ,
65
65
T : Send + ' static ,
66
66
{
67
- spawn_with_builder ( Builder :: new ( ) , future, "spawn" )
67
+ spawn_with_builder ( Builder :: new ( ) , future)
68
68
}
69
69
70
70
/// Task builder that configures the settings of a new task.
@@ -91,15 +91,11 @@ impl Builder {
91
91
F : Future < Output = T > + Send + ' static ,
92
92
T : Send + ' static ,
93
93
{
94
- Ok ( spawn_with_builder ( self , future, "spawn" ) )
94
+ Ok ( spawn_with_builder ( self , future) )
95
95
}
96
96
}
97
97
98
- pub ( crate ) fn spawn_with_builder < F , T > (
99
- builder : Builder ,
100
- future : F ,
101
- fn_name : & ' static str ,
102
- ) -> JoinHandle < T >
98
+ pub ( crate ) fn spawn_with_builder < F , T > ( builder : Builder , future : F ) -> JoinHandle < T >
103
99
where
104
100
F : Future < Output = T > + Send + ' static ,
105
101
T : Send + ' static ,
@@ -117,13 +113,9 @@ where
117
113
thread:: Builder :: new( )
118
114
. name( "async-task-driver" . to_string( ) )
119
115
. spawn( || {
120
- TAG . with( |tag| {
121
- for job in receiver {
122
- tag. set( job. tag( ) ) ;
123
- abort_on_panic( || job. run( ) ) ;
124
- tag. set( ptr:: null( ) ) ;
125
- }
126
- } ) ;
116
+ for job in receiver {
117
+ set_tag( job. tag( ) , || abort_on_panic( || job. run( ) ) )
118
+ }
127
119
} )
128
120
. expect( "cannot start a thread driving tasks" ) ;
129
121
}
@@ -135,11 +127,12 @@ where
135
127
let tag = task:: Tag :: new ( name) ;
136
128
let schedule = |job| QUEUE . send ( job) . unwrap ( ) ;
137
129
130
+ // Log this `spawn` operation.
138
131
let child_id = tag. task_id ( ) . as_u64 ( ) ;
139
132
let parent_id = get_task ( |t| t. id ( ) . as_u64 ( ) ) . unwrap_or ( 0 ) ;
140
- print (
141
- format_args ! ( "{}" , fn_name ) ,
142
- LogData {
133
+ log_utils :: print (
134
+ format_args ! ( "spawn" ) ,
135
+ log_utils :: LogData {
143
136
parent_id,
144
137
child_id,
145
138
} ,
@@ -152,9 +145,9 @@ where
152
145
// Abort on panic because thread-local variables behave the same way.
153
146
abort_on_panic ( || get_task ( |task| task. metadata ( ) . local_map . clear ( ) ) ) ;
154
147
155
- print (
156
- format_args ! ( "{} completed" , fn_name ) ,
157
- LogData {
148
+ log_utils :: print (
149
+ format_args ! ( "spawn completed" ) ,
150
+ log_utils :: LogData {
158
151
parent_id,
159
152
child_id,
160
153
} ,
@@ -171,61 +164,34 @@ thread_local! {
171
164
static TAG : Cell <* const task:: Tag > = Cell :: new( ptr:: null_mut( ) ) ;
172
165
}
173
166
174
- pub ( crate ) fn get_task < F : FnOnce ( & Task ) -> R , R > ( f : F ) -> Option < R > {
175
- let res = TAG . try_with ( |tag| unsafe { tag. get ( ) . as_ref ( ) . map ( task:: Tag :: task) . map ( f) } ) ;
176
-
177
- match res {
178
- Ok ( Some ( val) ) => Some ( val) ,
179
- Ok ( None ) | Err ( _) => None ,
180
- }
181
- }
182
-
183
- /// Calls a function and aborts if it panics.
184
- ///
185
- /// This is useful in unsafe code where we can't recover from panics.
186
- #[ inline]
187
- fn abort_on_panic < T > ( f : impl FnOnce ( ) -> T ) -> T {
188
- struct Bomb ;
167
+ pub ( crate ) fn set_tag < F , R > ( tag : * const task:: Tag , f : F ) -> R
168
+ where
169
+ F : FnOnce ( ) -> R ,
170
+ {
171
+ struct ResetTag < ' a > ( & ' a Cell < * const task:: Tag > ) ;
189
172
190
- impl Drop for Bomb {
173
+ impl Drop for ResetTag < ' _ > {
191
174
fn drop ( & mut self ) {
192
- std :: process :: abort ( ) ;
175
+ self . 0 . set ( ptr :: null ( ) ) ;
193
176
}
194
177
}
195
178
196
- let bomb = Bomb ;
197
- let t = f ( ) ;
198
- mem:: forget ( bomb) ;
199
- t
200
- }
179
+ TAG . with ( |t| {
180
+ t. set ( tag) ;
181
+ let _guard = ResetTag ( t) ;
201
182
202
- /// This struct only exists because kv logging isn't supported from the macros right now.
203
- struct LogData {
204
- parent_id : u64 ,
205
- child_id : u64 ,
183
+ f ( )
184
+ } )
206
185
}
207
186
208
- impl < ' a > log:: kv:: Source for LogData {
209
- fn visit < ' kvs > (
210
- & ' kvs self ,
211
- visitor : & mut dyn log:: kv:: Visitor < ' kvs > ,
212
- ) -> Result < ( ) , log:: kv:: Error > {
213
- visitor. visit_pair ( "parent_id" . into ( ) , self . parent_id . into ( ) ) ?;
214
- visitor. visit_pair ( "child_id" . into ( ) , self . child_id . into ( ) ) ?;
215
- Ok ( ( ) )
216
- }
217
- }
187
+ pub ( crate ) fn get_task < F , R > ( f : F ) -> Option < R >
188
+ where
189
+ F : FnOnce ( & Task ) -> R ,
190
+ {
191
+ let res = TAG . try_with ( |tag| unsafe { tag. get ( ) . as_ref ( ) . map ( task:: Tag :: task) . map ( f) } ) ;
218
192
219
- fn print ( msg : Arguments < ' _ > , key_values : impl log:: kv:: Source ) {
220
- log:: logger ( ) . log (
221
- & log:: Record :: builder ( )
222
- . args ( msg)
223
- . key_values ( & key_values)
224
- . level ( log:: Level :: Trace )
225
- . target ( module_path ! ( ) )
226
- . module_path ( Some ( module_path ! ( ) ) )
227
- . file ( Some ( file ! ( ) ) )
228
- . line ( Some ( line ! ( ) ) )
229
- . build ( ) ,
230
- ) ;
193
+ match res {
194
+ Ok ( Some ( val) ) => Some ( val) ,
195
+ Ok ( None ) | Err ( _) => None ,
196
+ }
231
197
}
0 commit comments