summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-06-03 22:15:32 -0700
committerPaul Phillips <paulp@improving.org>2013-06-04 08:12:05 -0700
commit767a25fe2178b00f494d55bdaae53535cd7fb57d (patch)
tree1bae0553a051f6a8805391db9e75858fd297f3b6 /src/library
parentfb06073844f388ec4c007b4c08e7d508fc88d5ab (diff)
parente317d0bcc9fa8f2a2e6d93c4ad5edf5326f5a617 (diff)
downloadscala-767a25fe2178b00f494d55bdaae53535cd7fb57d.tar.gz
scala-767a25fe2178b00f494d55bdaae53535cd7fb57d.tar.bz2
scala-767a25fe2178b00f494d55bdaae53535cd7fb57d.zip
Merge branch 'pr/merge-2.10.2' into master
* pr/merge-2.10.2: SI-7375 ClassTag for value class aliases SI-7507 Fix lookup of private[this] member in presence of self type. SI-7532 Fix regression in Java inner classfile reader SI-7517 Fix higher kinded type inference regression SI-7516 Revert "SI-7234 Make named args play nice w. depmet types" A test case for a recent LUB progression. SI-7421 remove unneeded extra-attachement in maven deploy SI-7486 Regressions in implicit search. SI-7509 Avoid crasher as erronous args flow through NamesDefaults SI-6138 Centralize and refine detection of `getClass` calls SI-7497 Fix scala.util.Properties.isMac SI-7473 Bad for expr crashes postfix Increase build.number to 2.10.3 SI-7391 Always use ForkJoin in Scala actors on ... ... Java 6 and above (except when the porperty actors.enableForkJoin says otherwise) Reimplementing much of the DefaultPromise methods Optimizations: 1) Avoiding to call 'synchronized' in tryComplete and in tryAwait 2) Implementing blocking by using an optimized latch so no blocking ops for non-blockers 3) Reducing method size of isCompleted to be cheaper to inline 4) 'result' to use Try.get instead of patmat c.typeCheck(silent = true) now suppresses ambiguous errors Conflicts: bincompat-backward.whitelist.conf bincompat-forward.whitelist.conf src/compiler/scala/reflect/macros/contexts/Typers.scala src/compiler/scala/reflect/reify/package.scala src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala src/compiler/scala/tools/nsc/typechecker/Typers.scala src/compiler/scala/tools/reflect/ToolBoxFactory.scala src/library/scala/concurrent/impl/Promise.scala src/reflect/scala/reflect/internal/Types.scala
Diffstat (limited to 'src/library')
-rw-r--r--src/library/scala/concurrent/impl/Promise.scala85
-rw-r--r--src/library/scala/util/Properties.scala12
2 files changed, 49 insertions, 48 deletions
diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala
index 7af70400ef..ffaea8de96 100644
--- a/src/library/scala/concurrent/impl/Promise.scala
+++ b/src/library/scala/concurrent/impl/Promise.scala
@@ -8,11 +8,14 @@
package scala.concurrent.impl
-import scala.concurrent.{ ExecutionContext, CanAwait, OnCompleteRunnable, TimeoutException, ExecutionException }
+import scala.concurrent.{ ExecutionContext, CanAwait, OnCompleteRunnable, TimeoutException, ExecutionException, blocking }
+import scala.concurrent.Future.InternalCallbackExecutor
import scala.concurrent.duration.{ Duration, Deadline, FiniteDuration, NANOSECONDS }
import scala.annotation.tailrec
import scala.util.control.NonFatal
import scala.util.{ Try, Success, Failure }
+import java.io.ObjectInputStream
+import java.util.concurrent.locks.AbstractQueuedSynchronizer
private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with scala.concurrent.Future[T] {
def future: this.type = this
@@ -53,69 +56,68 @@ private[concurrent] object Promise {
case t => Failure(t)
}
+ /*
+ * Inspired by: http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/main/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+ private final class CompletionLatch[T] extends AbstractQueuedSynchronizer with (Try[T] => Unit) {
+ override protected def tryAcquireShared(ignored: Int): Int = if (getState != 0) 1 else -1
+ override protected def tryReleaseShared(ignore: Int): Boolean = {
+ setState(1)
+ true
+ }
+ override def apply(ignored: Try[T]): Unit = releaseShared(1)
+ }
+
+
/** Default promise implementation.
*/
class DefaultPromise[T] extends AbstractPromise with Promise[T] { self =>
updateState(null, Nil) // Start at "No callbacks"
- protected final def tryAwait(atMost: Duration): Boolean = {
- @tailrec
- def awaitUnsafe(deadline: Deadline, nextWait: FiniteDuration): Boolean = {
- if (!isCompleted && nextWait > Duration.Zero) {
- val ms = nextWait.toMillis
- val ns = (nextWait.toNanos % 1000000l).toInt // as per object.wait spec
-
- synchronized { if (!isCompleted) wait(ms, ns) }
-
- awaitUnsafe(deadline, deadline.timeLeft)
- } else
- isCompleted
- }
- @tailrec
- def awaitUnbounded(): Boolean = {
- if (isCompleted) true
- else {
- synchronized { if (!isCompleted) wait() }
- awaitUnbounded()
- }
- }
-
+ protected final def tryAwait(atMost: Duration): Boolean = if (!isCompleted) {
import Duration.Undefined
+ import scala.concurrent.Future.InternalCallbackExecutor
atMost match {
- case u if u eq Undefined => throw new IllegalArgumentException("cannot wait for Undefined period")
- case Duration.Inf => awaitUnbounded()
- case Duration.MinusInf => isCompleted
- case f: FiniteDuration => if (f > Duration.Zero) awaitUnsafe(f.fromNow, f) else isCompleted
+ case e if e eq Undefined => throw new IllegalArgumentException("cannot wait for Undefined period")
+ case Duration.Inf =>
+ val l = new CompletionLatch[T]()
+ onComplete(l)(InternalCallbackExecutor)
+ l.acquireSharedInterruptibly(1)
+ case Duration.MinusInf => // Drop out
+ case f: FiniteDuration =>
+ if (f > Duration.Zero) {
+ val l = new CompletionLatch[T]()
+ onComplete(l)(InternalCallbackExecutor)
+ l.tryAcquireSharedNanos(1, f.toNanos)
+ }
}
- }
+
+ isCompleted
+ } else true // Already completed
@throws(classOf[TimeoutException])
@throws(classOf[InterruptedException])
def ready(atMost: Duration)(implicit permit: CanAwait): this.type =
- if (isCompleted || tryAwait(atMost)) this
+ if (tryAwait(atMost)) this
else throw new TimeoutException("Futures timed out after [" + atMost + "]")
@throws(classOf[Exception])
def result(atMost: Duration)(implicit permit: CanAwait): T =
- ready(atMost).value.get match {
- case Failure(e) => throw e
- case Success(r) => r
- }
+ ready(atMost).value.get.get // ready throws TimeoutException if timeout so value.get is safe here
def value: Option[Try[T]] = getState match {
case c: Try[_] => Some(c.asInstanceOf[Try[T]])
case _ => None
}
- override def isCompleted: Boolean = getState match { // Cheaper than boxing result into Option due to "def value"
- case _: Try[_] => true
- case _ => false
- }
+ override def isCompleted: Boolean = getState.isInstanceOf[Try[_]]
def tryComplete(value: Try[T]): Boolean = {
val resolved = resolveTry(value)
- (try {
- @tailrec
+ @tailrec
def tryComplete(v: Try[T]): List[CallbackRunnable[T]] = {
getState match {
case raw: List[_] =>
@@ -124,10 +126,7 @@ private[concurrent] object Promise {
case _ => null
}
}
- tryComplete(resolved)
- } finally {
- synchronized { notifyAll() } //Notify any evil blockers
- }) match {
+ tryComplete(resolved) match {
case null => false
case rs if rs.isEmpty => true
case rs => rs.foreach(r => r.executeWithValue(resolved)); true
diff --git a/src/library/scala/util/Properties.scala b/src/library/scala/util/Properties.scala
index 73469a955d..2240dde360 100644
--- a/src/library/scala/util/Properties.scala
+++ b/src/library/scala/util/Properties.scala
@@ -122,8 +122,7 @@ private[scala] trait PropertiesTrait {
*/
def lineSeparator = propOrElse("line.separator", "\n")
- /** Various well-known properties.
- */
+ /* Various well-known properties. */
def javaClassPath = propOrEmpty("java.class.path")
def javaHome = propOrEmpty("java.home")
def javaVendor = propOrEmpty("java.vendor")
@@ -139,10 +138,13 @@ private[scala] trait PropertiesTrait {
def userHome = propOrEmpty("user.home")
def userName = propOrEmpty("user.name")
- /** Some derived values.
- */
+ /* Some derived values. */
+ /** Returns `true` iff the underlying operating system is a version of Microsoft Windows. */
def isWin = osName startsWith "Windows"
- def isMac = javaVendor startsWith "Apple"
+ // See http://mail.openjdk.java.net/pipermail/macosx-port-dev/2012-November/005148.html for
+ // the reason why we don't follow developer.apple.com/library/mac/#technotes/tn2002/tn2110.
+ /** Returns `true` iff the underlying operating system is a version of Apple Mac OSX. */
+ def isMac = osName startsWith "Mac OS X"
// This is looking for javac, tools.jar, etc.
// Tries JDK_HOME first, then the more common but likely jre JAVA_HOME,