Home | History | Annotate | Download | only in concurrent
      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 {
     34   private Callables() {}
     35 
     36   /**
     37    * Creates a {@code Callable} which immediately returns a preset value each
     38    * time it is called.
     39    */
     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