aboutsummaryrefslogtreecommitdiff
path: root/android/guava/src/com/google/common/util/concurrent/Callables.java
blob: c4caf36b570582344878ec41779004ab6a8d8d65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
 * Copyright (C) 2009 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.common.util.concurrent;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Supplier;
import java.util.concurrent.Callable;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;

/**
 * Static utility methods pertaining to the {@link Callable} interface.
 *
 * @author Isaac Shum
 * @since 1.0
 */
@GwtCompatible(emulated = true)
public final class Callables {
  private Callables() {}

  /** Creates a {@code Callable} which immediately returns a preset value each time it is called. */
  public static <T> Callable<T> returning(@NullableDecl final T value) {
    return new Callable<T>() {
      @Override
      public T call() {
        return value;
      }
    };
  }

  /**
   * Creates an {@link AsyncCallable} from a {@link Callable}.
   *
   * <p>The {@link AsyncCallable} returns the {@link ListenableFuture} resulting from {@link
   * ListeningExecutorService#submit(Callable)}.
   *
   * @since 20.0
   */
  @Beta
  @GwtIncompatible
  public static <T> AsyncCallable<T> asAsyncCallable(
      final Callable<T> callable, final ListeningExecutorService listeningExecutorService) {
    checkNotNull(callable);
    checkNotNull(listeningExecutorService);
    return new AsyncCallable<T>() {
      @Override
      public ListenableFuture<T> call() throws Exception {
        return listeningExecutorService.submit(callable);
      }
    };
  }

  /**
   * Wraps the given callable such that for the duration of {@link Callable#call} the thread that is
   * running will have the given name.
   *
   *
   * @param callable The callable to wrap
   * @param nameSupplier The supplier of thread names, {@link Supplier#get get} will be called once
   *     for each invocation of the wrapped callable.
   */
  @GwtIncompatible // threads
  static <T> Callable<T> threadRenaming(
      final Callable<T> callable, final Supplier<String> nameSupplier) {
    checkNotNull(nameSupplier);
    checkNotNull(callable);
    return new Callable<T>() {
      @Override
      public T call() throws Exception {
        Thread currentThread = Thread.currentThread();
        String oldName = currentThread.getName();
        boolean restoreName = trySetName(nameSupplier.get(), currentThread);
        try {
          return callable.call();
        } finally {
          if (restoreName) {
            boolean unused = trySetName(oldName, currentThread);
          }
        }
      }
    };
  }

  /**
   * Wraps the given runnable such that for the duration of {@link Runnable#run} the thread that is
   * running with have the given name.
   *
   *
   * @param task The Runnable to wrap
   * @param nameSupplier The supplier of thread names, {@link Supplier#get get} will be called once
   *     for each invocation of the wrapped callable.
   */
  @GwtIncompatible // threads
  static Runnable threadRenaming(final Runnable task, final Supplier<String> nameSupplier) {
    checkNotNull(nameSupplier);
    checkNotNull(task);
    return new Runnable() {
      @Override
      public void run() {
        Thread currentThread = Thread.currentThread();
        String oldName = currentThread.getName();
        boolean restoreName = trySetName(nameSupplier.get(), currentThread);
        try {
          task.run();
        } finally {
          if (restoreName) {
            boolean unused = trySetName(oldName, currentThread);
          }
        }
      }
    };
  }

  /** Tries to set name of the given {@link Thread}, returns true if successful. */
  @GwtIncompatible // threads
  private static boolean trySetName(final String threadName, Thread currentThread) {
    /*
     * setName should usually succeed, but the security manager can prohibit it. Is there a way to
     * see if we have the modifyThread permission without catching an exception?
     */
    try {
      currentThread.setName(threadName);
      return true;
    } catch (SecurityException e) {
      return false;
    }
  }
}