• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Guava 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 com.google.common.util.concurrent;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 
21 import com.google.common.base.Supplier;
22 
23 import java.util.concurrent.Callable;
24 
25 import javax.annotation.Nullable;
26 
27 /**
28  * Static utility methods pertaining to the {@link Callable} interface.
29  *
30  * @author Isaac Shum
31  * @since 1.0
32  */
33 public final class Callables {
Callables()34   private Callables() {}
35 
36   /**
37    * Creates a {@code Callable} which immediately returns a preset value each
38    * time it is called.
39    */
returning(final @Nullable T value)40   public static <T> Callable<T> returning(final @Nullable T value) {
41     return new Callable<T>() {
42       @Override public T call() {
43         return value;
44       }
45     };
46   }
47 
48   /**
49    * Wraps the given callable such that for the duration of {@link Callable#call} the thread that is
50    * running will have the given name.
51    *
52    *
53    * @param callable The callable to wrap
54    * @param nameSupplier The supplier of thread names, {@link Supplier#get get} will be called once
55    *     for each invocation of the wrapped callable.
56    */
57   static <T> Callable<T> threadRenaming(final Callable<T> callable,
58       final Supplier<String> nameSupplier) {
59     checkNotNull(nameSupplier);
60     checkNotNull(callable);
61     return new Callable<T>() {
62       @Override public T call() throws Exception {
63         Thread currentThread = Thread.currentThread();
64         String oldName = currentThread.getName();
65         boolean restoreName = trySetName(nameSupplier.get(), currentThread);
66         try {
67           return callable.call();
68         } finally {
69           if (restoreName) {
70             trySetName(oldName, currentThread);
71           }
72         }
73       }
74     };
75   }
76 
77   /**
78    * Wraps the given runnable such that for the duration of {@link Runnable#run} the thread that is
79    * running with have the given name.
80    *
81    *
82    * @param task The Runnable to wrap
83    * @param nameSupplier The supplier of thread names, {@link Supplier#get get} will be called once
84    *     for each invocation of the wrapped callable.
85    */
86   static Runnable threadRenaming(final Runnable task, final Supplier<String> nameSupplier) {
87     checkNotNull(nameSupplier);
88     checkNotNull(task);
89     return new Runnable() {
90       @Override public void run() {
91         Thread currentThread = Thread.currentThread();
92         String oldName = currentThread.getName();
93         boolean restoreName = trySetName(nameSupplier.get(), currentThread);
94         try {
95           task.run();
96         } finally {
97           if (restoreName) {
98             trySetName(oldName, currentThread);
99           }
100         }
101       }
102     };
103   }
104 
105   /** Tries to set name of the given {@link Thread}, returns true if successful. */
106   private static boolean trySetName(final String threadName, Thread currentThread) {
107     // In AppEngine this will always fail, should we test for that explicitly using
108     // MoreExecutors.isAppEngine.  More generally, is there a way to see if we have the modifyThread
109     // permission without catching an exception?
110     try {
111       currentThread.setName(threadName);
112       return true;
113     } catch (SecurityException e) {
114       return false;
115     }
116   }
117 }
118