@@ -79,9 +79,11 @@ thread_local! {
79
79
pub struct Context {
80
80
#[ cfg( feature = "trace" ) ]
81
81
pub ( super ) span : Option < Arc < SynchronizedSpan > > ,
82
- entries : HashMap < TypeId , Arc < dyn Any + Sync + Send > , BuildHasherDefault < IdHasher > > ,
82
+ entries : Option < Arc < EntryMap > > ,
83
83
}
84
84
85
+ type EntryMap = HashMap < TypeId , Arc < dyn Any + Sync + Send > , BuildHasherDefault < IdHasher > > ;
86
+
85
87
impl Context {
86
88
/// Creates an empty `Context`.
87
89
///
@@ -111,7 +113,7 @@ impl Context {
111
113
/// do_work()
112
114
/// ```
113
115
pub fn current ( ) -> Self {
114
- Context :: map_current ( |cx| cx. clone ( ) )
116
+ Self :: map_current ( |cx| cx. clone ( ) )
115
117
}
116
118
117
119
/// Applies a function to the current context returning its value.
@@ -153,12 +155,7 @@ impl Context {
153
155
/// assert_eq!(all_current_and_b.get::<ValueB>(), Some(&ValueB(42)));
154
156
/// ```
155
157
pub fn current_with_value < T : ' static + Send + Sync > ( value : T ) -> Self {
156
- let mut new_context = Context :: current ( ) ;
157
- new_context
158
- . entries
159
- . insert ( TypeId :: of :: < T > ( ) , Arc :: new ( value) ) ;
160
-
161
- new_context
158
+ Self :: map_current ( |cx| cx. with_value ( value) )
162
159
}
163
160
164
161
/// Returns a reference to the entry for the corresponding value type.
@@ -184,8 +181,9 @@ impl Context {
184
181
/// ```
185
182
pub fn get < T : ' static > ( & self ) -> Option < & T > {
186
183
self . entries
187
- . get ( & TypeId :: of :: < T > ( ) )
188
- . and_then ( |rc| rc. downcast_ref ( ) )
184
+ . as_ref ( ) ?
185
+ . get ( & TypeId :: of :: < T > ( ) ) ?
186
+ . downcast_ref ( )
189
187
}
190
188
191
189
/// Returns a copy of the context with the new value included.
@@ -216,12 +214,20 @@ impl Context {
216
214
/// assert_eq!(cx_with_a_and_b.get::<ValueB>(), Some(&ValueB(42)));
217
215
/// ```
218
216
pub fn with_value < T : ' static + Send + Sync > ( & self , value : T ) -> Self {
219
- let mut new_context = self . clone ( ) ;
220
- new_context
221
- . entries
222
- . insert ( TypeId :: of :: < T > ( ) , Arc :: new ( value) ) ;
223
-
224
- new_context
217
+ let entries = if let Some ( current_entries) = & self . entries {
218
+ let mut inner_entries = ( * * current_entries) . clone ( ) ;
219
+ inner_entries. insert ( TypeId :: of :: < T > ( ) , Arc :: new ( value) ) ;
220
+ Some ( Arc :: new ( inner_entries) )
221
+ } else {
222
+ let mut entries = EntryMap :: default ( ) ;
223
+ entries. insert ( TypeId :: of :: < T > ( ) , Arc :: new ( value) ) ;
224
+ Some ( Arc :: new ( entries) )
225
+ } ;
226
+ Context {
227
+ entries,
228
+ #[ cfg( feature = "trace" ) ]
229
+ span : self . span . clone ( ) ,
230
+ }
225
231
}
226
232
227
233
/// Replaces the current context on this thread with this context.
@@ -327,7 +333,7 @@ impl Context {
327
333
impl fmt:: Debug for Context {
328
334
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
329
335
let mut dbg = f. debug_struct ( "Context" ) ;
330
- let mut entries = self . entries . len ( ) ;
336
+ let mut entries = self . entries . as_ref ( ) . map_or ( 0 , |e| e . len ( ) ) ;
331
337
#[ cfg( feature = "trace" ) ]
332
338
{
333
339
if let Some ( span) = & self . span {
0 commit comments