@@ -79,9 +79,11 @@ thread_local! {
7979pub struct Context {
8080 #[ cfg( feature = "trace" ) ]
8181 pub ( super ) span : Option < Arc < SynchronizedSpan > > ,
82- entries : HashMap < TypeId , Arc < dyn Any + Sync + Send > , BuildHasherDefault < IdHasher > > ,
82+ entries : Option < Arc < EntryMap > > ,
8383}
8484
85+ type EntryMap = HashMap < TypeId , Arc < dyn Any + Sync + Send > , BuildHasherDefault < IdHasher > > ;
86+
8587impl Context {
8688 /// Creates an empty `Context`.
8789 ///
@@ -111,7 +113,7 @@ impl Context {
111113 /// do_work()
112114 /// ```
113115 pub fn current ( ) -> Self {
114- Context :: map_current ( |cx| cx. clone ( ) )
116+ Self :: map_current ( |cx| cx. clone ( ) )
115117 }
116118
117119 /// Applies a function to the current context returning its value.
@@ -153,12 +155,7 @@ impl Context {
153155 /// assert_eq!(all_current_and_b.get::<ValueB>(), Some(&ValueB(42)));
154156 /// ```
155157 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) )
162159 }
163160
164161 /// Returns a reference to the entry for the corresponding value type.
@@ -184,8 +181,9 @@ impl Context {
184181 /// ```
185182 pub fn get < T : ' static > ( & self ) -> Option < & T > {
186183 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 ( )
189187 }
190188
191189 /// Returns a copy of the context with the new value included.
@@ -216,12 +214,20 @@ impl Context {
216214 /// assert_eq!(cx_with_a_and_b.get::<ValueB>(), Some(&ValueB(42)));
217215 /// ```
218216 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+ }
225231 }
226232
227233 /// Replaces the current context on this thread with this context.
@@ -327,7 +333,7 @@ impl Context {
327333impl fmt:: Debug for Context {
328334 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
329335 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 ( ) ) ;
331337 #[ cfg( feature = "trace" ) ]
332338 {
333339 if let Some ( span) = & self . span {
0 commit comments