• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc;
18 
19 import io.grpc.Context.CheckReturnValue;
20 import io.grpc.PersistentHashArrayMappedTrie.Node;
21 import java.io.Closeable;
22 import java.util.ArrayList;
23 import java.util.concurrent.Callable;
24 import java.util.concurrent.Executor;
25 import java.util.concurrent.ScheduledExecutorService;
26 import java.util.concurrent.ScheduledFuture;
27 import java.util.concurrent.TimeUnit;
28 import java.util.concurrent.TimeoutException;
29 import java.util.concurrent.atomic.AtomicReference;
30 import java.util.logging.Level;
31 import java.util.logging.Logger;
32 
33 /**
34  * A context propagation mechanism which can carry scoped-values across API boundaries and between
35  * threads. Examples of state propagated via context include:
36  * <ul>
37  *   <li>Security principals and credentials.</li>
38  *   <li>Local and distributed tracing information.</li>
39  * </ul>
40  *
41  * <p>A Context object can be {@link #attach attached} to the {@link Storage}, which effectively
42  * forms a <b>scope</b> for the context.  The scope is bound to the current thread.  Within a scope,
43  * its Context is accessible even across API boundaries, through {@link #current}.  The scope is
44  * later exited by {@link #detach detaching} the Context.
45  *
46  * <p>Context objects are immutable and inherit state from their parent. To add or overwrite the
47  * current state a new context object must be created and then attached, replacing the previously
48  * bound context. For example:
49  *
50  * <pre>
51  *   Context withCredential = Context.current().withValue(CRED_KEY, cred);
52  *   withCredential.run(new Runnable() {
53  *     public void run() {
54  *        readUserRecords(userId, CRED_KEY.get());
55  *     }
56  *   });
57  * </pre>
58  *
59  * <p>Contexts are also used to represent a scoped unit of work. When the unit of work is done the
60  * context must be cancelled. This cancellation will cascade to all descendant contexts. You can
61  * add a {@link CancellationListener} to a context to be notified when it or one of its ancestors
62  * has been cancelled. Cancellation does not release the state stored by a context and it's
63  * perfectly valid to {@link #attach()} an already cancelled context to make it current. To cancel a
64  * context (and its descendants) you first create a {@link CancellableContext} and when you need to
65  * signal cancellation call {@link CancellableContext#cancel} or {@link
66  * CancellableContext#detachAndCancel}.
67  *
68  * <p>Contexts can also be created with a timeout relative to the system nano clock which will
69  * cause it to automatically cancel at the desired time.
70  *
71  *
72  * <p>Notes and cautions on use:
73  * <ul>
74  *    <li>Every {@code attach()} should have a {@code detach()} in the same method. And every
75  * CancellableContext should be cancelled at some point. Breaking these rules may lead to memory
76  * leaks.
77  *    <li>While Context objects are immutable they do not place such a restriction on the state
78  * they store.</li>
79  *    <li>Context is not intended for passing optional parameters to an API and developers should
80  * take care to avoid excessive dependence on context when designing an API.</li>
81  *    <li>Do not mock this class.  Use {@link #ROOT} for a non-null instance.
82  * </ul>
83  */
84 /* @DoNotMock("Use ROOT for a non-null Context") // commented out to avoid dependencies  */
85 @CheckReturnValue
86 public class Context {
87 
88   static final Logger log = Logger.getLogger(Context.class.getName());
89 
90   // Long chains of contexts are suspicious and usually indicate a misuse of Context.
91   // The threshold is arbitrarily chosen.
92   // VisibleForTesting
93   static final int CONTEXT_DEPTH_WARN_THRESH = 1000;
94 
95   /**
96    * The logical root context which is the ultimate ancestor of all contexts. This context
97    * is not cancellable and so will not cascade cancellation or retain listeners.
98    *
99    * <p>Never assume this is the default context for new threads, because {@link Storage} may define
100    * a default context that is different from ROOT.
101    */
102   public static final Context ROOT = new Context();
103 
104   // Visible For testing
storage()105   static Storage storage() {
106     return LazyStorage.storage;
107   }
108 
109   // Lazy-loaded storage. Delaying storage initialization until after class initialization makes it
110   // much easier to avoid circular loading since there can still be references to Context as long as
111   // they don't depend on storage, like key() and currentContextExecutor(). It also makes it easier
112   // to handle exceptions.
113   private static final class LazyStorage {
114     static final Storage storage;
115 
116     static {
117       AtomicReference<Throwable> deferredStorageFailure = new AtomicReference<>();
118       storage = createStorage(deferredStorageFailure);
119       Throwable failure = deferredStorageFailure.get();
120       // Logging must happen after storage has been set, as loggers may use Context.
121       if (failure != null) {
log.log(Level.FINE, "Storage override doesn't exist. Using default", failure)122         log.log(Level.FINE, "Storage override doesn't exist. Using default", failure);
123       }
124     }
125 
createStorage( AtomicReference<? super ClassNotFoundException> deferredStorageFailure)126     private static Storage createStorage(
127         AtomicReference<? super ClassNotFoundException> deferredStorageFailure) {
128       try {
129         Class<?> clazz = Class.forName("io.grpc.override.ContextStorageOverride");
130         // The override's constructor is prohibited from triggering any code that can loop back to
131         // Context
132         return clazz.asSubclass(Storage.class).getConstructor().newInstance();
133       } catch (ClassNotFoundException e) {
134         deferredStorageFailure.set(e);
135         return new ThreadLocalContextStorage();
136       } catch (Exception e) {
137         throw new RuntimeException("Storage override failed to initialize", e);
138       }
139     }
140   }
141 
142   /**
143    * Create a {@link Key} with the given debug name.
144    *
145    * @param debugString a name intended for debugging purposes and does not impact behavior.
146    *                    Multiple different keys may have the same debugString.
147    *                    The value should be not null.
148    */
key(String debugString)149   public static <T> Key<T> key(String debugString) {
150     return new Key<>(debugString);
151   }
152 
153   /**
154    * Create a {@link Key} with the given debug name and default value.
155    *
156    * @param debugString a name intended for debugging purposes and does not impact behavior.
157    *                    Multiple different keys may have the same debugString.
158    *                    The value should be not null.
159    */
keyWithDefault(String debugString, T defaultValue)160   public static <T> Key<T> keyWithDefault(String debugString, T defaultValue) {
161     return new Key<>(debugString, defaultValue);
162   }
163 
164   /**
165    * Return the context associated with the current scope, will never return {@code null}.
166    *
167    * <p>Will never return {@link CancellableContext} even if one is attached, instead a
168    * {@link Context} is returned with the same properties and lifetime. This is to avoid
169    * code stealing the ability to cancel arbitrarily.
170    */
current()171   public static Context current() {
172     Context current = storage().current();
173     if (current == null) {
174       return ROOT;
175     }
176     return current;
177   }
178 
179   final CancellableContext cancellableAncestor;
180   final Node<Key<?>, Object> keyValueEntries;
181   // The number parents between this context and the root context.
182   final int generation;
183 
184   /**
185    * Construct a context that cannot be cancelled and will not cascade cancellation from its parent.
186    */
Context(Node<Key<?>, Object> keyValueEntries, int generation)187   private Context(Node<Key<?>, Object> keyValueEntries, int generation) {
188     this.cancellableAncestor = null;
189     this.keyValueEntries = keyValueEntries;
190     this.generation = generation;
191     validateGeneration(generation);
192   }
193 
194   /**
195    * Construct a context that cannot be cancelled but will cascade cancellation from its parent if
196    * it is cancellable.
197    */
Context(Context parent, Node<Key<?>, Object> keyValueEntries)198   private Context(Context parent, Node<Key<?>, Object> keyValueEntries) {
199     this.cancellableAncestor = cancellableAncestor(parent);
200     this.keyValueEntries = keyValueEntries;
201     this.generation = parent.generation + 1;
202     validateGeneration(generation);
203   }
204 
205   /**
206    * Construct for {@link #ROOT}.
207    */
Context()208   private Context() {
209     this.cancellableAncestor = null;
210     this.keyValueEntries = null;
211     this.generation = 0;
212     validateGeneration(generation);
213   }
214 
215   /**
216    * Create a new context which is independently cancellable and also cascades cancellation from
217    * its parent. Callers <em>must</em> ensure that either {@link
218    * CancellableContext#cancel(Throwable)} or {@link CancellableContext#detachAndCancel(Context,
219    * Throwable)} are called at a later point, in order to allow this context to be garbage
220    * collected.
221    *
222    * <p>Sample usage:
223    * <pre>
224    *   Context.CancellableContext withCancellation = Context.current().withCancellation();
225    *   try {
226    *     withCancellation.run(new Runnable() {
227    *       public void run() {
228    *         Context current = Context.current();
229    *         while (!current.isCancelled()) {
230    *           keepWorking();
231    *         }
232    *       }
233    *     });
234    *   } finally {
235    *     withCancellation.cancel(null);
236    *   }
237    * </pre>
238    */
withCancellation()239   public CancellableContext withCancellation() {
240     return new CancellableContext(this);
241   }
242 
243   /**
244    * Create a new context which will cancel itself after the given {@code duration} from now.
245    * The returned context will cascade cancellation of its parent. Callers may explicitly cancel
246    * the returned context prior to the deadline just as for {@link #withCancellation()}. If the unit
247    * of work completes before the deadline, the context should be explicitly cancelled to allow
248    * it to be garbage collected.
249    *
250    * <p>Sample usage:
251    * <pre>
252    *   Context.CancellableContext withDeadline = Context.current()
253    *       .withDeadlineAfter(5, TimeUnit.SECONDS, scheduler);
254    *   try {
255    *     withDeadline.run(new Runnable() {
256    *       public void run() {
257    *         Context current = Context.current();
258    *         while (!current.isCancelled()) {
259    *           keepWorking();
260    *         }
261    *       }
262    *     });
263    *   } finally {
264    *     withDeadline.cancel(null);
265    *   }
266    * </pre>
267    */
withDeadlineAfter(long duration, TimeUnit unit, ScheduledExecutorService scheduler)268   public CancellableContext withDeadlineAfter(long duration, TimeUnit unit,
269                                               ScheduledExecutorService scheduler) {
270     return withDeadline(Deadline.after(duration, unit), scheduler);
271   }
272 
273   /**
274    * Create a new context which will cancel itself at the given {@link Deadline}.
275    * The returned context will cascade cancellation of its parent. Callers may explicitly cancel
276    * the returned context prior to the deadline just as for {@link #withCancellation()}. If the unit
277    * of work completes before the deadline, the context should be explicitly cancelled to allow
278    * it to be garbage collected.
279    *
280    * <p>Sample usage:
281    * <pre>
282    *   Context.CancellableContext withDeadline = Context.current()
283    *      .withDeadline(someReceivedDeadline, scheduler);
284    *   try {
285    *     withDeadline.run(new Runnable() {
286    *       public void run() {
287    *         Context current = Context.current();
288    *         while (!current.isCancelled() &amp;&amp; moreWorkToDo()) {
289    *           keepWorking();
290    *         }
291    *       }
292    *     });
293    *   } finally {
294    *     withDeadline.cancel(null);
295    *   }
296    * </pre>
297    */
withDeadline(Deadline newDeadline, ScheduledExecutorService scheduler)298   public CancellableContext withDeadline(Deadline newDeadline, ScheduledExecutorService scheduler) {
299     checkNotNull(newDeadline, "deadline");
300     checkNotNull(scheduler, "scheduler");
301     Deadline existingDeadline = getDeadline();
302     boolean scheduleDeadlineCancellation = true;
303     if (existingDeadline != null && existingDeadline.compareTo(newDeadline) <= 0) {
304       // The new deadline won't have an effect, so ignore it
305       newDeadline = existingDeadline;
306       scheduleDeadlineCancellation = false;
307     }
308     CancellableContext newCtx = new CancellableContext(this, newDeadline);
309     if (scheduleDeadlineCancellation) {
310       newCtx.setUpDeadlineCancellation(newDeadline, scheduler);
311     }
312     return newCtx;
313   }
314 
315   /**
316    * Create a new context with the given key value set. The new context will cascade cancellation
317    * from its parent.
318    *
319    <pre>
320    *   Context withCredential = Context.current().withValue(CRED_KEY, cred);
321    *   withCredential.run(new Runnable() {
322    *     public void run() {
323    *        readUserRecords(userId, CRED_KEY.get());
324    *     }
325    *   });
326    * </pre>
327    *
328    * <p>Note that multiple calls to {@link #withValue} can be chained together.
329    * That is,
330    *
331    * <pre>
332    * context.withValues(K1, V1, K2, V2);
333    * // is the same as
334    * context.withValue(K1, V1).withValue(K2, V2);
335    * </pre>
336    *
337    * <p>Nonetheless, {@link Context} should not be treated like a general purpose
338    * map with a large number of keys and values — combine multiple related items
339    * together into a single key instead of separating them. But if the items
340    * are unrelated, have separate keys for them.
341    */
withValue(Key<V> k1, V v1)342   public <V> Context withValue(Key<V> k1, V v1) {
343     Node<Key<?>, Object> newKeyValueEntries =
344         PersistentHashArrayMappedTrie.put(keyValueEntries, k1, v1);
345     return new Context(this, newKeyValueEntries);
346   }
347 
348   /**
349    * Create a new context with the given key value set. The new context will cascade cancellation
350    * from its parent.
351    */
withValues(Key<V1> k1, V1 v1, Key<V2> k2, V2 v2)352   public <V1, V2> Context withValues(Key<V1> k1, V1 v1, Key<V2> k2, V2 v2) {
353     Node<Key<?>, Object> newKeyValueEntries =
354         PersistentHashArrayMappedTrie.put(keyValueEntries, k1, v1);
355     newKeyValueEntries = PersistentHashArrayMappedTrie.put(newKeyValueEntries, k2, v2);
356     return new Context(this, newKeyValueEntries);
357   }
358 
359   /**
360    * Create a new context with the given key value set. The new context will cascade cancellation
361    * from its parent.
362    */
withValues(Key<V1> k1, V1 v1, Key<V2> k2, V2 v2, Key<V3> k3, V3 v3)363   public <V1, V2, V3> Context withValues(Key<V1> k1, V1 v1, Key<V2> k2, V2 v2, Key<V3> k3, V3 v3) {
364     Node<Key<?>, Object> newKeyValueEntries =
365         PersistentHashArrayMappedTrie.put(keyValueEntries, k1, v1);
366     newKeyValueEntries = PersistentHashArrayMappedTrie.put(newKeyValueEntries, k2, v2);
367     newKeyValueEntries = PersistentHashArrayMappedTrie.put(newKeyValueEntries, k3, v3);
368     return new Context(this, newKeyValueEntries);
369   }
370 
371   /**
372    * Create a new context with the given key value set. The new context will cascade cancellation
373    * from its parent.
374    *
375    * <p>For more than 4 key-value pairs, note that multiple calls to
376    * {@link #withValue} can be chained together. That is,
377    *
378    * <pre>
379    * context.withValues(K1, V1, K2, V2);
380    * // is the same as
381    * context.withValue(K1, V1).withValue(K2, V2);
382    * </pre>
383    *
384    * <p>Nonetheless, {@link Context} should not be treated like a general purpose
385    * map with a large number of keys and values — combine multiple related items
386    * together into a single key instead of separating them. But if the items
387    * are unrelated, have separate keys for them.
388    */
withValues(Key<V1> k1, V1 v1, Key<V2> k2, V2 v2, Key<V3> k3, V3 v3, Key<V4> k4, V4 v4)389   public <V1, V2, V3, V4> Context withValues(Key<V1> k1, V1 v1, Key<V2> k2, V2 v2,
390       Key<V3> k3, V3 v3, Key<V4> k4, V4 v4) {
391     Node<Key<?>, Object> newKeyValueEntries =
392         PersistentHashArrayMappedTrie.put(keyValueEntries, k1, v1);
393     newKeyValueEntries = PersistentHashArrayMappedTrie.put(newKeyValueEntries, k2, v2);
394     newKeyValueEntries = PersistentHashArrayMappedTrie.put(newKeyValueEntries, k3, v3);
395     newKeyValueEntries = PersistentHashArrayMappedTrie.put(newKeyValueEntries, k4, v4);
396     return new Context(this, newKeyValueEntries);
397   }
398 
399   /**
400    * Create a new context which propagates the values of this context but does not cascade its
401    * cancellation.
402    */
fork()403   public Context fork() {
404     return new Context(keyValueEntries, generation + 1);
405   }
406 
407   /**
408    * Attach this context, thus enter a new scope within which this context is {@link #current}.  The
409    * previously current context is returned. It is allowed to attach contexts where {@link
410    * #isCancelled()} is {@code true}.
411    *
412    * <p>Instead of using {@code attach()} and {@link #detach(Context)} most use-cases are better
413    * served by using the {@link #run(Runnable)} or {@link #call(java.util.concurrent.Callable)} to
414    * execute work immediately within a context's scope. If work needs to be done in other threads it
415    * is recommended to use the 'wrap' methods or to use a propagating executor.
416    *
417    * <p>All calls to {@code attach()} should have a corresponding {@link #detach(Context)} within
418    * the same method:
419    * <pre>{@code Context previous = someContext.attach();
420    * try {
421    *   // Do work
422    * } finally {
423    *   someContext.detach(previous);
424    * }}</pre>
425    */
attach()426   public Context attach() {
427     Context prev = storage().doAttach(this);
428     if (prev == null) {
429       return ROOT;
430     }
431     return prev;
432   }
433 
434   /**
435    * Reverse an {@code attach()}, restoring the previous context and exiting the current scope.
436    *
437    * <p>This context should be the same context that was previously {@link #attach attached}.  The
438    * provided replacement should be what was returned by the same {@link #attach attach()} call.  If
439    * an {@code attach()} and a {@code detach()} meet above requirements, they match.
440    *
441    * <p>It is expected that between any pair of matching {@code attach()} and {@code detach()}, all
442    * {@code attach()}es and {@code detach()}es are called in matching pairs.  If this method finds
443    * that this context is not {@link #current current}, either you or some code in-between are not
444    * detaching correctly, and a SEVERE message will be logged but the context to attach will still
445    * be bound.  <strong>Never</strong> use {@code Context.current().detach()}, as this will
446    * compromise this error-detecting mechanism.
447    */
detach(Context toAttach)448   public void detach(Context toAttach) {
449     checkNotNull(toAttach, "toAttach");
450     storage().detach(this, toAttach);
451   }
452 
453   // Visible for testing
isCurrent()454   boolean isCurrent() {
455     return current() == this;
456   }
457 
458   /**
459    * Is this context cancelled.
460    */
isCancelled()461   public boolean isCancelled() {
462     if (cancellableAncestor == null) {
463       return false;
464     } else {
465       return cancellableAncestor.isCancelled();
466     }
467   }
468 
469   /**
470    * If a context {@link #isCancelled()} then return the cause of the cancellation or
471    * {@code null} if context was cancelled without a cause. If the context is not yet cancelled
472    * will always return {@code null}.
473    *
474    * <p>The cancellation cause is provided for informational purposes only and implementations
475    * should generally assume that it has already been handled and logged properly.
476    */
cancellationCause()477   public Throwable cancellationCause() {
478     if (cancellableAncestor == null) {
479       return null;
480     } else {
481       return cancellableAncestor.cancellationCause();
482     }
483   }
484 
485   /**
486    * A context may have an associated {@link Deadline} at which it will be automatically cancelled.
487    * @return A {@link io.grpc.Deadline} or {@code null} if no deadline is set.
488    */
getDeadline()489   public Deadline getDeadline() {
490     if (cancellableAncestor == null) {
491       return null;
492     }
493     return cancellableAncestor.getDeadline();
494   }
495 
496   /**
497    * Add a listener that will be notified when the context becomes cancelled.
498    */
addListener(final CancellationListener cancellationListener, final Executor executor)499   public void addListener(final CancellationListener cancellationListener,
500                           final Executor executor) {
501     checkNotNull(cancellationListener, "cancellationListener");
502     checkNotNull(executor, "executor");
503     if (cancellableAncestor == null) {
504       return;
505     }
506     cancellableAncestor.addListenerInternal(
507         new ExecutableListener(executor, cancellationListener, this));
508   }
509 
510   /**
511    * Remove a {@link CancellationListener}.
512    */
removeListener(CancellationListener cancellationListener)513   public void removeListener(CancellationListener cancellationListener) {
514     if (cancellableAncestor == null) {
515       return;
516     }
517     cancellableAncestor.removeListenerInternal(cancellationListener, this);
518   }
519 
520   // Used in tests to ensure that listeners are defined and released when cancellation cascades.
521   // It's very important to ensure that we do not accidentally retain listeners.
listenerCount()522   int listenerCount() {
523     if (cancellableAncestor == null) {
524       return 0;
525     }
526     return cancellableAncestor.listenerCount();
527   }
528 
529   /**
530    * Immediately run a {@link Runnable} with this context as the {@link #current} context.
531    * @param r {@link Runnable} to run.
532    */
run(Runnable r)533   public void run(Runnable r) {
534     Context previous = attach();
535     try {
536       r.run();
537     } finally {
538       detach(previous);
539     }
540   }
541 
542   /**
543    * Immediately call a {@link Callable} with this context as the {@link #current} context.
544    * @param c {@link Callable} to call.
545    * @return result of call.
546    */
547   @CanIgnoreReturnValue
call(Callable<V> c)548   public <V> V call(Callable<V> c) throws Exception {
549     Context previous = attach();
550     try {
551       return c.call();
552     } finally {
553       detach(previous);
554     }
555   }
556 
557   /**
558    * Wrap a {@link Runnable} so that it executes with this context as the {@link #current} context.
559    */
wrap(final Runnable r)560   public Runnable wrap(final Runnable r) {
561     return new Runnable() {
562       @Override
563       public void run() {
564         Context previous = attach();
565         try {
566           r.run();
567         } finally {
568           detach(previous);
569         }
570       }
571     };
572   }
573 
574   /**
575    * Wrap a {@link Callable} so that it executes with this context as the {@link #current} context.
576    */
577   public <C> Callable<C> wrap(final Callable<C> c) {
578     return new Callable<C>() {
579       @Override
580       public C call() throws Exception {
581         Context previous = attach();
582         try {
583           return c.call();
584         } finally {
585           detach(previous);
586         }
587       }
588     };
589   }
590 
591   /**
592    * Wrap an {@link Executor} so that it always executes with this context as the {@link #current}
593    * context. It is generally expected that {@link #currentContextExecutor(Executor)} would be
594    * used more commonly than this method.
595    *
596    * <p>One scenario in which this executor may be useful is when a single thread is sharding work
597    * to multiple threads.
598    *
599    * @see #currentContextExecutor(Executor)
600    */
601   public Executor fixedContextExecutor(final Executor e) {
602     final class FixedContextExecutor implements Executor {
603       @Override
604       public void execute(Runnable r) {
605         e.execute(wrap(r));
606       }
607     }
608 
609     return new FixedContextExecutor();
610   }
611 
612   /**
613    * Create an executor that propagates the {@link #current} context when {@link Executor#execute}
614    * is called as the {@link #current} context of the {@code Runnable} scheduled. <em>Note that this
615    * is a static method.</em>
616    *
617    * @see #fixedContextExecutor(Executor)
618    */
619   public static Executor currentContextExecutor(final Executor e) {
620     final class CurrentContextExecutor implements Executor {
621       @Override
622       public void execute(Runnable r) {
623         e.execute(Context.current().wrap(r));
624       }
625     }
626 
627     return new CurrentContextExecutor();
628   }
629 
630   /**
631    * A context which inherits cancellation from its parent but which can also be independently
632    * cancelled and which will propagate cancellation to its descendants. To avoid leaking memory,
633    * every CancellableContext must have a defined lifetime, after which it is guaranteed to be
634    * cancelled.
635    *
636    * <p>This class must be cancelled by either calling {@link #close} or {@link #cancel}.
637    * {@link #close} is equivalent to calling {@code cancel(null)}. It is safe to call the methods
638    * more than once, but only the first call will have any effect. Because it's safe to call the
639    * methods multiple times, users are encouraged to always call {@link #close} at the end of
640    * the operation, and disregard whether {@link #cancel} was already called somewhere else.
641    *
642    * <p>Blocking code can use the try-with-resources idiom:
643    * <pre>
644    * try (CancellableContext c = Context.current()
645    *     .withDeadlineAfter(100, TimeUnit.MILLISECONDS, executor)) {
646    *   Context toRestore = c.attach();
647    *   try {
648    *     // do some blocking work
649    *   } finally {
650    *     c.detach(toRestore);
651    *   }
652    * }</pre>
653    *
654    * <p>Asynchronous code will have to manually track the end of the CancellableContext's lifetime,
655    * and cancel the context at the appropriate time.
656    */
657   public static final class CancellableContext extends Context implements Closeable {
658 
659     private final Deadline deadline;
660     private final Context uncancellableSurrogate;
661 
662     private ArrayList<ExecutableListener> listeners;
663     // parentListener is initialized when listeners is initialized (only if there is a
664     // cancellable ancestor), and uninitialized when listeners is uninitialized.
665     private CancellationListener parentListener;
666     private Throwable cancellationCause;
667     private ScheduledFuture<?> pendingDeadline;
668     private boolean cancelled;
669 
670     /**
671      * Create a cancellable context that does not have a deadline.
672      */
673     private CancellableContext(Context parent) {
674       super(parent, parent.keyValueEntries);
675       deadline = parent.getDeadline();
676       // Create a surrogate that inherits from this to attach so that you cannot retrieve a
677       // cancellable context from Context.current()
678       uncancellableSurrogate = new Context(this, keyValueEntries);
679     }
680 
681     /**
682      * Create a cancellable context that has a deadline.
683      */
684     private CancellableContext(Context parent, Deadline deadline) {
685       super(parent, parent.keyValueEntries);
686       this.deadline = deadline;
687       this.uncancellableSurrogate = new Context(this, keyValueEntries);
688     }
689 
690     private void setUpDeadlineCancellation(Deadline deadline, ScheduledExecutorService scheduler) {
691       if (!deadline.isExpired()) {
692         final class CancelOnExpiration implements Runnable {
693           @Override
694           public void run() {
695             try {
696               cancel(new TimeoutException("context timed out"));
697             } catch (Throwable t) {
698               log.log(Level.SEVERE, "Cancel threw an exception, which should not happen", t);
699             }
700           }
701         }
702 
703         synchronized (this) {
704           pendingDeadline = deadline.runOnExpiration(new CancelOnExpiration(), scheduler);
705         }
706       } else {
707         // Cancel immediately if the deadline is already expired.
708         cancel(new TimeoutException("context timed out"));
709       }
710     }
711 
712     @Override
713     public Context attach() {
714       return uncancellableSurrogate.attach();
715     }
716 
717     @Override
718     public void detach(Context toAttach) {
719       uncancellableSurrogate.detach(toAttach);
720     }
721 
722     @Override
723     public void addListener(
724         final CancellationListener cancellationListener, final Executor executor) {
725       checkNotNull(cancellationListener, "cancellationListener");
726       checkNotNull(executor, "executor");
727       addListenerInternal(new ExecutableListener(executor, cancellationListener, this));
728     }
729 
730     private void addListenerInternal(ExecutableListener executableListener) {
731       synchronized (this) {
732         if (isCancelled()) {
733           executableListener.deliver();
734         } else {
735           if (listeners == null) {
736             // Now that we have a listener we need to listen to our parent so
737             // we can cascade listener notification.
738             listeners = new ArrayList<>();
739             listeners.add(executableListener);
740             if (cancellableAncestor != null) {
741               parentListener =
742                   new CancellationListener() {
743                     @Override
744                     public void cancelled(Context context) {
745                       CancellableContext.this.cancel(context.cancellationCause());
746                     }
747                   };
748               cancellableAncestor.addListenerInternal(
749                   new ExecutableListener(DirectExecutor.INSTANCE, parentListener, this));
750             }
751           } else {
752             listeners.add(executableListener);
753           }
754         }
755       }
756     }
757 
758     @Override
759     public void removeListener(CancellationListener cancellationListener) {
760       removeListenerInternal(cancellationListener, this);
761     }
762 
763     private void removeListenerInternal(CancellationListener cancellationListener,
764         Context context) {
765       synchronized (this) {
766         if (listeners != null) {
767           for (int i = listeners.size() - 1; i >= 0; i--) {
768             ExecutableListener executableListener = listeners.get(i);
769             if (executableListener.listener == cancellationListener
770                 && executableListener.context == context) {
771               listeners.remove(i);
772               // Just remove the first matching listener, given that we allow duplicate
773               // adds we should allow for duplicates after remove.
774               break;
775             }
776           }
777           // We have no listeners so no need to listen to our parent
778           if (listeners.isEmpty()) {
779             if (cancellableAncestor != null) {
780               cancellableAncestor.removeListener(parentListener);
781             }
782             parentListener = null;
783             listeners = null;
784           }
785         }
786       }
787     }
788 
789     /**
790      * Returns true if the Context is the current context.
791      *
792      * @deprecated This method violates some GRPC class encapsulation and should not be used.
793      *     If you must know whether a Context is the current context, check whether it is the same
794      *     object returned by {@link Context#current()}.
795      */
796     //TODO(spencerfang): The superclass's method is package-private, so this should really match.
797     @Override
798     @Deprecated
799     public boolean isCurrent() {
800       return uncancellableSurrogate.isCurrent();
801     }
802 
803     /**
804      * Cancel this context and optionally provide a cause (can be {@code null}) for the
805      * cancellation. This will trigger notification of listeners. It is safe to call this method
806      * multiple times. Only the first call will have any effect.
807      *
808      * <p>Calling {@code cancel(null)} is the same as calling {@link #close}.
809      *
810      * @return {@code true} if this context cancelled the context and notified listeners,
811      *    {@code false} if the context was already cancelled.
812      */
813     @CanIgnoreReturnValue
814     public boolean cancel(Throwable cause) {
815       boolean triggeredCancel = false;
816       ScheduledFuture<?> localPendingDeadline = null;
817       synchronized (this) {
818         if (!cancelled) {
819           cancelled = true;
820           if (pendingDeadline != null) {
821             // If we have a scheduled cancellation pending attempt to cancel it.
822             localPendingDeadline = pendingDeadline;
823             pendingDeadline = null;
824           }
825           this.cancellationCause = cause;
826           triggeredCancel = true;
827         }
828       }
829       if (localPendingDeadline != null) {
830         localPendingDeadline.cancel(false);
831       }
832       if (triggeredCancel) {
833         notifyAndClearListeners();
834       }
835       return triggeredCancel;
836     }
837 
838     /**
839      * Notify all listeners that this context has been cancelled and immediately release
840      * any reference to them so that they may be garbage collected.
841      */
842     private void notifyAndClearListeners() {
843       ArrayList<ExecutableListener> tmpListeners;
844       CancellationListener tmpParentListener;
845       synchronized (this) {
846         if (listeners == null) {
847           return;
848         }
849         tmpParentListener = parentListener;
850         parentListener = null;
851         tmpListeners = listeners;
852         listeners = null;
853       }
854       // Deliver events to this context listeners before we notify child contexts. We do this
855       // to cancel higher level units of work before child units. This allows for a better error
856       // handling paradigm where the higher level unit of work knows it is cancelled and so can
857       // ignore errors that bubble up as a result of cancellation of lower level units.
858       for (ExecutableListener tmpListener : tmpListeners) {
859         if (tmpListener.context == this) {
860           tmpListener.deliver();
861         }
862       }
863       for (ExecutableListener tmpListener : tmpListeners) {
864         if (!(tmpListener.context == this)) {
865           tmpListener.deliver();
866         }
867       }
868       if (cancellableAncestor != null) {
869         cancellableAncestor.removeListener(tmpParentListener);
870       }
871     }
872 
873     @Override
874     int listenerCount() {
875       synchronized (this) {
876         return listeners == null ? 0 : listeners.size();
877       }
878     }
879 
880     /**
881      * Cancel this context and detach it as the current context.
882      *
883      * @param toAttach context to make current.
884      * @param cause of cancellation, can be {@code null}.
885      */
886     public void detachAndCancel(Context toAttach, Throwable cause) {
887       try {
888         detach(toAttach);
889       } finally {
890         cancel(cause);
891       }
892     }
893 
894     @Override
895     public boolean isCancelled() {
896       synchronized (this) {
897         if (cancelled) {
898           return true;
899         }
900       }
901       // Detect cancellation of parent in the case where we have no listeners and
902       // record it.
903       if (super.isCancelled()) {
904         cancel(super.cancellationCause());
905         return true;
906       }
907       return false;
908     }
909 
910     @Override
911     public Throwable cancellationCause() {
912       if (isCancelled()) {
913         return cancellationCause;
914       }
915       return null;
916     }
917 
918     @Override
919     public Deadline getDeadline() {
920       return deadline;
921     }
922 
923     /**
924      * Cleans up this object by calling {@code cancel(null)}.
925      */
926     @Override
927     public void close() {
928       cancel(null);
929     }
930   }
931 
932   /**
933    * A listener notified on context cancellation.
934    */
935   public interface CancellationListener {
936     /**
937      * Notifies that a context was cancelled.
938      *
939      * @param context the newly cancelled context.
940      */
941     void cancelled(Context context);
942   }
943 
944   /**
945    * Key for indexing values stored in a context. Keys use reference equality and Context does not
946    * provide a mechanism to loop over Keys. This means there is no way to access a Key's value from
947    * a Context without having access to the Key instance itself. This allows strong control over
948    * what code can get/set a key in the Context. For example, you might manage access to Key similar
949    * to a ThreadLocal using Java visibility (private/protected). Generally Keys are stored in static
950    * fields.
951    */
952   public static final class Key<T> {
953     private final String name;
954     private final T defaultValue;
955 
956     Key(String name) {
957       this(name, null);
958     }
959 
960     Key(String name, T defaultValue) {
961       this.name = checkNotNull(name, "name");
962       this.defaultValue = defaultValue;
963     }
964 
965     /**
966      * Get the value from the {@link #current()} context for this key.
967      */
968     public T get() {
969       return get(Context.current());
970     }
971 
972     /**
973      * Get the value from the specified context for this key.
974      */
975     @SuppressWarnings("unchecked")
976     public T get(Context context) {
977       T value = (T) PersistentHashArrayMappedTrie.get(context.keyValueEntries, this);
978       return value == null ? defaultValue : value;
979     }
980 
981     @Override
982     public String toString() {
983       return name;
984     }
985   }
986 
987   /**
988    * Defines the mechanisms for attaching and detaching the "current" context. The constructor for
989    * extending classes <em>must not</em> trigger any activity that can use Context, which includes
990    * logging, otherwise it can trigger an infinite initialization loop. Extending classes must not
991    * assume that only one instance will be created; Context guarantees it will only use one
992    * instance, but it may create multiple and then throw away all but one.
993    *
994    * <p>The default implementation will put the current context in a {@link ThreadLocal}.  If an
995    * alternative implementation named {@code io.grpc.override.ContextStorageOverride} exists in the
996    * classpath, it will be used instead of the default implementation.
997    *
998    * <p>This API is <a href="https://github.com/grpc/grpc-java/issues/2462">experimental</a> and
999    * subject to change.
1000    */
1001   public abstract static class Storage {
1002     /**
1003      * Unused.
1004      *
1005      * @deprecated This is an old API that is no longer used.
1006      */
1007     @Deprecated
1008     public void attach(Context toAttach) {
1009       throw new UnsupportedOperationException("Deprecated. Do not call.");
1010     }
1011 
1012     /**
1013      * Implements {@link io.grpc.Context#attach}.
1014      *
1015      * <p>Caution: {@link Context#attach()} interprets a return value of {@code null} to mean
1016      * the same thing as {@link Context#ROOT}.
1017      *
1018      * <p>See also: {@link #current()}.
1019 
1020      * @param toAttach the context to be attached
1021      * @return A {@link Context} that should be passed back into {@link #detach(Context, Context)}
1022      *        as the {@code toRestore} parameter. {@code null} is a valid return value, but see
1023      *        caution note.
1024      */
1025     public Context doAttach(Context toAttach) {
1026       // This is a default implementation to help migrate existing Storage implementations that
1027       // have an attach() method but no doAttach() method.
1028       Context current = current();
1029       attach(toAttach);
1030       return current;
1031     }
1032 
1033     /**
1034      * Implements {@link io.grpc.Context#detach}.
1035      *
1036      * @param toDetach the context to be detached. Should be, or be equivalent to, the current
1037      *        context of the current scope
1038      * @param toRestore the context to be the current.  Should be, or be equivalent to, the context
1039      *        of the outer scope
1040      */
1041     public abstract void detach(Context toDetach, Context toRestore);
1042 
1043     /**
1044      * Implements {@link io.grpc.Context#current}.
1045      *
1046      * <p>Caution: {@link Context} interprets a return value of {@code null} to mean the same
1047      * thing as {@link Context#ROOT}.
1048      *
1049      * <p>See also {@link #doAttach(Context)}.
1050      *
1051      * @return The context of the current scope. {@code null} is a valid return value, but see
1052      *        caution note.
1053      */
1054     public abstract Context current();
1055   }
1056 
1057   /**
1058    * Stores listener and executor pair.
1059    */
1060   private static final class ExecutableListener implements Runnable {
1061     private final Executor executor;
1062     final CancellationListener listener;
1063     private final Context context;
1064 
1065     ExecutableListener(Executor executor, CancellationListener listener, Context context) {
1066       this.executor = executor;
1067       this.listener = listener;
1068       this.context = context;
1069     }
1070 
1071     void deliver() {
1072       try {
1073         executor.execute(this);
1074       } catch (Throwable t) {
1075         log.log(Level.INFO, "Exception notifying context listener", t);
1076       }
1077     }
1078 
1079     @Override
1080     public void run() {
1081       listener.cancelled(context);
1082     }
1083   }
1084 
1085   @CanIgnoreReturnValue
1086   static <T> T checkNotNull(T reference, Object errorMessage) {
1087     if (reference == null) {
1088       throw new NullPointerException(String.valueOf(errorMessage));
1089     }
1090     return reference;
1091   }
1092 
1093   private enum DirectExecutor implements Executor {
1094     INSTANCE;
1095 
1096     @Override
1097     public void execute(Runnable command) {
1098       command.run();
1099     }
1100 
1101     @Override
1102     public String toString() {
1103       return "Context.DirectExecutor";
1104     }
1105   }
1106 
1107   /**
1108    * Returns {@code parent} if it is a {@link CancellableContext}, otherwise returns the parent's
1109    * {@link #cancellableAncestor}.
1110    */
1111   static CancellableContext cancellableAncestor(Context parent) {
1112     if (parent instanceof CancellableContext) {
1113       return (CancellableContext) parent;
1114     }
1115     // The parent simply cascades cancellations.
1116     // Bypass the parent and reference the ancestor directly (may be null).
1117     return parent.cancellableAncestor;
1118   }
1119 
1120   /**
1121    * If the ancestry chain length is unreasonably long, then print an error to the log and record
1122    * the stack trace.
1123    */
1124   private static void validateGeneration(int generation) {
1125     if (generation == CONTEXT_DEPTH_WARN_THRESH) {
1126       log.log(
1127           Level.SEVERE,
1128           "Context ancestry chain length is abnormally long. "
1129               + "This suggests an error in application code. "
1130               + "Length exceeded: " + CONTEXT_DEPTH_WARN_THRESH,
1131           new Exception());
1132     }
1133   }
1134 
1135   // Not using the standard com.google.errorprone.annotations.CheckReturnValue because that will
1136   // introduce dependencies that some io.grpc.Context API consumers may not want.
1137   @interface CheckReturnValue {}
1138 
1139   @interface CanIgnoreReturnValue {}
1140 }
1141