View Javadoc
1   /*
2    * Copyright (C) 2009 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5    * in compliance with the License. You may obtain a copy of the License at
6    *
7    * http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software distributed under the License
10   * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11   * or implied. See the License for the specific language governing permissions and limitations under
12   * the License.
13   */
14  
15  package com.google.common.util.concurrent;
16  
17  import static com.google.common.base.Preconditions.checkNotNull;
18  
19  import com.google.common.annotations.Beta;
20  import com.google.common.annotations.GwtCompatible;
21  import com.google.common.annotations.GwtIncompatible;
22  import com.google.common.base.Supplier;
23  import java.util.concurrent.Callable;
24  import javax.annotation.Nullable;
25  
26  /**
27   * Static utility methods pertaining to the {@link Callable} interface.
28   *
29   * @author Isaac Shum
30   * @since 1.0
31   */
32  @GwtCompatible(emulated = true)
33  public final class Callables {
34    private Callables() {}
35  
36    /**
37     * Creates a {@code Callable} which immediately returns a preset value each time it is called.
38     */
39    public static <T> Callable<T> returning(@Nullable final T value) {
40      return new Callable<T>() {
41        @Override
42        public T call() {
43          return value;
44        }
45      };
46    }
47  
48    /**
49     * Creates an {@link AsyncCallable} from a {@link Callable}.
50     *
51     * <p>The {@link AsyncCallable} returns the {@link ListenableFuture} resulting from
52     * {@link ListeningExecutorService#submit(Callable)}.
53     *
54     * @since 20.0
55     */
56    @Beta
57    @GwtIncompatible
58    public static <T> AsyncCallable<T> asAsyncCallable(
59        final Callable<T> callable,
60        final ListeningExecutorService listeningExecutorService) {
61      checkNotNull(callable);
62      checkNotNull(listeningExecutorService);
63      return new AsyncCallable<T>() {
64        @Override
65        public ListenableFuture<T> call() throws Exception {
66          return listeningExecutorService.submit(callable);
67        }
68      };
69    }
70  
71    /**
72     * Wraps the given callable such that for the duration of {@link Callable#call} the thread that is
73     * running will have the given name.
74     *
75     *
76     * @param callable The callable to wrap
77     * @param nameSupplier The supplier of thread names, {@link Supplier#get get} will be called once
78     *     for each invocation of the wrapped callable.
79     */
80    @GwtIncompatible // threads
81    static <T> Callable<T> threadRenaming(
82        final Callable<T> callable, final Supplier<String> nameSupplier) {
83      checkNotNull(nameSupplier);
84      checkNotNull(callable);
85      return new Callable<T>() {
86        @Override
87        public T call() throws Exception {
88          Thread currentThread = Thread.currentThread();
89          String oldName = currentThread.getName();
90          boolean restoreName = trySetName(nameSupplier.get(), currentThread);
91          try {
92            return callable.call();
93          } finally {
94            if (restoreName) {
95              boolean unused = trySetName(oldName, currentThread);
96            }
97          }
98        }
99      };
100   }
101 
102   /**
103    * Wraps the given runnable such that for the duration of {@link Runnable#run} the thread that is
104    * running with have the given name.
105    *
106    *
107    * @param task The Runnable to wrap
108    * @param nameSupplier The supplier of thread names, {@link Supplier#get get} will be called once
109    *     for each invocation of the wrapped callable.
110    */
111   @GwtIncompatible // threads
112   static Runnable threadRenaming(final Runnable task, final Supplier<String> nameSupplier) {
113     checkNotNull(nameSupplier);
114     checkNotNull(task);
115     return new Runnable() {
116       @Override
117       public void run() {
118         Thread currentThread = Thread.currentThread();
119         String oldName = currentThread.getName();
120         boolean restoreName = trySetName(nameSupplier.get(), currentThread);
121         try {
122           task.run();
123         } finally {
124           if (restoreName) {
125             boolean unused = trySetName(oldName, currentThread);
126           }
127         }
128       }
129     };
130   }
131 
132   /** Tries to set name of the given {@link Thread}, returns true if successful. */
133   @GwtIncompatible // threads
134   private static boolean trySetName(final String threadName, Thread currentThread) {
135     // In AppEngine, this will always fail. Should we test for that explicitly using
136     // MoreExecutors.isAppEngine? More generally, is there a way to see if we have the modifyThread
137     // permission without catching an exception?
138     try {
139       currentThread.setName(threadName);
140       return true;
141     } catch (SecurityException e) {
142       return false;
143     }
144   }
145 }