diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/build/maven/scala-library-pom.xml | 29 | ||||
-rw-r--r-- | src/library/scala/collection/mutable/HashTable.scala | 2 | ||||
-rw-r--r-- | src/library/scala/concurrent/ConcurrentPackageObject.scala | 30 | ||||
-rw-r--r-- | src/library/scala/concurrent/ExecutionContext.scala | 6 | ||||
-rw-r--r-- | src/library/scala/concurrent/Future.scala | 33 | ||||
-rw-r--r-- | src/library/scala/concurrent/impl/ExecutionContextImpl.scala | 42 | ||||
-rw-r--r-- | src/library/scala/concurrent/impl/Future.scala | 30 | ||||
-rw-r--r-- | src/library/scala/concurrent/impl/Promise.scala | 2 | ||||
-rw-r--r-- | src/library/scala/math/BigDecimal.scala | 15 | ||||
-rw-r--r-- | src/library/scala/math/BigInt.scala | 38 |
10 files changed, 157 insertions, 70 deletions
diff --git a/src/build/maven/scala-library-pom.xml b/src/build/maven/scala-library-pom.xml index 673c3dfada..c3f8a4531c 100644 --- a/src/build/maven/scala-library-pom.xml +++ b/src/build/maven/scala-library-pom.xml @@ -30,17 +30,24 @@ <system>JIRA</system> <url>https://issues.scala-lang.org/</url> </issueManagement> - <distributionManagement> - <repository> - <id>scala-tools.org</id> - <url>@RELEASE_REPOSITORY@</url> - </repository> - <snapshotRepository> - <id>scala-tools.org</id> - <url>@SNAPSHOT_REPOSITORY@</url> - <uniqueVersion>false</uniqueVersion> - </snapshotRepository> - </distributionManagement> + <dependencies> + <dependency> + <groupId>org.skife.com.typesafe.config</groupId> + <artifactId>typesafe-config</artifactId> + <version>0.3.0</version> + </dependency> + </dependencies> + <distributionManagement> + <repository> + <id>scala-tools.org</id> + <url>@RELEASE_REPOSITORY@</url> + </repository> + <snapshotRepository> + <id>scala-tools.org</id> + <url>@SNAPSHOT_REPOSITORY@</url> + <uniqueVersion>false</uniqueVersion> + </snapshotRepository> + </distributionManagement> <developers> <developer> <id>lamp</id> diff --git a/src/library/scala/collection/mutable/HashTable.scala b/src/library/scala/collection/mutable/HashTable.scala index cc0aed6963..06b7d40bfc 100644 --- a/src/library/scala/collection/mutable/HashTable.scala +++ b/src/library/scala/collection/mutable/HashTable.scala @@ -366,7 +366,7 @@ private[collection] object HashTable { private[collection] final def newThreshold(_loadFactor: Int, size: Int) = ((size.toLong * _loadFactor) / loadFactorDenum).toInt - private[collection] final def sizeForThreshold(_loadFactor: Int, thr: Int) = thr * loadFactorDenum / _loadFactor + private[collection] final def sizeForThreshold(_loadFactor: Int, thr: Int) = ((thr.toLong * loadFactorDenum) / _loadFactor).toInt private[collection] final def capacity(expectedSize: Int) = if (expectedSize == 0) 1 else powerOfTwo(expectedSize) diff --git a/src/library/scala/concurrent/ConcurrentPackageObject.scala b/src/library/scala/concurrent/ConcurrentPackageObject.scala index ba98757906..f4744a8757 100644 --- a/src/library/scala/concurrent/ConcurrentPackageObject.scala +++ b/src/library/scala/concurrent/ConcurrentPackageObject.scala @@ -10,8 +10,8 @@ package scala.concurrent -import java.util.concurrent.{ Executors, ExecutorService } -import scala.concurrent.forkjoin.ForkJoinPool +import java.util.concurrent.{ Executors, ExecutorService, ThreadFactory } +import scala.concurrent.forkjoin.{ ForkJoinPool, ForkJoinWorkerThread } import scala.util.{ Try, Success, Failure } import scala.concurrent.util.Duration import ConcurrentPackageObject._ @@ -24,14 +24,9 @@ abstract class ConcurrentPackageObject { /** A global execution environment for executing lightweight tasks. */ lazy val executionContext = - new impl.ExecutionContextImpl(getExecutorService) - - private[concurrent] def getExecutorService: AnyRef = - if (scala.util.Properties.isJavaAtLeast("1.6")) { - val vendor = scala.util.Properties.javaVmVendor - if ((vendor contains "Oracle") || (vendor contains "Sun") || (vendor contains "Apple")) new ForkJoinPool - else Executors.newCachedThreadPool() - } else Executors.newCachedThreadPool() + new impl.ExecutionContextImpl() + + private val currentExecutionContext = new ThreadLocal[ExecutionContext] val handledFutureException: PartialFunction[Throwable, Throwable] = { case t: Throwable if isFutureThrowable(t) => t @@ -58,10 +53,10 @@ abstract class ConcurrentPackageObject { /* concurrency constructs */ - def future[T](body: =>T)(implicit execCtx: ExecutionContext = executionContext): Future[T] = + def future[T](body: =>T)(implicit execctx: ExecutionContext = executionContext): Future[T] = Future[T](body) - def promise[T]()(implicit execCtx: ExecutionContext = executionContext): Promise[T] = + def promise[T]()(implicit execctx: ExecutionContext = executionContext): Promise[T] = Promise[T]() /** Wraps a block of code into an awaitable object. */ @@ -82,8 +77,8 @@ abstract class ConcurrentPackageObject { * - InterruptedException - in the case that a wait within the blockable object was interrupted * - TimeoutException - in the case that the blockable object timed out */ - def blocking[T](body: =>T)(implicit execCtx: ExecutionContext): T = - executionContext.blocking(body) + def blocking[T](body: =>T): T = + blocking(body2awaitable(body), Duration.fromNanos(0)) /** Blocks on an awaitable object. * @@ -94,8 +89,11 @@ abstract class ConcurrentPackageObject { * - InterruptedException - in the case that a wait within the blockable object was interrupted * - TimeoutException - in the case that the blockable object timed out */ - def blocking[T](awaitable: Awaitable[T], atMost: Duration)(implicit execCtx: ExecutionContext = executionContext): T = - executionContext.blocking(awaitable, atMost) + def blocking[T](awaitable: Awaitable[T], atMost: Duration): T = + currentExecutionContext.get match { + case null => Await.result(awaitable, atMost) + case ec => ec.internalBlockingCall(awaitable, atMost) + } @inline implicit final def int2durationops(x: Int): DurationOps = new DurationOps(x) } diff --git a/src/library/scala/concurrent/ExecutionContext.scala b/src/library/scala/concurrent/ExecutionContext.scala index a206a2d4ea..f639f76dc9 100644 --- a/src/library/scala/concurrent/ExecutionContext.scala +++ b/src/library/scala/concurrent/ExecutionContext.scala @@ -26,10 +26,8 @@ trait ExecutionContext { def execute[U](body: () => U): Unit - def blocking[T](body: =>T): T - - def blocking[T](awaitable: Awaitable[T], atMost: Duration): T - + def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T + def reportFailure(t: Throwable): Unit /* implementations follow */ diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala index d73801aa90..8cecadc605 100644 --- a/src/library/scala/concurrent/Future.scala +++ b/src/library/scala/concurrent/Future.scala @@ -274,6 +274,18 @@ self => p.future } + /** Used by for-comprehensions. + */ + final def withFilter(p: T => Boolean): Future[T] = filter(p) + // final def withFilter(p: T => Boolean) = new FutureWithFilter[T](this, p) + + // final class FutureWithFilter[+S](self: Future[S], p: S => Boolean) { + // def foreach(f: S => Unit): Unit = self filter p foreach f + // def map[R](f: S => R) = self filter p map f + // def flatMap[R](f: S => Future[R]) = self filter p flatMap f + // def withFilter(q: S => Boolean): FutureWithFilter[S] = new FutureWithFilter[S](self, x => p(x) && q(x)) + // } + /** Creates a new future by mapping the value of the current future if the given partial function is defined at that value. * * If the current future contains a value for which the partial function is defined, the new future will also hold that value. @@ -417,7 +429,26 @@ self => p.future } - + + /** Creates a new `Future[S]` which is completed with this `Future`'s result if + * that conforms to `S`'s erased type or a `ClassCastException` otherwise. + */ + def mapTo[S](implicit m: Manifest[S]): Future[S] = { + val p = newPromise[S] + + onComplete { + case l: Failure[_] => p complete l.asInstanceOf[Try[S]] + case Success(t) => + p complete (try { + Success(impl.Future.boxedType(m.erasure).cast(t).asInstanceOf[S]) + } catch { + case e: ClassCastException => Failure(e) + }) + } + + p.future + } + /** Applies the side-effecting function to the result of this future, and returns * a new future with the result of this future. * diff --git a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala index 5dc440f42b..2cfd6f22cd 100644 --- a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala +++ b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala @@ -10,7 +10,7 @@ package scala.concurrent.impl -import java.util.concurrent.{Callable, ExecutorService} +import java.util.concurrent.{Callable, ExecutorService, Executors, ThreadFactory} import scala.concurrent.forkjoin._ import scala.concurrent.{ExecutionContext, resolver, Awaitable, body2awaitable} import scala.util.{ Try, Success, Failure } @@ -18,8 +18,42 @@ import scala.concurrent.util.{ Duration } -private[scala] class ExecutionContextImpl(val executorService: AnyRef) extends ExecutionContext { +private[scala] class ExecutionContextImpl() extends ExecutionContext { import ExecutionContextImpl._ + + val executorService: AnyRef = getExecutorService + + // to ensure that the current execution context thread local is properly set + private def executorsThreadFactory = new ThreadFactory { + def newThread(r: Runnable) = new Thread(new Runnable { + override def run() { + currentExecutionContext.set(ExecutionContextImpl.this) + r.run() + } + }) + } + + // to ensure that the current execution context thread local is properly set + private def forkJoinPoolThreadFactory = new ForkJoinPool.ForkJoinWorkerThreadFactory { + def newThread(fjp: ForkJoinPool) = new ForkJoinWorkerThread(fjp) { + override def onStart() { + currentExecutionContext.set(ExecutionContextImpl.this) + } + } + } + + private def getExecutorService: AnyRef = + if (scala.util.Properties.isJavaAtLeast("1.6")) { + val vendor = scala.util.Properties.javaVmVendor + if ((vendor contains "Oracle") || (vendor contains "Sun") || (vendor contains "Apple")) + new ForkJoinPool( + Runtime.getRuntime.availableProcessors(), + forkJoinPoolThreadFactory, + null, + false) + else + Executors.newCachedThreadPool(executorsThreadFactory) + } else Executors.newCachedThreadPool(executorsThreadFactory) def execute(runnable: Runnable): Unit = executorService match { case fj: ForkJoinPool => @@ -37,9 +71,7 @@ private[scala] class ExecutionContextImpl(val executorService: AnyRef) extends E def run() = body() }) - def blocking[T](body: =>T): T = blocking(body2awaitable(body), Duration.fromNanos(0)) - - def blocking[T](awaitable: Awaitable[T], atMost: Duration): T = { + def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T = { Future.releaseStack(this) awaitable.result(atMost)(scala.concurrent.Await.canAwaitEvidence) diff --git a/src/library/scala/concurrent/impl/Future.scala b/src/library/scala/concurrent/impl/Future.scala index 6833b2467f..1111aa4753 100644 --- a/src/library/scala/concurrent/impl/Future.scala +++ b/src/library/scala/concurrent/impl/Future.scala @@ -40,36 +40,6 @@ private[concurrent] trait Future[+T] extends scala.concurrent.Future[T] with Awa def onComplete[U](func: Try[T] => U): this.type - /** Creates a new Future[A] which is completed with this Future's result if - * that conforms to A's erased type or a ClassCastException otherwise. - */ - final def mapTo[T](implicit m: Manifest[T]) = { - val p = new Promise.DefaultPromise[T] - - onComplete { - case f @ Failure(t) => p complete f.asInstanceOf[Try[T]] - case Success(v) => - p complete (try { - Success(Future.boxedType(m.erasure).cast(v).asInstanceOf[T]) - } catch { - case e: ClassCastException => Failure(e) - }) - } - - p.future - } - - /** Used by for-comprehensions. - */ - final def withFilter(p: T => Boolean) = new FutureWithFilter[T](this, p) - - final class FutureWithFilter[+A](self: Future[A], p: A => Boolean) { - def foreach(f: A => Unit): Unit = self filter p foreach f - def map[B](f: A => B) = self filter p map f - def flatMap[B](f: A => Future[B]) = self filter p flatMap f - def withFilter(q: A => Boolean): FutureWithFilter[A] = new FutureWithFilter[A](self, x ⇒ p(x) && q(x)) - } - } object Future { diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala index c79b0d02cc..f05e306088 100644 --- a/src/library/scala/concurrent/impl/Promise.scala +++ b/src/library/scala/concurrent/impl/Promise.scala @@ -127,7 +127,7 @@ object Promise { value.isDefined } - executor.blocking(concurrent.body2awaitable(awaitUnsafe(dur2long(atMost))), atMost) + blocking(concurrent.body2awaitable(awaitUnsafe(dur2long(atMost))), atMost) } def ready(atMost: Duration)(implicit permit: CanAwait): this.type = diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala index c1f45eccfb..cb42b76b51 100644 --- a/src/library/scala/math/BigDecimal.scala +++ b/src/library/scala/math/BigDecimal.scala @@ -183,7 +183,8 @@ extends ScalaNumber with ScalaNumericConversions with Serializable { override def equals (that: Any): Boolean = that match { case that: BigDecimal => this equals that case that: BigInt => this.toBigIntExact exists (that equals _) - case _: Float | _: Double => unifiedPrimitiveEquals(that) + case that: Double => isValidDouble && toDouble == that + case that: Float => isValidFloat && toFloat == that case _ => isValidLong && unifiedPrimitiveEquals(that) } override def isValidByte = noArithmeticException(toByteExact) @@ -191,6 +192,18 @@ extends ScalaNumber with ScalaNumericConversions with Serializable { override def isValidChar = isValidInt && toIntExact >= Char.MinValue && toIntExact <= Char.MaxValue override def isValidInt = noArithmeticException(toIntExact) def isValidLong = noArithmeticException(toLongExact) + /** Returns `true` iff this can be represented exactly by [[scala.Float]]; otherwise returns `false`. + */ + def isValidFloat = { + val f = toFloat + !f.isInfinity && bigDecimal.compareTo(new java.math.BigDecimal(f)) == 0 + } + /** Returns `true` iff this can be represented exactly by [[scala.Double]]; otherwise returns `false`. + */ + def isValidDouble = { + val d = toDouble + !d.isInfinity && bigDecimal.compareTo(new java.math.BigDecimal(d)) == 0 + } private def noArithmeticException(body: => Unit): Boolean = { try { body ; true } diff --git a/src/library/scala/math/BigInt.scala b/src/library/scala/math/BigInt.scala index 8a53afaa62..dbec30b2fe 100644 --- a/src/library/scala/math/BigInt.scala +++ b/src/library/scala/math/BigInt.scala @@ -20,6 +20,7 @@ object BigInt { private val minCached = -1024 private val maxCached = 1024 private val cache = new Array[BigInt](maxCached - minCached + 1) + private val minusOne = BigInteger.valueOf(-1) @deprecated("Use Long.MinValue", "2.9.0") val MinLong = BigInt(Long.MinValue) @@ -122,6 +123,8 @@ class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericCo override def equals(that: Any): Boolean = that match { case that: BigInt => this equals that case that: BigDecimal => that.toBigIntExact exists (this equals _) + case that: Double => isValidDouble && toDouble == that + case that: Float => isValidFloat && toFloat == that case x => isValidLong && unifiedPrimitiveEquals(x) } override def isValidByte = this >= Byte.MinValue && this <= Byte.MaxValue @@ -129,6 +132,41 @@ class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericCo override def isValidChar = this >= Char.MinValue && this <= Char.MaxValue override def isValidInt = this >= Int.MinValue && this <= Int.MaxValue def isValidLong = this >= Long.MinValue && this <= Long.MaxValue + /** Returns `true` iff this can be represented exactly by [[scala.Float]]; otherwise returns `false`. + */ + def isValidFloat = { + val bitLen = bitLength + (bitLen <= 24 || + { + val lowest = lowestSetBit + bitLen <= java.lang.Float.MAX_EXPONENT + 1 && // exclude this < -2^128 && this >= 2^128 + lowest >= bitLen - 24 && + lowest < java.lang.Float.MAX_EXPONENT + 1 // exclude this == -2^128 + } + ) && !bitLengthOverflow + } + /** Returns `true` iff this can be represented exactly by [[scala.Double]]; otherwise returns `false`. + */ + def isValidDouble = { + val bitLen = bitLength + (bitLen <= 53 || + { + val lowest = lowestSetBit + bitLen <= java.lang.Double.MAX_EXPONENT + 1 && // exclude this < -2^1024 && this >= 2^1024 + lowest >= bitLen - 53 && + lowest < java.lang.Double.MAX_EXPONENT + 1 // exclude this == -2^1024 + } + ) && !bitLengthOverflow + } + /** Some implementations of java.math.BigInteger allow huge values with bit length greater than Int.MaxValue . + * The BigInteger.bitLength method returns truncated bit length in this case . + * This method tests if result of bitLength is valid. + * This method will become unnecessary if BigInt constructors reject huge BigIntegers. + */ + private def bitLengthOverflow = { + val shifted = bigInteger.shiftRight(Int.MaxValue) + (shifted.signum != 0) && !(shifted equals BigInt.minusOne) + } protected[math] def isWhole = true def underlying = bigInteger |