001/*
002 * Copyright (C) 2009 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 */
014
015package com.google.common.util.concurrent;
016
017import static com.google.common.base.Preconditions.checkNotNull;
018
019import com.google.common.annotations.Beta;
020import com.google.common.annotations.GwtCompatible;
021import com.google.common.annotations.GwtIncompatible;
022import com.google.common.base.Supplier;
023import java.util.concurrent.Callable;
024import javax.annotation.Nullable;
025
026/**
027 * Static utility methods pertaining to the {@link Callable} interface.
028 *
029 * @author Isaac Shum
030 * @since 1.0
031 */
032@GwtCompatible(emulated = true)
033public final class Callables {
034  private Callables() {}
035
036  /**
037   * Creates a {@code Callable} which immediately returns a preset value each time it is called.
038   */
039  public static <T> Callable<T> returning(@Nullable final T value) {
040    return new Callable<T>() {
041      @Override
042      public T call() {
043        return value;
044      }
045    };
046  }
047
048  /**
049   * Creates an {@link AsyncCallable} from a {@link Callable}.
050   *
051   * <p>The {@link AsyncCallable} returns the {@link ListenableFuture} resulting from
052   * {@link ListeningExecutorService#submit(Callable)}.
053   *
054   * @since 20.0
055   */
056  @Beta
057  @GwtIncompatible
058  public static <T> AsyncCallable<T> asAsyncCallable(
059      final Callable<T> callable,
060      final ListeningExecutorService listeningExecutorService) {
061    checkNotNull(callable);
062    checkNotNull(listeningExecutorService);
063    return new AsyncCallable<T>() {
064      @Override
065      public ListenableFuture<T> call() throws Exception {
066        return listeningExecutorService.submit(callable);
067      }
068    };
069  }
070
071  /**
072   * Wraps the given callable such that for the duration of {@link Callable#call} the thread that is
073   * running will have the given name.
074   *
075   *
076   * @param callable The callable to wrap
077   * @param nameSupplier The supplier of thread names, {@link Supplier#get get} will be called once
078   *     for each invocation of the wrapped callable.
079   */
080  @GwtIncompatible // threads
081  static <T> Callable<T> threadRenaming(
082      final Callable<T> callable, final Supplier<String> nameSupplier) {
083    checkNotNull(nameSupplier);
084    checkNotNull(callable);
085    return new Callable<T>() {
086      @Override
087      public T call() throws Exception {
088        Thread currentThread = Thread.currentThread();
089        String oldName = currentThread.getName();
090        boolean restoreName = trySetName(nameSupplier.get(), currentThread);
091        try {
092          return callable.call();
093        } finally {
094          if (restoreName) {
095            boolean unused = trySetName(oldName, currentThread);
096          }
097        }
098      }
099    };
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}