Skip to content

Commit 94dd70b

Browse files
committed
Transformation class + some separation checking fixes
1 parent 295229f commit 94dd70b

File tree

4 files changed

+27
-18
lines changed

4 files changed

+27
-18
lines changed

scala2-library-cc/src/scala/concurrent/ExecutionContext.scala

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import scala.annotation.implicitNotFound
1717

1818
import language.experimental.captureChecking
1919
import caps.Capability
20+
import caps.consume
2021

2122
/**
2223
* An `ExecutionContext` can execute program logic asynchronously,
@@ -255,7 +256,7 @@ object ExecutionContext {
255256
* @param reporter a function for error reporting
256257
* @return the `ExecutionContext` using the given `ExecutorService`
257258
*/
258-
def fromExecutorService(e: ExecutorService, reporter: Throwable => Unit): ExecutionContextExecutorService^{reporter} =
259+
def fromExecutorService(e: ExecutorService, @consume reporter: Throwable => Unit): ExecutionContextExecutorService^{reporter} =
259260
impl.ExecutionContextImpl.fromExecutorService(e, reporter)
260261

261262
/** Creates an `ExecutionContext` from the given `ExecutorService` with the [[scala.concurrent.ExecutionContext$.defaultReporter default reporter]].
@@ -279,7 +280,7 @@ object ExecutionContext {
279280
* @param reporter a function for error reporting
280281
* @return the `ExecutionContext` using the given `Executor`
281282
*/
282-
def fromExecutor(e: Executor, reporter: Throwable => Unit): ExecutionContextExecutor^{reporter} =
283+
def fromExecutor(e: Executor, @consume reporter: Throwable => Unit): ExecutionContextExecutor^ =
283284
impl.ExecutionContextImpl.fromExecutor(e, reporter)
284285

285286
/** Creates an `ExecutionContext` from the given `Executor` with the [[scala.concurrent.ExecutionContext$.defaultReporter default reporter]].

scala2-library-cc/src/scala/concurrent/Future.scala

+4-4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import scala.reflect.ClassTag
2525
import scala.concurrent.ExecutionContext.parasitic
2626

2727
import language.experimental.captureChecking
28+
import caps.consume
2829

2930
/** A `Future` represents a value which may or may not be currently available,
3031
* but will be available at some point, or an exception if that value could not be made available.
@@ -424,7 +425,7 @@ trait Future[+T] extends Awaitable[T] {
424425
* @return a `Future` with the result of the application of `f` to the results of `this` and `that`
425426
* @group Transformations
426427
*/
427-
def zipWith[U, R](that: Future[U])(f: (T, U) => R)(implicit executor: ExecutionContext): Future[R] = {
428+
def zipWith[U, R](that: Future[U])(@consume f: (T, U) => R)(implicit executor: ExecutionContext): Future[R] = {
428429
// This is typically overriden by the implementation in DefaultPromise, which provides
429430
// symmetric fail-fast behavior regardless of which future fails first.
430431
//
@@ -573,7 +574,7 @@ object Future {
573574
private[concurrent] final val recoverWithFailed = (t: Throwable) => recoverWithFailedMarker
574575

575576
private[this] final val _zipWithTuple2: (Any, Any) => (Any, Any) = Tuple2.apply _
576-
private[concurrent] final def zipWithTuple2Fun[T,U] = _zipWithTuple2.asInstanceOf[(T,U) => (T,U)]
577+
private[concurrent] final def zipWithTuple2Fun[T,U] = _zipWithTuple2.asInstanceOf //[(T,U) => (T,U)]
577578

578579
private[this] final val _addToBuilderFun: (Builder[Any, Nothing], Any) => Builder[Any, Nothing] = (b: Builder[Any, Nothing], e: Any) => b += e
579580
private[concurrent] final def addToBuilderFun[A, M] = _addToBuilderFun.asInstanceOf[Function2[Builder[A, M], A, Builder[A, M]]]
@@ -633,7 +634,7 @@ object Future {
633634
override final def recover[U >: Nothing](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U] = this
634635
override final def recoverWith[U >: Nothing](pf: PartialFunction[Throwable, Future[U]])(implicit executor: ExecutionContext): Future[U] = this
635636
override final def zip[U](that: Future[U]): Future[(Nothing, U)] = this
636-
override final def zipWith[U, R](that: Future[U])(f: (Nothing, U) => R)(implicit executor: ExecutionContext): Future[R] = this
637+
override final def zipWith[U, R](that: Future[U])(@consume f: (Nothing, U) => R)(implicit executor: ExecutionContext): Future[R] = this
637638
override final def fallbackTo[U >: Nothing](that: Future[U]): Future[U] = this
638639
override final def mapTo[S](implicit tag: ClassTag[S]): Future[S] = this
639640
override final def andThen[U](pf: PartialFunction[Try[Nothing], U])(implicit executor: ExecutionContext): Future[Nothing] = this
@@ -877,4 +878,3 @@ object Future {
877878
trait OnCompleteRunnable extends Batchable {
878879
self: Runnable =>
879880
}
880-

scala2-library-cc/src/scala/concurrent/impl/ExecutionContextImpl.scala

+4-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import java.util.Collection
1717
import scala.concurrent.{ BlockContext, ExecutionContext, CanAwait, ExecutionContextExecutor, ExecutionContextExecutorService }
1818

1919
import language.experimental.captureChecking
20+
import caps.consume
2021

2122
private[scala] class ExecutionContextImpl private[impl] (final val executor: Executor, final val reporter: Throwable => Unit) extends ExecutionContextExecutor {
2223
require(executor ne null, "Executor must not be null")
@@ -82,7 +83,7 @@ private[concurrent] object ExecutionContextImpl {
8283
})
8384
}
8485

85-
def createDefaultExecutorService(reporter: Throwable => Unit): ExecutionContextExecutorService^ = {
86+
def createDefaultExecutorService(@consume reporter: Throwable => Unit): ExecutionContextExecutorService^ = {
8687
def getInt(name: String, default: String) = (try System.getProperty(name, default) catch {
8788
case e: SecurityException => default
8889
}) match {
@@ -112,13 +113,13 @@ private[concurrent] object ExecutionContextImpl {
112113
}
113114
}
114115

115-
def fromExecutor(e: Executor, reporter: Throwable => Unit = ExecutionContext.defaultReporter): ExecutionContextExecutor^ =
116+
def fromExecutor(e: Executor, @consume reporter: Throwable => Unit = ExecutionContext.defaultReporter): ExecutionContextExecutor^ =
116117
e match {
117118
case null => createDefaultExecutorService(reporter)
118119
case some => new ExecutionContextImpl(some, reporter)
119120
}
120121

121-
def fromExecutorService(es: ExecutorService, reporter: Throwable => Unit = ExecutionContext.defaultReporter):
122+
def fromExecutorService(es: ExecutorService, @consume reporter: Throwable => Unit = ExecutionContext.defaultReporter):
122123
ExecutionContextExecutorService^ = es match {
123124
case null => createDefaultExecutorService(reporter)
124125
case some =>

scala2-library-cc/src/scala/concurrent/impl/Promise.scala

+16-9
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ import java.util.Objects.requireNonNull
2424
import java.io.{IOException, NotSerializableException, ObjectInputStream, ObjectOutputStream}
2525

2626
import language.experimental.captureChecking
27+
import scala.annotation.unchecked.uncheckedCaptures
28+
import caps.cap
29+
import caps.consume
2730
import caps.unsafe.*
2831

2932
/**
@@ -66,15 +69,15 @@ private[concurrent] object Promise {
6669
/**
6770
* Compresses this chain and returns the currently known root of this chain of Links.
6871
**/
69-
final def promise(owner: DefaultPromise[T]^): DefaultPromise[T]^{this, to, owner} = {
72+
final def promise(owner: DefaultPromise[T]^): DefaultPromise[T]^{cap.rd, this, to, owner} = {
7073
val c = get()
7174
compressed(current = c, target = c, owner = owner)
7275
}
7376

7477
/**
7578
* The combination of traversing and possibly unlinking of a given `target` DefaultPromise.
7679
**/
77-
@inline @tailrec private[this] final def compressed(current: DefaultPromise[T]^, target: DefaultPromise[T]^, owner: DefaultPromise[T]^): DefaultPromise[T]^{this, current, target, owner} = {
80+
@inline @tailrec private[this] final def compressed(current: DefaultPromise[T]^{cap.rd, this}, target: DefaultPromise[T]^, owner: DefaultPromise[T]^): DefaultPromise[T]^{this, current, target, owner} = {
7881
val value = target.get()
7982
if (value.isInstanceOf[Callbacks[_]]) {
8083
if (compareAndSet(current, target)) target // Link
@@ -127,6 +130,7 @@ private[concurrent] object Promise {
127130
/**
128131
* Returns the associated `Future` with this `Promise`
129132
*/
133+
@consume
130134
override final def future: Future[T]^ = (this : Future[T]^)
131135

132136
override final def transform[S](f: Try[T] => Try[S])(implicit executor: ExecutionContext): Future[S] =
@@ -135,7 +139,7 @@ private[concurrent] object Promise {
135139
override final def transformWith[S](f: Try[T] => Future[S])(implicit executor: ExecutionContext): Future[S] =
136140
dispatchOrAddCallbacks(get(), new Transformation[T, S](Xform_transformWith, f, executor))
137141

138-
override final def zipWith[U, R](that: Future[U])(f: (T, U) => R)(implicit executor: ExecutionContext): Future[R] = {
142+
override final def zipWith[U, R](that: Future[U])(@consume f: (T, U) => R)(implicit executor: ExecutionContext): Future[R] = {
139143
val state = get()
140144
if (state.isInstanceOf[Try[_]]) {
141145
if (state.asInstanceOf[Try[T]].isFailure) this.asInstanceOf[Future[R]]
@@ -414,11 +418,14 @@ private[concurrent] object Promise {
414418
* function's type parameters are erased, and the _xform tag will be used to reify them.
415419
**/
416420
final class Transformation[-F, T] private[this] (
417-
private[this] final val _fun: Any => Any,
418-
private[this] final val _ec: ExecutionContext,
421+
__fun: Any => Any,
422+
__ec: ExecutionContext,
419423
private[this] final var _arg: Try[F],
420424
private[this] final val _xform: Int
421425
) extends DefaultPromise[T]() with Callbacks[F] with Runnable with Batchable {
426+
@uncheckedCaptures private[this] final var _fun: Any => Any = __fun
427+
@uncheckedCaptures private[this] final var _ec: ExecutionContext = __ec
428+
422429
final def this(xform: Int, f: _ => _, ec: ExecutionContext) =
423430
this(f.asInstanceOf[Any => Any], ec.prepare(): @nowarn("cat=deprecation"), null, xform)
424431

@@ -434,9 +441,9 @@ private[concurrent] object Promise {
434441
try e.execute(this.unsafeAssumePure) /* Safe publication of _arg, _fun, _ec */
435442
catch {
436443
case t: Throwable =>
437-
// _fun = null // allow to GC
444+
_fun = null // allow to GC
438445
_arg = null // see above
439-
// _ec = null // see above again
446+
_ec = null // see above again
440447
handleFailure(t, e)
441448
}
442449

@@ -460,9 +467,9 @@ private[concurrent] object Promise {
460467
val v = _arg
461468
val fun = _fun
462469
val ec = _ec
463-
// _fun = null // allow to GC
470+
_fun = null // allow to GC
464471
_arg = null // see above
465-
// _ec = null // see above
472+
_ec = null // see above
466473
try {
467474
val resolvedResult: Try[_] =
468475
(_xform: @switch) match {

0 commit comments

Comments
 (0)