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