/build/source/nativelink-util/src/origin_context.rs
Line | Count | Source |
1 | | // Copyright 2024 The NativeLink Authors. All rights reserved. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | use core::panic; |
16 | | use std::any::Any; |
17 | | use std::cell::RefCell; |
18 | | use std::clone::Clone; |
19 | | use std::collections::HashMap; |
20 | | use std::collections::hash_map::Entry; |
21 | | use std::mem::ManuallyDrop; |
22 | | use std::pin::Pin; |
23 | | use std::sync::Arc; |
24 | | use std::task::{Context, Poll}; |
25 | | |
26 | | use futures::Future; |
27 | | use nativelink_error::{Code, Error, make_err}; |
28 | | use pin_project_lite::pin_project; |
29 | | use tracing::instrument::Instrumented; |
30 | | use tracing::{Instrument, Span}; |
31 | | |
32 | | use crate::background_spawn; |
33 | | |
34 | | /// Make a symbol that represents a unique memory pointer that is |
35 | | /// constant and chosen at compile time. This enables two modules |
36 | | /// to use that memory location to reference data that lives in a |
37 | | /// shared module without the two modules knowing about each other. |
38 | | /// For example, let's say we have a context that holds anonymous |
39 | | /// data; we can use these symbols to let one module set the data |
40 | | /// and tie the data to a symbol and another module read the data |
41 | | /// with the symbol, without the two modules knowing about each other. |
42 | | /// |
43 | | /// Safety: The symbol name must be globally unique. |
44 | | #[macro_export] |
45 | | macro_rules! unsafe_make_symbol { |
46 | | ($name:ident, $type:ident) => { |
47 | | #[unsafe(no_mangle)] |
48 | | #[used] |
49 | | pub static $name: $crate::origin_context::NLSymbol<$type> = |
50 | | $crate::origin_context::NLSymbol { |
51 | | name: concat!(module_path!(), "::", stringify!($name)), |
52 | | _phantom: std::marker::PhantomData {}, |
53 | | }; |
54 | | }; |
55 | | } |
56 | | |
57 | | // Symbol that represents the identity of the origin of a request. |
58 | | // See: IdentityHeaderSpec for details. |
59 | | // Safety: There is no other symbol named `ORIGIN_IDENTITY`. |
60 | | unsafe_make_symbol!(ORIGIN_IDENTITY, String); |
61 | | |
62 | | #[derive(Debug)] |
63 | | pub struct NLSymbol<T: Send + Sync + 'static> { |
64 | | pub name: &'static str, |
65 | | pub _phantom: std::marker::PhantomData<T>, |
66 | | } |
67 | | |
68 | | impl<T: Send + Sync + 'static> Symbol for NLSymbol<T> { |
69 | | type Type = T; |
70 | | |
71 | 0 | fn name(&self) -> &'static str { |
72 | 0 | self.name |
73 | 0 | } |
74 | | } |
75 | | |
76 | | pub trait Symbol { |
77 | | type Type: 'static; |
78 | | |
79 | 0 | fn name(&self) -> &'static str { |
80 | 0 | std::any::type_name::<Self>() |
81 | 0 | } |
82 | | } |
83 | | |
84 | | /// Simple wrapper around a symbol address. |
85 | | /// |
86 | | /// By using an address rather than a pointer, we can ensure that the struct |
87 | | /// is thread-safe and avoids any potential unsoundness from dereferencing a |
88 | | /// pointer. |
89 | | #[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)] |
90 | | #[repr(transparent)] |
91 | | pub struct SymbolAddress(usize); |
92 | | |
93 | | impl SymbolAddress { |
94 | 151 | pub fn from_ptr<T: ?Sized>(ptr: *const T) -> Self { |
95 | 151 | Self(ptr.addr()) |
96 | 151 | } |
97 | | } |
98 | | |
99 | | /// Context used to store data about the origin of a request. |
100 | | #[derive(Debug, Default, Clone)] |
101 | | pub struct OriginContext { |
102 | | data: HashMap<SymbolAddress, Arc<dyn Any + Send + Sync + 'static>>, |
103 | | } |
104 | | |
105 | | impl OriginContext { |
106 | | /// Creates a new (empty) context. |
107 | 304 | pub fn new() -> Self { |
108 | 304 | Self::default() |
109 | 304 | } |
110 | | |
111 | | /// Replaces the value for a given symbol on the context. |
112 | 0 | pub fn replace_value<T: Any + Send + Sync + 'static>( |
113 | 0 | &mut self, |
114 | 0 | symbol: &'static impl Symbol<Type = T>, |
115 | 0 | cb: impl FnOnce(Option<Arc<T>>) -> Option<Arc<T>>, |
116 | 0 | ) { |
117 | 0 | let entry = self.data.entry(SymbolAddress::from_ptr(symbol)); |
118 | 0 | let old_value = match &entry { |
119 | 0 | Entry::Occupied(data) => Arc::downcast(data.get().clone()).ok(), |
120 | 0 | Entry::Vacant(_) => None, |
121 | | }; |
122 | 0 | match cb(old_value) { |
123 | 0 | Some(new_value) => { |
124 | 0 | entry.insert_entry(new_value); |
125 | 0 | } |
126 | | None => { |
127 | 0 | if let Entry::Occupied(entry) = entry { Branch (127:24): [True: 0, False: 0]
Branch (127:24): [Folded - Ignored]
Branch (127:24): [Folded - Ignored]
Branch (127:24): [True: 0, False: 0]
|
128 | 0 | entry.remove(); |
129 | 0 | } |
130 | | } |
131 | | } |
132 | 0 | } |
133 | | |
134 | | /// Sets the value for a given symbol on the context. |
135 | 42 | pub fn set_value<T: Any + Send + Sync + 'static>( |
136 | 42 | &mut self, |
137 | 42 | symbol: &'static impl Symbol<Type = T>, |
138 | 42 | value: Arc<T>, |
139 | 42 | ) -> Option<Arc<dyn Any + Send + Sync + 'static>> { |
140 | 42 | self.data.insert(SymbolAddress::from_ptr(symbol), value) |
141 | 42 | } |
142 | | |
143 | | /// Gets the value current set for a given symbol on the context. |
144 | | #[inline] |
145 | 109 | pub fn get_value<T: Send + Sync + 'static>( |
146 | 109 | &self, |
147 | 109 | symbol: &'static impl Symbol<Type = T>, |
148 | 109 | ) -> Result<Option<Arc<T>>, Error> { |
149 | 109 | self.data |
150 | 109 | .get(&SymbolAddress::from_ptr(symbol)) |
151 | 109 | .map_or(Ok(None), |value| { |
152 | 2 | Arc::downcast::<T>(value.clone()).map_or_else( |
153 | 0 | |_| { |
154 | 0 | Err(make_err!( |
155 | 0 | Code::Internal, |
156 | 0 | "Failed to downcast symbol: {}", |
157 | 0 | symbol.name(), |
158 | 0 | )) |
159 | 0 | }, |
160 | 2 | |v| Ok(Some(v)), |
161 | | ) |
162 | 2 | }) |
163 | 109 | } |
164 | | |
165 | | /// Consumes the context and runs the given function with the context set |
166 | | /// as the active context. When the function exits, the context is restored |
167 | | /// to the previous global context. |
168 | | #[inline] |
169 | 4 | pub fn run<T>(self, span: Span, func: impl FnOnce() -> T) -> T { |
170 | 4 | Arc::new(self).wrap(span, func)() |
171 | 4 | } |
172 | | |
173 | | /// Wraps a function so when it is called the passed in context is set as |
174 | | /// the active context and when the function exits, the context is restored |
175 | | /// to the previous global context. |
176 | | #[inline] |
177 | 4 | fn wrap<T>(self: Arc<Self>, span: Span, func: impl FnOnce() -> T) -> impl FnOnce() -> T { |
178 | 4 | move || { |
179 | 4 | let enter = Self::enter(self); |
180 | 4 | let result = span.in_scope(func); |
181 | 4 | enter.release(); |
182 | 4 | result |
183 | 4 | } |
184 | 4 | } |
185 | | |
186 | | /// Wraps a future so when it is called the passed in context is set as |
187 | | /// the active context and when the future exits, the context is restored |
188 | | /// to the previous global context. |
189 | | #[inline] |
190 | 342 | pub fn wrap_async<T>( |
191 | 342 | self: Arc<Self>, |
192 | 342 | span: Span, |
193 | 342 | fut: impl Future<Output = T>, |
194 | 342 | ) -> impl Future<Output = T> { |
195 | 342 | ContextAwareFuture::new(Some(self), fut.instrument(span)) |
196 | 342 | } |
197 | | |
198 | | /// Spawns a future in the background with the given context. |
199 | 0 | pub fn background_spawn( |
200 | 0 | self: Arc<Self>, |
201 | 0 | span: Span, |
202 | 0 | fut: impl Future<Output = ()> + Send + 'static, |
203 | 0 | ) { |
204 | 0 | background_spawn!(span: span, ctx: Some(self), fut: fut); |
205 | 0 | } |
206 | | |
207 | | /// Enters the context, storing the previous context. If the returned |
208 | | /// `ContextDropGuard` is dropped, the previous context is restored. |
209 | | #[inline] |
210 | 18.2k | fn enter(self: Arc<Self>) -> ContextDropGuard { |
211 | 18.2k | ContextDropGuard::new(self) |
212 | 18.2k | } |
213 | | } |
214 | | |
215 | | /// Static struct to interact with the active global context. |
216 | | #[derive(Debug, Clone, Copy)] |
217 | | pub struct ActiveOriginContext; |
218 | | |
219 | | impl ActiveOriginContext { |
220 | | /// Sets the active context for the current thread. |
221 | 1.53k | pub fn get() -> Option<Arc<OriginContext>> { |
222 | 1.53k | GLOBAL_ORIGIN_CONTEXT.with_borrow(Clone::clone) |
223 | 1.53k | } |
224 | | |
225 | | /// Gets the value current set for a given symbol on the |
226 | | /// active context. |
227 | | #[inline] |
228 | 107 | pub fn get_value<T: Send + Sync + 'static>( |
229 | 107 | symbol: &'static impl Symbol<Type = T>, |
230 | 107 | ) -> Result<Option<Arc<T>>, Error> { |
231 | 107 | GLOBAL_ORIGIN_CONTEXT.with_borrow(|maybe_ctx| { |
232 | 107 | maybe_ctx.as_ref().map_or_else( |
233 | 0 | || { |
234 | 0 | Err(make_err!( |
235 | 0 | Code::Internal, |
236 | 0 | "Expected active context to be set" |
237 | 0 | )) |
238 | 0 | }, |
239 | 107 | |ctx| ctx.get_value(symbol), |
240 | | ) |
241 | 107 | }) |
242 | 107 | } |
243 | | |
244 | | /// Forks the active context, returning a new context with the same data. |
245 | | #[inline] |
246 | 42 | pub fn fork() -> Result<OriginContext, Error> { |
247 | 42 | GLOBAL_ORIGIN_CONTEXT.with_borrow(|maybe_ctx| { |
248 | 42 | maybe_ctx.as_ref().map_or_else( |
249 | 0 | || { |
250 | 0 | Err(make_err!( |
251 | 0 | Code::Internal, |
252 | 0 | "Expected active context to be set" |
253 | 0 | )) |
254 | 0 | }, |
255 | 42 | |ctx| Ok(ctx.as_ref().clone()), |
256 | | ) |
257 | 42 | }) |
258 | 42 | } |
259 | | } |
260 | | |
261 | | thread_local! { |
262 | | /// Global context that is used to store the active context. |
263 | | static GLOBAL_ORIGIN_CONTEXT: RefCell<Option<Arc<OriginContext>>> = const { RefCell::new(None) }; |
264 | | } |
265 | | |
266 | | /// Special guard struct that is used to hold the previous context and restore it |
267 | | /// when the guard is released or dropped. |
268 | | struct ContextDropGuard { |
269 | | prev_ctx: Option<Arc<OriginContext>>, |
270 | | new_ctx_ptr: *const OriginContext, |
271 | | } |
272 | | |
273 | | impl ContextDropGuard { |
274 | | /// Places the new context in the global context, stores the previous context |
275 | | /// and returns a new `ContextDropGuard`, so if it is ever released or dropped |
276 | | /// the previous context will be restored. |
277 | | #[inline] |
278 | 18.2k | fn new(new_ctx: Arc<OriginContext>) -> Self { |
279 | 18.2k | let new_ctx_ptr = Arc::as_ptr(&new_ctx); |
280 | 18.2k | let prev_ctx = GLOBAL_ORIGIN_CONTEXT.replace(Some(new_ctx)); |
281 | 18.2k | Self { |
282 | 18.2k | prev_ctx, |
283 | 18.2k | new_ctx_ptr, |
284 | 18.2k | } |
285 | 18.2k | } |
286 | | |
287 | | /// Swap the global context with the previous context. |
288 | | /// Returns the context used in the `.enter()`/`.new()` call. |
289 | 18.2k | fn restore_global_context(&mut self) -> Arc<OriginContext> { |
290 | 18.2k | let new_ctx = GLOBAL_ORIGIN_CONTEXT |
291 | 18.2k | .replace(self.prev_ctx.take()) |
292 | 18.2k | .expect("Expected global context to be set"); |
293 | 18.2k | assert_eq!(self.new_ctx_ptr, Arc::as_ptr(&new_ctx)); |
294 | 18.2k | new_ctx |
295 | 18.2k | } |
296 | | |
297 | | /// Release the context guard and restore the previous context. |
298 | | /// This is an optimization, so we don't need to clone our Arc |
299 | | /// if the caller can use the context after releasing it. |
300 | | #[inline] |
301 | 16.4k | fn release(mut self) -> Arc<OriginContext> { |
302 | 16.4k | let new_ctx = self.restore_global_context(); |
303 | 16.4k | std::mem::forget(self); // Prevent the destructor from being called. |
304 | 16.4k | new_ctx |
305 | 16.4k | } |
306 | | } |
307 | | |
308 | | impl Drop for ContextDropGuard { |
309 | | #[inline] |
310 | 1.87k | fn drop(&mut self) { |
311 | 1.87k | // If the user calls `.release()` the drop() will not be triggered. |
312 | 1.87k | // If a panic happens, the drop() will be called and the `.release()` |
313 | 1.87k | // will not be called, this is our safety net. |
314 | 1.87k | self.restore_global_context(); |
315 | 1.87k | } |
316 | | } |
317 | | |
318 | | pin_project! { |
319 | | #[must_use = "futures do nothing unless you `.await` or poll them"] |
320 | | pub struct ContextAwareFuture<F> { |
321 | | // `ManuallyDrop` is used so we can call `self.span.enter()` in the `drop()` |
322 | | // of our inner future, then drop the span. |
323 | | #[pin] |
324 | | inner: ManuallyDrop<Instrumented<F>>, |
325 | | context: Option<Arc<OriginContext>>, |
326 | | } |
327 | | |
328 | | impl <F> PinnedDrop for ContextAwareFuture<F> { |
329 | | #[inline] |
330 | | fn drop(this: Pin<&mut Self>) { |
331 | | let this = this.project(); |
332 | | // Note: If the future panics, the context will not be restored, so |
333 | | // this is a best effort to provide access to our global context |
334 | | // in the destructors the event of a panic. |
335 | | let _enter = this.context.take().map(OriginContext::enter); |
336 | | // SAFETY: 1. `Pin::get_unchecked_mut()` is safe, because this isn't |
337 | | // different from wrapping `T` in `Option` and calling |
338 | | // `Pin::set(&mut this.inner, None)`, except avoiding |
339 | | // additional memory overhead. |
340 | | // 2. `ManuallyDrop::drop()` is safe, because |
341 | | // `PinnedDrop::drop()` is guaranteed to be called only |
342 | | // once. |
343 | | unsafe { |
344 | | ManuallyDrop::drop(this.inner.get_unchecked_mut()); |
345 | | } |
346 | | } |
347 | | } |
348 | | } |
349 | | |
350 | | impl<T> ContextAwareFuture<T> { |
351 | | /// Utility function to create a new `ContextAwareFuture` from the |
352 | | /// active context. |
353 | | #[must_use = "futures do nothing unless you `.await` or poll them"] |
354 | | #[inline] |
355 | 9 | pub fn new_from_active(inner: Instrumented<T>) -> ContextAwareFuture<T> { |
356 | 9 | if let Some(ctx) = ActiveOriginContext::get() { Branch (356:16): [Folded - Ignored]
Branch (356:16): [True: 2, False: 0]
Branch (356:16): [True: 2, False: 0]
Branch (356:16): [True: 2, False: 0]
Branch (356:16): [True: 2, False: 0]
Branch (356:16): [True: 1, False: 0]
Branch (356:16): [Folded - Ignored]
|
357 | 9 | ContextAwareFuture::new(Some(ctx), inner) |
358 | | } else { |
359 | | // Useful to get tracing stack trace. |
360 | 0 | tracing::error!("OriginContext must be set"); |
361 | 0 | panic!("OriginContext must be set"); |
362 | | } |
363 | 9 | } |
364 | | |
365 | | #[must_use = "futures do nothing unless you `.await` or poll them"] |
366 | | #[inline] |
367 | 1.87k | pub(crate) const fn new(context: Option<Arc<OriginContext>>, inner: Instrumented<T>) -> Self { |
368 | 1.87k | Self { |
369 | 1.87k | inner: ManuallyDrop::new(inner), |
370 | 1.87k | context, |
371 | 1.87k | } |
372 | 1.87k | } |
373 | | } |
374 | | |
375 | | impl<T: Future> Future for ContextAwareFuture<T> { |
376 | | type Output = T::Output; |
377 | | |
378 | | #[inline] |
379 | 16.4k | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
380 | 16.4k | let this = self.project(); |
381 | 16.4k | let Some(ctx) = this.context.take() else { Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 23, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 115, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 32, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 6, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 54, False: 0]
Branch (381:13): [True: 1.22k, False: 0]
Branch (381:13): [True: 5, False: 0]
Branch (381:13): [True: 48, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 137, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 706, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 5, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 290, False: 0]
Branch (381:13): [True: 67, False: 0]
Branch (381:13): [True: 270, False: 0]
Branch (381:13): [True: 13, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 15, False: 0]
Branch (381:13): [True: 13, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 7, False: 0]
Branch (381:13): [True: 13, False: 0]
Branch (381:13): [True: 7, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 5, False: 0]
Branch (381:13): [True: 2.63k, False: 0]
Branch (381:13): [True: 83, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 5, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 5, False: 0]
Branch (381:13): [True: 30, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 30, False: 0]
Branch (381:13): [True: 3.24k, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 6, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 6, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 5, False: 0]
Branch (381:13): [True: 5, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 45, False: 0]
Branch (381:13): [True: 218, False: 0]
Branch (381:13): [True: 76, False: 0]
Branch (381:13): [True: 122, False: 0]
Branch (381:13): [True: 34, False: 0]
Branch (381:13): [True: 1.01k, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 13, False: 0]
Branch (381:13): [True: 12, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 18, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 1.02k, False: 0]
Branch (381:13): [True: 13, False: 0]
Branch (381:13): [True: 18, False: 0]
Branch (381:13): [True: 27, False: 0]
Branch (381:13): [True: 17, False: 0]
Branch (381:13): [True: 34, False: 0]
Branch (381:13): [True: 224, False: 0]
Branch (381:13): [True: 20, False: 0]
Branch (381:13): [True: 36, False: 0]
Branch (381:13): [True: 28, False: 0]
Branch (381:13): [True: 24, False: 0]
Branch (381:13): [True: 17, False: 0]
Branch (381:13): [True: 37, False: 0]
Branch (381:13): [True: 26, False: 0]
Branch (381:13): [True: 30, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 18, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 9, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 9, False: 0]
Branch (381:13): [True: 15, False: 0]
Branch (381:13): [True: 19, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 24, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 10, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [Folded - Ignored]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 12, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 8, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 8, False: 0]
Branch (381:13): [True: 9, False: 0]
Branch (381:13): [True: 11, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 59, False: 0]
Branch (381:13): [True: 41, False: 0]
Branch (381:13): [True: 72, False: 0]
Branch (381:13): [True: 59, False: 0]
Branch (381:13): [True: 298, False: 0]
Branch (381:13): [True: 61, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 44, False: 0]
Branch (381:13): [True: 71, False: 0]
Branch (381:13): [True: 13, False: 0]
Branch (381:13): [True: 13, False: 0]
Branch (381:13): [True: 43, False: 0]
Branch (381:13): [True: 385, False: 0]
Branch (381:13): [True: 41, False: 0]
Branch (381:13): [True: 21, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 50, False: 0]
Branch (381:13): [True: 33, False: 0]
Branch (381:13): [True: 62, False: 0]
Branch (381:13): [True: 18, False: 0]
Branch (381:13): [True: 12, False: 0]
Branch (381:13): [True: 21, False: 0]
Branch (381:13): [True: 40, False: 0]
Branch (381:13): [True: 48, False: 0]
Branch (381:13): [True: 47, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 27, False: 0]
Branch (381:13): [True: 27, False: 0]
Branch (381:13): [True: 118, False: 0]
Branch (381:13): [True: 51, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 26, False: 0]
Branch (381:13): [True: 7, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 5, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 24, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 24, False: 0]
Branch (381:13): [True: 24, False: 0]
Branch (381:13): [True: 24, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 24, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 502, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 993, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 5, False: 0]
Branch (381:13): [True: 5, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 6, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 6, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 5, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 5, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 0, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 5, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 6, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 5, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 75, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 3, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 4, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 2, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
Branch (381:13): [True: 1, False: 0]
|
382 | | // Useful to get tracing stack trace. |
383 | 0 | tracing::error!("Expected context to be set"); |
384 | 0 | panic!("Expected context to be set"); |
385 | | }; |
386 | 16.4k | let enter = ctx.enter(); |
387 | 16.4k | // Since `inner` is only moved when the future itself is dropped, `inner` will |
388 | 16.4k | // never move, so this should be safe. |
389 | 16.4k | // see: https://docs.rs/tracing/0.1.40/src/tracing/instrument.rs.html#297 |
390 | 16.4k | let inner = unsafe { this.inner.map_unchecked_mut(|v| &mut **v) }; |
391 | 16.4k | let result = inner.poll(cx); |
392 | 16.4k | assert!( |
393 | 16.4k | this.context.replace(enter.release()).is_none(), |
394 | 0 | "Expected context to be unset" |
395 | | ); |
396 | 16.4k | result |
397 | 16.4k | } |
398 | | } |