Skip to content

Commit fa0743c

Browse files
committed
Add missing canonical combinators:
- `def transform[S](f: Try[T] => Try[S])(implicit executor: ExecutionContext): Future[S]` - `def transformWith[S](f: Try[T] => Future[S])(implicit executor: ExecutionContext): Future[S]` - `def flatten[S](implicit ev: T <:< Future[S]): Future[S]` - `def zipWith[U, R](that: Future[U])(f: (T, U) => R)(implicit executor: ExecutionContext): Future[R]` Add missing utilities: - `val unit: Future[Unit]` in `object Future` - `object never extends Future[Nothing]` in `object Future` - `def defaultBlockContext: BlockContext` in `object BlockContext` - `def toString: String` on stdlib implementations of `Future` Refactors: - the `scala.concurrent.Future` trait to not explicit create any `Promises`, so that implementations can control implementation type, this is mainly facilitated through adding of the `transform` and `transformWith` methods. - the implementation of `ExecutionContextImpl` has been cleaned up - the `scala.concurrent.impl.DefaultPromise` has been reimplemented to not use `sun.misc.Unsafe` Securing: - Add a self-check in `completeWith` and `tryCompleteWith` to avoid cycles in trait Promise - Capping the maximum number of threads for the global `ExecutionContext` to the max parallelism - Implementing (almost) all `Future` combinators on `transformWith` and `transform` means that `DefaultPromise` linking works on both `(flat)map` and `recover(With)` - Nested `blocking {}` should not spawn extra threads beyond the first. Removes: - the private `internalExecutor` method in favor of an import in trait `Future` - the private `internalExecutor` method in favor of an import in trait `Promise` - the `AtomicReferenceFieldUpdater` in `AbstractPromise` since we're using `Unsafe` - `scala.concurrent.impl.Future` is no longer needed Deprecates: - `Future.onSuccess` - discourage the use of callbacks (and is also redundant considering `foreach` and `onComplete`) - `Future.onFailure` - discourage the use of callbacks (and is also redundant considering `onComplete` and `failed.foreach`) - `ExecutionContext.prepare` - it was ill specced and it is too easy to forget to call it (or even know when to call it or call it more times than needed) - All classes in scala.concurrent.forkjoin. Scala 2.12 will be Java 8+ and as such the jsr166e should be used as included in java.util.concurrent. Reimplements: - `failed` - in terms of `transform` - `map` - in terms of `transform` - `flatMap` - in terms of `transformWith` - `recover` - in terms of `transform` - `recoverWith` - in terms of `transformWith` - `zip` - in terms of `flatMap` + `map` - `fallbackTo` - in terms of `recoverWith` + `recoverWith` - `andThen` - in terms of `transform` Miscellaneous: - Giving the threads of `ExecutionContext.global` sensible names - Optimizes `object Future.successful` and `object Future.failed` are now separate implementations, to optimize for the result, avoiding doing work for the "other branch". - Optimizes `compressedRoot()` by avoiding double-calls to volatile get. Documentation: - Almost all methods on `Future` and `Promise` have been revisited and had their ScalaDoc updated Tests: - Yes
1 parent c0ceffb commit fa0743c

24 files changed

+1086
-429
lines changed

src/forkjoin/scala/concurrent/forkjoin/ForkJoinPool.java

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
* @since 1.8
2424
* @author Doug Lea
2525
*/
26+
@Deprecated
2627
/*public*/ abstract class CountedCompleter<T> extends ForkJoinTask<T> {
2728
private static final long serialVersionUID = 5232453752276485070L;
2829

@@ -471,6 +472,7 @@ private static sun.misc.Unsafe getUnsafe() {
471472
* @since 1.7
472473
* @author Doug Lea
473474
*/
475+
@Deprecated
474476
public class ForkJoinPool extends AbstractExecutorService {
475477

476478
/*
@@ -3578,6 +3580,7 @@ static void quiesceCommonPool() {
35783580
* }
35793581
* }}</pre>
35803582
*/
3583+
@Deprecated
35813584
public static interface ManagedBlocker {
35823585
/**
35833586
* Possibly blocks the current thread, for example waiting for

src/forkjoin/scala/concurrent/forkjoin/ForkJoinTask.java

+5
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@
180180
* @since 1.7
181181
* @author Doug Lea
182182
*/
183+
@Deprecated
183184
public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
184185

185186
/*
@@ -391,6 +392,7 @@ private int doInvoke() {
391392
* any ForkJoinPool will call helpExpungeStaleExceptions when its
392393
* pool becomes isQuiescent.
393394
*/
395+
@Deprecated
394396
static final class ExceptionNode extends WeakReference<ForkJoinTask<?>> {
395397
final Throwable ex;
396398
ExceptionNode next;
@@ -1330,6 +1332,7 @@ public final boolean compareAndSetForkJoinTaskTag(short e, short tag) {
13301332
* to be compliant with AbstractExecutorService constraints
13311333
* when used in ForkJoinPool.
13321334
*/
1335+
@Deprecated
13331336
static final class AdaptedRunnable<T> extends ForkJoinTask<T>
13341337
implements RunnableFuture<T> {
13351338
final Runnable runnable;
@@ -1349,6 +1352,7 @@ static final class AdaptedRunnable<T> extends ForkJoinTask<T>
13491352
/**
13501353
* Adaptor for Runnables without results
13511354
*/
1355+
@Deprecated
13521356
static final class AdaptedRunnableAction extends ForkJoinTask<Void>
13531357
implements RunnableFuture<Void> {
13541358
final Runnable runnable;
@@ -1366,6 +1370,7 @@ public final void setRawResult(Void v) { }
13661370
/**
13671371
* Adaptor for Callables
13681372
*/
1373+
@Deprecated
13691374
static final class AdaptedCallable<T> extends ForkJoinTask<T>
13701375
implements RunnableFuture<T> {
13711376
final Callable<? extends T> callable;

src/forkjoin/scala/concurrent/forkjoin/ForkJoinWorkerThread.java

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
* @since 1.7
2121
* @author Doug Lea
2222
*/
23+
@Deprecated
2324
public class ForkJoinWorkerThread extends Thread {
2425
/*
2526
* ForkJoinWorkerThreads are managed by ForkJoinPools and perform

src/forkjoin/scala/concurrent/forkjoin/LinkedTransferQueue.java

+3
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
* @author Doug Lea
5454
* @param <E> the type of elements held in this collection
5555
*/
56+
@Deprecated
5657
public class LinkedTransferQueue<E> extends AbstractQueue<E>
5758
implements TransferQueue<E>, java.io.Serializable {
5859
private static final long serialVersionUID = -3223113410248163686L;
@@ -416,6 +417,7 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
416417
* unnecessary ordering constraints: Writes that are intrinsically
417418
* ordered wrt other accesses or CASes use simple relaxed forms.
418419
*/
420+
@Deprecated
419421
static final class Node {
420422
final boolean isData; // false if this is a request node
421423
volatile Object item; // initially non-null if isData; CASed to match
@@ -789,6 +791,7 @@ private int countOfMode(boolean data) {
789791
return count;
790792
}
791793

794+
@Deprecated
792795
final class Itr implements Iterator<E> {
793796
private Node nextNode; // next node to return item for
794797
private E nextItem; // the corresponding item

src/forkjoin/scala/concurrent/forkjoin/RecursiveAction.java

+1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133
* @since 1.7
134134
* @author Doug Lea
135135
*/
136+
@Deprecated
136137
public abstract class RecursiveAction extends ForkJoinTask<Void> {
137138
private static final long serialVersionUID = 5232453952276485070L;
138139

src/forkjoin/scala/concurrent/forkjoin/RecursiveTask.java

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
* @since 1.7
3737
* @author Doug Lea
3838
*/
39+
@Deprecated
3940
public abstract class RecursiveTask<V> extends ForkJoinTask<V> {
4041
private static final long serialVersionUID = 5232453952276485270L;
4142

src/forkjoin/scala/concurrent/forkjoin/ThreadLocalRandom.java

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
* @since 1.7
3333
* @author Doug Lea
3434
*/
35+
@Deprecated
3536
public class ThreadLocalRandom extends Random {
3637
// same constants as Random, but must be redeclared because private
3738
private static final long multiplier = 0x5DEECE66DL;
@@ -80,6 +81,7 @@ protected ThreadLocalRandom initialValue() {
8081
*
8182
* @return the current thread's {@code ThreadLocalRandom}
8283
*/
84+
@Deprecated
8385
public static ThreadLocalRandom current() {
8486
return localRandom.get();
8587
}

src/forkjoin/scala/concurrent/forkjoin/TransferQueue.java

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
* @author Doug Lea
3838
* @param <E> the type of elements held in this collection
3939
*/
40+
@Deprecated
4041
public interface TransferQueue<E> extends BlockingQueue<E> {
4142
/**
4243
* Transfers the element to a waiting consumer immediately, if possible.

src/forkjoin/scala/concurrent/util/Unsafe.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,12 @@
77
\* */
88

99
package scala.concurrent.util;
10-
11-
12-
1310
import java.lang.reflect.Field;
1411

1512

16-
13+
@Deprecated
1714
public final class Unsafe {
15+
@Deprecated
1816
public final static sun.misc.Unsafe instance;
1917
static {
2018
try {

src/library/scala/concurrent/BlockContext.scala

+12-3
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ package scala.concurrent
4141
trait BlockContext {
4242

4343
/** Used internally by the framework;
44-
* Designates (and eventually executes) a thunk which potentially blocks the calling `Thread`.
44+
* Designates (and eventually executes) a thunk which potentially blocks the calling `java.lang.Thread`.
4545
*
4646
* Clients must use `scala.concurrent.blocking` or `scala.concurrent.Await` instead.
4747
*/
@@ -53,9 +53,16 @@ object BlockContext {
5353
override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = thunk
5454
}
5555

56+
/**
57+
* @return the `BlockContext` that will be used if no other is found.
58+
**/
59+
def defaultBlockContext: BlockContext = DefaultBlockContext
60+
5661
private val contextLocal = new ThreadLocal[BlockContext]()
5762

58-
/** Obtain the current thread's current `BlockContext`. */
63+
/**
64+
@return the `BlockContext` that would be used for the current `java.lang.Thread` at this point
65+
**/
5966
def current: BlockContext = contextLocal.get match {
6067
case null => Thread.currentThread match {
6168
case ctx: BlockContext => ctx
@@ -64,7 +71,9 @@ object BlockContext {
6471
case some => some
6572
}
6673

67-
/** Pushes a current `BlockContext` while executing `body`. */
74+
/**
75+
* Installs a current `BlockContext` around executing `body`.
76+
**/
6877
def withBlockContext[T](blockContext: BlockContext)(body: => T): T = {
6978
val old = contextLocal.get // can be null
7079
try {

src/library/scala/concurrent/ExecutionContext.scala

+17-15
Original file line numberDiff line numberDiff line change
@@ -72,22 +72,24 @@ trait ExecutionContext {
7272
*/
7373
def reportFailure(@deprecatedName('t) cause: Throwable): Unit
7474

75-
/** Prepares for the execution of a task. Returns the prepared execution context.
76-
*
77-
* `prepare` should be called at the site where an `ExecutionContext` is received (for
78-
* example, through an implicit method parameter). The returned execution context may
79-
* then be used to execute tasks. The role of `prepare` is to save any context relevant
80-
* to an execution's ''call site'', so that this context may be restored at the
81-
* ''execution site''. (These are often different: for example, execution may be
82-
* suspended through a `Promise`'s future until the `Promise` is completed, which may
83-
* be done in another thread, on another stack.)
84-
*
85-
* Note: a valid implementation of `prepare` is one that simply returns `this`.
86-
*
87-
* @return the prepared execution context
88-
*/
75+
/** Prepares for the execution of a task. Returns the prepared
76+
* execution context. The recommended implementation of
77+
* `prepare` is to return `this`.
78+
*
79+
* This method should no longer be overridden or called. It was
80+
* originally expected that `prepare` would be called by
81+
* all libraries that consume ExecutionContexts, in order to
82+
* capture thread local context. However, this usage has proven
83+
* difficult to implement in practice and instead it is
84+
* now better to avoid using `prepare` entirely.
85+
*
86+
* Instead, if an `ExecutionContext` needs to capture thread
87+
* local context, it should capture that context when it is
88+
* constructed, so that it doesn't need any additional
89+
* preparation later.
90+
*/
91+
@deprecated("Preparation of ExecutionContexts will be removed.", "2.12")
8992
def prepare(): ExecutionContext = this
90-
9193
}
9294

9395
/**

0 commit comments

Comments
 (0)