@@ -78,9 +78,11 @@ thread_local! {
7878pub struct Context {
7979 #[ cfg( feature = "trace" ) ]
8080 pub ( super ) span : Option < Arc < SynchronizedSpan > > ,
81- entries : HashMap < TypeId , Arc < dyn Any + Sync + Send > , BuildHasherDefault < IdHasher > > ,
81+ entries : Option < Arc < EntryMap > > ,
8282}
8383
84+ type EntryMap = HashMap < TypeId , Arc < dyn Any + Sync + Send > , BuildHasherDefault < IdHasher > > ;
85+
8486impl Context {
8587 /// Creates an empty `Context`.
8688 ///
@@ -152,12 +154,7 @@ impl Context {
152154 /// assert_eq!(all_current_and_b.get::<ValueB>(), Some(&ValueB(42)));
153155 /// ```
154156 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+ Context :: map_current ( |cx| cx. with_value ( value) )
161158 }
162159
163160 /// Returns a reference to the entry for the corresponding value type.
@@ -182,9 +179,13 @@ impl Context {
182179 /// assert_eq!(cx.get::<MyUser>(), None);
183180 /// ```
184181 pub fn get < T : ' static > ( & self ) -> Option < & T > {
185- self . entries
186- . get ( & TypeId :: of :: < T > ( ) )
187- . and_then ( |rc| rc. downcast_ref ( ) )
182+ if let Some ( entries) = & self . entries {
183+ entries
184+ . get ( & TypeId :: of :: < T > ( ) )
185+ . and_then ( |rc| rc. downcast_ref ( ) )
186+ } else {
187+ None
188+ }
188189 }
189190
190191 /// Returns a copy of the context with the new value included.
@@ -215,12 +216,20 @@ impl Context {
215216 /// assert_eq!(cx_with_a_and_b.get::<ValueB>(), Some(&ValueB(42)));
216217 /// ```
217218 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
219+ let entries = if let Some ( current_entries) = & self . entries {
220+ let mut inner_entries = ( * * current_entries) . clone ( ) ;
221+ inner_entries. insert ( TypeId :: of :: < T > ( ) , Arc :: new ( value) ) ;
222+ Some ( Arc :: new ( inner_entries) )
223+ } else {
224+ let mut entries = EntryMap :: default ( ) ;
225+ entries. insert ( TypeId :: of :: < T > ( ) , Arc :: new ( value) ) ;
226+ Some ( Arc :: new ( entries) )
227+ } ;
228+ Context {
229+ entries,
230+ #[ cfg( feature = "trace" ) ]
231+ span : self . span . clone ( ) ,
232+ }
224233 }
225234
226235 /// Replaces the current context on this thread with this context.
@@ -326,7 +335,7 @@ impl Context {
326335impl fmt:: Debug for Context {
327336 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
328337 let mut dbg = f. debug_struct ( "Context" ) ;
329- let mut entries = self . entries . len ( ) ;
338+ let mut entries = self . entries . as_ref ( ) . map_or ( 0 , |e| e . len ( ) ) ;
330339 #[ cfg( feature = "trace" ) ]
331340 {
332341 if let Some ( span) = & self . span {
0 commit comments