diff options
author | Martin Odersky <odersky@gmail.com> | 2012-04-13 16:27:46 -0700 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2012-04-13 16:27:46 -0700 |
commit | 2744be417e1f2c461068bb2daef9fa8f11822031 (patch) | |
tree | 06580aa466401d86d63176b2af429e9daaf047f9 /src/library | |
parent | b5757577c520e6339e4278fa91f725e66561f73e (diff) | |
parent | 1d0610840bb7409f0da084d3cc94e4110dd2e2c4 (diff) | |
download | scala-2744be417e1f2c461068bb2daef9fa8f11822031.tar.gz scala-2744be417e1f2c461068bb2daef9fa8f11822031.tar.bz2 scala-2744be417e1f2c461068bb2daef9fa8f11822031.zip |
Merge branch 'master' into topic/sip18
Diffstat (limited to 'src/library')
20 files changed, 286 insertions, 176 deletions
diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala index 99c54ce58c..5b8ebde308 100644 --- a/src/library/scala/Array.scala +++ b/src/library/scala/Array.scala @@ -467,6 +467,19 @@ object Array extends FallbackArrayBuilding { * @version 1.0 * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_38.html#anchor "The Scala 2.8 Collections' API"]] * section on `Array` by Martin Odersky for more information. + * @define coll array + * @define Coll Array + * @define orderDependent + * @define orderDependentFold + * @define mayNotTerminateInf + * @define willNotTerminateInf + * @define collectExample + * @define undefinedorder + * @define thatinfo the class of the returned collection. In the standard library configuration, + * `That` is either `Array[B]` if a ClassManifest is available for B or `ArraySeq[B]` otherwise. + * @define zipthatinfo $thatinfo + * @define bfinfo an implicit value of class `CanBuildFrom` which determines the result class `That` from the current + * representation type `Repr` and the new element type `B`. */ final class Array[T](_length: Int) extends java.io.Serializable with java.lang.Cloneable { diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala index 79ceff328e..a58297d7d4 100644 --- a/src/library/scala/Option.scala +++ b/src/library/scala/Option.scala @@ -82,6 +82,17 @@ object Option { * @define option [[scala.Option]] * @define p `p` * @define f `f` + * @define coll option + * @define Coll Option + * @define orderDependent + * @define orderDependentFold + * @define mayNotTerminateInf + * @define willNotTerminateInf + * @define collectExample + * @define undefinedorder + * @define thatinfo the class of the returned collection. In the standard library configuration, `That` is `Iterable[B]` + * @define bfinfo an implicit value of class `CanBuildFrom` which determines the result class `That` from the current + * representation type `Repr` and the new element type `B`. */ sealed abstract class Option[+A] extends Product with Serializable { self => diff --git a/src/library/scala/Tuple2.scala b/src/library/scala/Tuple2.scala index b1befca4fa..37ab564c3c 100644 --- a/src/library/scala/Tuple2.scala +++ b/src/library/scala/Tuple2.scala @@ -23,7 +23,7 @@ case class Tuple2[@specialized(Int, Long, Double, Char, Boolean, AnyRef) +T1, @s extends Product2[T1, T2] { override def toString() = "(" + _1 + "," + _2 + ")" - + /** Swaps the elements of this `Tuple`. * @return a new Tuple where the first element is the second element of this Tuple and the * second element is the first element of this Tuple. @@ -54,6 +54,16 @@ case class Tuple2[@specialized(Int, Long, Double, Char, Boolean, AnyRef) +T1, @s def zipped[Repr1, El1, Repr2, El2](implicit w1: T1 => TLike[El1, Repr1], w2: T2 => ILike[El2, Repr2]): Zipped[Repr1, El1, Repr2, El2] = new Zipped[Repr1, El1, Repr2, El2](_1, _2) + /** + * @define coll zipped + * @define Coll Zipped + * @define orderDependent + * @define orderDependentFold + * @define mayNotTerminateInf + * @define willNotTerminateInf + * @define collectExample + * @define undefinedorder + */ class Zipped[+Repr1, +El1, +Repr2, +El2](coll1: TLike[El1, Repr1], coll2: ILike[El2, Repr2]) { // coll2: ILike for filter def map[B, To](f: (El1, El2) => B)(implicit cbf: CBF[Repr1, B, To]): To = { val b = cbf(coll1.repr) diff --git a/src/library/scala/Tuple3.scala b/src/library/scala/Tuple3.scala index 0d5399308b..cd5ee23757 100644 --- a/src/library/scala/Tuple3.scala +++ b/src/library/scala/Tuple3.scala @@ -24,7 +24,7 @@ case class Tuple3[+T1, +T2, +T3](_1: T1, _2: T2, _3: T3) extends Product3[T1, T2, T3] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + ")" - + @deprecated("Use `zipped` instead.", "2.9.0") def zip[Repr1, El1, El2, El3, To](implicit w1: T1 => TLike[El1, Repr1], @@ -53,6 +53,17 @@ case class Tuple3[+T1, +T2, +T3](_1: T1, _2: T2, _3: T3) w3: T3 => ILike[El3, Repr3]): Zipped[Repr1, El1, Repr2, El2, Repr3, El3] = new Zipped[Repr1, El1, Repr2, El2, Repr3, El3](_1, _2, _3) + /** + * @define coll zipped + * @define Coll Zipped + * @define orderDependent + * @define orderDependentFold + * @define mayNotTerminateInf + * @define willNotTerminateInf + * @define collectExample + * @define undefinedorder + * @define thatInfo The class of the returned collection. + */ class Zipped[+Repr1, +El1, +Repr2, +El2, +Repr3, +El3](coll1: TLike[El1, Repr1], coll2: ILike[El2, Repr2], coll3: ILike[El3, Repr3]) { diff --git a/src/library/scala/concurrent/ConcurrentPackageObject.scala b/src/library/scala/concurrent/ConcurrentPackageObject.scala index c6da343f3a..fafd7fd238 100644 --- a/src/library/scala/concurrent/ConcurrentPackageObject.scala +++ b/src/library/scala/concurrent/ConcurrentPackageObject.scala @@ -36,34 +36,42 @@ abstract class ConcurrentPackageObject { case _ => true } - private[concurrent] def resolve[T](source: Either[Throwable, T]): Either[Throwable, T] = source match { - case Left(t: scala.runtime.NonLocalReturnControl[_]) => Right(t.value.asInstanceOf[T]) - case Left(t: scala.util.control.ControlThrowable) => Left(new ExecutionException("Boxed ControlThrowable", t)) - case Left(t: InterruptedException) => Left(new ExecutionException("Boxed InterruptedException", t)) - case Left(e: Error) => Left(new ExecutionException("Boxed Error", e)) - case _ => source + private[concurrent] def resolveEither[T](source: Either[Throwable, T]): Either[Throwable, T] = source match { + case Left(t) => resolver(t) + case _ => source } - private[concurrent] def resolver[T] = - resolverFunction.asInstanceOf[PartialFunction[Throwable, Either[Throwable, T]]] - + private[concurrent] def resolver[T](throwable: Throwable): Either[Throwable, T] = throwable match { + case t: scala.runtime.NonLocalReturnControl[_] => Right(t.value.asInstanceOf[T]) + case t: scala.util.control.ControlThrowable => Left(new ExecutionException("Boxed ControlThrowable", t)) + case t: InterruptedException => Left(new ExecutionException("Boxed InterruptedException", t)) + case e: Error => Left(new ExecutionException("Boxed Error", e)) + case t => Left(t) + } + /* concurrency constructs */ + /** Starts an asynchronous computation and returns a `Future` object with the result of that computation. + * + * The result becomes available once the asynchronous computation is completed. + * + * @tparam T the type of the result + * @param body the asychronous computation + * @param execctx the execution context on which the future is run + * @return the `Future` holding the result of the computation + */ def future[T](body: =>T)(implicit execctx: ExecutionContext = defaultExecutionContext): Future[T] = Future[T](body) + /** Creates a promise object which can be completed with a value. + * + * @tparam T the type of the value in the promise + * @param execctx the execution context on which the promise is created on + * @return the newly created `Promise` object + */ def promise[T]()(implicit execctx: ExecutionContext = defaultExecutionContext): Promise[T] = Promise[T]() - /** Wraps a block of code into an awaitable object. */ - def body2awaitable[T](body: =>T) = new Awaitable[T] { - def ready(atMost: Duration)(implicit permit: CanAwait) = { - body - this - } - def result(atMost: Duration)(implicit permit: CanAwait) = body - } - /** Used to block on a piece of code which potentially blocks. * * @param body A piece of code which contains potentially blocking or long running calls. @@ -74,7 +82,7 @@ abstract class ConcurrentPackageObject { * - TimeoutException - in the case that the blockable object timed out */ def blocking[T](body: =>T): T = - blocking(body2awaitable(body), Duration.fromNanos(0)) + blocking(impl.Future.body2awaitable(body), Duration.fromNanos(0)) /** Blocks on an awaitable object. * @@ -100,11 +108,11 @@ private[concurrent] object ConcurrentPackageObject { // compiling a subset of sources; it seems that the wildcard is not // properly handled, and you get messages like "type _$1 defined twice". // This is consistent with other package object breakdowns. - private val resolverFunction: PartialFunction[Throwable, Either[Throwable, _]] = { - case t: scala.runtime.NonLocalReturnControl[_] => Right(t.value) - case t: scala.util.control.ControlThrowable => Left(new ExecutionException("Boxed ControlThrowable", t)) - case t: InterruptedException => Left(new ExecutionException("Boxed InterruptedException", t)) - case e: Error => Left(new ExecutionException("Boxed Error", e)) - case t => Left(t) - } + // private val resolverFunction: PartialFunction[Throwable, Either[Throwable, _]] = { + // case t: scala.runtime.NonLocalReturnControl[_] => Right(t.value) + // case t: scala.util.control.ControlThrowable => Left(new ExecutionException("Boxed ControlThrowable", t)) + // case t: InterruptedException => Left(new ExecutionException("Boxed InterruptedException", t)) + // case e: Error => Left(new ExecutionException("Boxed Error", e)) + // case t => Left(t) + // } } diff --git a/src/library/scala/concurrent/ExecutionContext.scala b/src/library/scala/concurrent/ExecutionContext.scala index e1d4276396..3f62f58bf8 100644 --- a/src/library/scala/concurrent/ExecutionContext.scala +++ b/src/library/scala/concurrent/ExecutionContext.scala @@ -20,19 +20,22 @@ import collection._ trait ExecutionContext { - + + /** Runs a block of code on this execution context. + */ def execute(runnable: Runnable): Unit - - def execute[U](body: () => U): Unit - + + /** Used internally by the framework - blocks execution for at most `atMost` time while waiting + * for an `awaitable` object to become ready. + * + * Clients should use `scala.concurrent.blocking` instead. + */ def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T + /** Reports that an asynchronous computation failed. + */ def reportFailure(t: Throwable): Unit - - /* implementations follow */ - - private implicit val executionContext = this - + } diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala index 01ce902c79..0d76c23c25 100644 --- a/src/library/scala/concurrent/Future.scala +++ b/src/library/scala/concurrent/Future.scala @@ -513,6 +513,15 @@ trait Future[+T] extends Awaitable[T] { */ object Future { + /** Starts an asynchronous computation and returns a `Future` object with the result of that computation. + * + * The result becomes available once the asynchronous computation is completed. + * + * @tparam T the type of the result + * @param body the asychronous computation + * @param execctx the execution context on which the future is run + * @return the `Future` holding the result of the computation + */ def apply[T](body: =>T)(implicit executor: ExecutionContext): Future[T] = impl.Future(body) import scala.collection.mutable.Builder diff --git a/src/library/scala/concurrent/Promise.scala b/src/library/scala/concurrent/Promise.scala index 8f2bce5d1a..cd22a55ce7 100644 --- a/src/library/scala/concurrent/Promise.scala +++ b/src/library/scala/concurrent/Promise.scala @@ -107,15 +107,27 @@ trait Promise[T] { object Promise { - /** Creates a new promise. + /** Creates a promise object which can be completed with a value. + * + * @tparam T the type of the value in the promise + * @param execctx the execution context on which the promise is created on + * @return the newly created `Promise` object */ def apply[T]()(implicit executor: ExecutionContext): Promise[T] = new impl.Promise.DefaultPromise[T]() - /** Creates an already completed Promise with the specified exception + /** Creates an already completed Promise with the specified exception. + * + * @tparam T the type of the value in the promise + * @param execctx the execution context on which the promise is created on + * @return the newly created `Promise` object */ def failed[T](exception: Throwable)(implicit executor: ExecutionContext): Promise[T] = new impl.Promise.KeptPromise[T](Left(exception)) - /** Creates an already completed Promise with the specified result + /** Creates an already completed Promise with the specified result. + * + * @tparam T the type of the value in the promise + * @param execctx the execution context on which the promise is created on + * @return the newly created `Promise` object */ def successful[T](result: T)(implicit executor: ExecutionContext): Promise[T] = new impl.Promise.KeptPromise[T](Right(result)) diff --git a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala index c5062267dc..c308a59297 100644 --- a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala +++ b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala @@ -12,7 +12,7 @@ package scala.concurrent.impl import java.util.concurrent.{Callable, Executor, ExecutorService, Executors, ThreadFactory} import scala.concurrent.forkjoin._ -import scala.concurrent.{ExecutionContext, resolver, Awaitable, body2awaitable} +import scala.concurrent.{ExecutionContext, resolver, Awaitable} import scala.concurrent.util.{ Duration } @@ -56,24 +56,40 @@ private[scala] class ExecutionContextImpl(es: AnyRef) extends ExecutionContext w def execute(runnable: Runnable): Unit = executorService match { case fj: ForkJoinPool => - if (Thread.currentThread.isInstanceOf[ForkJoinWorkerThread]) { - val fjtask = ForkJoinTask.adapt(runnable) - fjtask.fork - } else { - fj.execute(runnable) + Thread.currentThread match { + case fjw: ForkJoinWorkerThread if fjw.getPool eq fj => + val fjtask = runnable match { + case fjt: ForkJoinTask[_] => fjt + case _ => ForkJoinTask.adapt(runnable) + } + fjtask.fork + case _ => + fj.execute(runnable) } case executor: Executor => executor execute runnable } - def execute[U](body: () => U): Unit = execute(new Runnable { - def run() = body() - }) - def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T = { Future.releaseStack(this) - awaitable.result(atMost)(scala.concurrent.Await.canAwaitEvidence) + executorService match { + case fj: ForkJoinPool => + var result: T = null.asInstanceOf[T] + val managedBlocker = new ForkJoinPool.ManagedBlocker { + @volatile var isdone = false + def block() = { + result = awaitable.result(atMost)(scala.concurrent.Await.canAwaitEvidence) + isdone = true + true + } + def isReleasable = isdone + } + ForkJoinPool.managedBlock(managedBlocker) + result + case _ => + awaitable.result(atMost)(scala.concurrent.Await.canAwaitEvidence) + } } def reportFailure(t: Throwable) = t match { diff --git a/src/library/scala/concurrent/impl/Future.scala b/src/library/scala/concurrent/impl/Future.scala index 615ab061a5..a3c8ed3095 100644 --- a/src/library/scala/concurrent/impl/Future.scala +++ b/src/library/scala/concurrent/impl/Future.scala @@ -10,9 +10,11 @@ package scala.concurrent.impl -import scala.concurrent.{Awaitable, ExecutionContext} +import scala.concurrent.util.Duration +import scala.concurrent.{Awaitable, ExecutionContext, CanAwait} import scala.collection.mutable.Stack + private[concurrent] trait Future[+T] extends scala.concurrent.Future[T] with Awaitable[T] { implicit def executor: ExecutionContext @@ -54,6 +56,15 @@ object Future { classOf[Unit] -> classOf[scala.runtime.BoxedUnit] ) + /** Wraps a block of code into an awaitable object. */ + private[concurrent] def body2awaitable[T](body: =>T) = new Awaitable[T] { + def ready(atMost: Duration)(implicit permit: CanAwait) = { + body + this + } + def result(atMost: Duration)(implicit permit: CanAwait) = body + } + def boxedType(c: Class[_]): Class[_] = { if (c.isPrimitive) toBoxed(c) else c } diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala index f7e073cb78..07b6d1f278 100644 --- a/src/library/scala/concurrent/impl/Promise.scala +++ b/src/library/scala/concurrent/impl/Promise.scala @@ -12,7 +12,7 @@ package scala.concurrent.impl import java.util.concurrent.TimeUnit.{ NANOSECONDS, MILLISECONDS } import java.util.concurrent.atomic.AtomicReferenceFieldUpdater -import scala.concurrent.{Awaitable, ExecutionContext, resolve, resolver, blocking, CanAwait, TimeoutException} +import scala.concurrent.{Awaitable, ExecutionContext, resolveEither, resolver, blocking, CanAwait, TimeoutException} //import scala.util.continuations._ import scala.concurrent.util.Duration import scala.util @@ -126,7 +126,7 @@ object Promise { value.isDefined } - blocking(concurrent.body2awaitable(awaitUnsafe(dur2long(atMost))), atMost) + blocking(Future.body2awaitable(awaitUnsafe(dur2long(atMost))), atMost) } def ready(atMost: Duration)(implicit permit: CanAwait): this.type = @@ -166,7 +166,7 @@ object Promise { case _ => null } } - tryComplete(resolve(value)) + tryComplete(resolveEither(value)) } finally { synchronized { notifyAll() } // notify any blockers from `tryAwait` } @@ -220,7 +220,7 @@ object Promise { */ final class KeptPromise[T](suppliedValue: Either[Throwable, T])(implicit val executor: ExecutionContext) extends Promise[T] { - val value = Some(resolve(suppliedValue)) + val value = Some(resolveEither(suppliedValue)) def tryComplete(value: Either[Throwable, T]): Boolean = false diff --git a/src/library/scala/concurrent/util/Duration.scala b/src/library/scala/concurrent/util/Duration.scala index 3f7c44945b..15a546de10 100644 --- a/src/library/scala/concurrent/util/Duration.scala +++ b/src/library/scala/concurrent/util/Duration.scala @@ -9,51 +9,6 @@ import TimeUnit._ import java.lang.{ Double ⇒ JDouble } import language.implicitConversions -object DurationImplicits { - trait Classifier[C] { - type R - def convert(d: FiniteDuration): R - } - - object span - implicit object spanConvert extends Classifier[span.type] { - type R = FiniteDuration - def convert(d: FiniteDuration) = d - } - - object fromNow - implicit object fromNowConvert extends Classifier[fromNow.type] { - type R = Deadline - def convert(d: FiniteDuration) = Deadline.now + d - } - - implicit def intToDurationInt(n: Int) = new DurationInt(n) - implicit def longToDurationLong(n: Long) = new DurationLong(n) - implicit def doubleToDurationDouble(d: Double) = new DurationDouble(d) - - implicit def pairIntToDuration(p: (Int, TimeUnit)) = Duration(p._1, p._2) - implicit def pairLongToDuration(p: (Long, TimeUnit)) = Duration(p._1, p._2) - implicit def durationToPair(d: Duration) = (d.length, d.unit) - - /* - * Avoid reflection based invocation by using non-duck type - */ - class IntMult(i: Int) { - def *(d: Duration) = d * i - } - implicit def intMult(i: Int) = new IntMult(i) - - class LongMult(l: Long) { - def *(d: Duration) = d * l - } - implicit def longMult(l: Long) = new LongMult(l) - - class DoubleMult(f: Double) { - def *(d: Duration) = d * f - } - implicit def doubleMult(f: Double) = new DoubleMult(f) -} - case class Deadline private (time: Duration) { def +(other: Duration): Deadline = copy(time = time + other) def -(other: Duration): Deadline = copy(time = time - other) @@ -72,10 +27,7 @@ object Duration { def apply(length: Long, unit: TimeUnit): FiniteDuration = new FiniteDuration(length, unit) def apply(length: Double, unit: TimeUnit): FiniteDuration = fromNanos(unit.toNanos(1) * length) - def apply(length: Long, unit: String): FiniteDuration = { - val (mult, timeUnit) = Duration.timeUnit(unit) - new FiniteDuration(length * mult, timeUnit) - } + def apply(length: Long, unit: String): FiniteDuration = new FiniteDuration(length, Duration.timeUnit(unit)) /** * Construct a Duration by parsing a String. In case of a format error, a @@ -118,11 +70,11 @@ object Duration { def unapply(s: String): Option[Duration] = s match { case RE(length, d, h, m, s, ms, mus, ns) ⇒ if (d ne null) - Some(Duration(JDouble.parseDouble(length) * 86400, SECONDS)) + Some(Duration(JDouble.parseDouble(length), DAYS)) else if (h ne null) - Some(Duration(JDouble.parseDouble(length) * 3600, SECONDS)) + Some(Duration(JDouble.parseDouble(length), HOURS)) else if (m ne null) - Some(Duration(JDouble.parseDouble(length) * 60, SECONDS)) + Some(Duration(JDouble.parseDouble(length), MINUTES)) else if (s ne null) Some(Duration(JDouble.parseDouble(length), SECONDS)) else if (ms ne null) @@ -143,11 +95,11 @@ object Duration { def fromNanos(nanos: Long): FiniteDuration = { if (nanos % 86400000000000L == 0) { - Duration(nanos / 1000000000L, SECONDS) - } else if (nanos % 1000000000L == 0) { - Duration(nanos / 1000000000L, SECONDS) - } else if (nanos % 1000000000L == 0) { - Duration(nanos / 1000000000L, SECONDS) + Duration(nanos / 86400000000000L, DAYS) + } else if (nanos % 3600000000000L == 0) { + Duration(nanos / 3600000000000L, HOURS) + } else if (nanos % 60000000000L == 0) { + Duration(nanos / 60000000000L, MINUTES) } else if (nanos % 1000000000L == 0) { Duration(nanos / 1000000000L, SECONDS) } else if (nanos % 1000000L == 0) { @@ -162,14 +114,14 @@ object Duration { /** * Parse TimeUnit from string representation. */ - protected[util] def timeUnit(unit: String): (Long, TimeUnit) = unit.toLowerCase match { - case "d" | "day" | "days" ⇒ (86400, SECONDS) - case "h" | "hour" | "hours" ⇒ (3600, SECONDS) - case "min" | "minute" | "minutes" ⇒ (60, SECONDS) - case "s" | "sec" | "second" | "seconds" ⇒ (1, SECONDS) - case "ms" | "milli" | "millis" | "millisecond" | "milliseconds" ⇒ (1, MILLISECONDS) - case "µs" | "micro" | "micros" | "microsecond" | "microseconds" ⇒ (1, MICROSECONDS) - case "ns" | "nano" | "nanos" | "nanosecond" | "nanoseconds" ⇒ (1, NANOSECONDS) + protected[util] def timeUnit(unit: String): TimeUnit = unit.toLowerCase match { + case "d" | "day" | "days" ⇒ DAYS + case "h" | "hour" | "hours" ⇒ HOURS + case "min" | "minute" | "minutes" ⇒ MINUTES + case "s" | "sec" | "second" | "seconds" ⇒ SECONDS + case "ms" | "milli" | "millis" | "millisecond" | "milliseconds" ⇒ MILLISECONDS + case "µs" | "micro" | "micros" | "microsecond" | "microseconds" ⇒ MICROSECONDS + case "ns" | "nano" | "nanos" | "nanosecond" | "nanoseconds" ⇒ NANOSECONDS } val Zero: FiniteDuration = new FiniteDuration(0, NANOSECONDS) @@ -329,13 +281,9 @@ object FiniteDuration { def compare(a: FiniteDuration, b: FiniteDuration) = a compare b } - def apply(length: Long, unit: TimeUnit) = - new FiniteDuration(length, unit) + def apply(length: Long, unit: TimeUnit) = new FiniteDuration(length, unit) - def apply(length: Long, unit: String) = { - val (mult, timeUnit) = Duration.timeUnit(unit) - new FiniteDuration(length * mult, timeUnit) - } + def apply(length: Long, unit: String) = new FiniteDuration(length, Duration.timeUnit(unit)) } @@ -352,6 +300,12 @@ class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duration { def toUnit(u: TimeUnit) = long2double(toNanos) / NANOSECONDS.convert(1, u) override def toString = this match { + case Duration(1, DAYS) ⇒ "1 day" + case Duration(x, DAYS) ⇒ x + " days" + case Duration(1, HOURS) ⇒ "1 hour" + case Duration(x, HOURS) ⇒ x + " hours" + case Duration(1, MINUTES) ⇒ "1 minute" + case Duration(x, MINUTES) ⇒ x + " minutes" case Duration(1, SECONDS) ⇒ "1 second" case Duration(x, SECONDS) ⇒ x + " seconds" case Duration(1, MILLISECONDS) ⇒ "1 millisecond" @@ -405,7 +359,7 @@ class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duration { } class DurationInt(n: Int) { - import DurationImplicits.Classifier + import duration.Classifier def nanoseconds = Duration(n, NANOSECONDS) def nanos = Duration(n, NANOSECONDS) @@ -425,14 +379,14 @@ class DurationInt(n: Int) { def seconds = Duration(n, SECONDS) def second = Duration(n, SECONDS) - def minutes = Duration(n * 60, SECONDS) - def minute = Duration(n * 60, SECONDS) + def minutes = Duration(n, MINUTES) + def minute = Duration(n, MINUTES) - def hours = Duration(n * 3600, SECONDS) - def hour = Duration(n * 3600, SECONDS) + def hours = Duration(n, HOURS) + def hour = Duration(n, HOURS) - def days = Duration(n * 86400, SECONDS) - def day = Duration(n * 86400, SECONDS) + def days = Duration(n, DAYS) + def day = Duration(n, DAYS) def nanoseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, NANOSECONDS)) def nanos[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, NANOSECONDS)) @@ -452,18 +406,18 @@ class DurationInt(n: Int) { def seconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, SECONDS)) def second[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, SECONDS)) - def minutes[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 60, SECONDS)) - def minute[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 60, SECONDS)) + def minutes[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MINUTES)) + def minute[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MINUTES)) - def hours[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 3600, SECONDS)) - def hour[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 3600, SECONDS)) + def hours[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, HOURS)) + def hour[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, HOURS)) - def days[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 86400, SECONDS)) - def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 86400, SECONDS)) + def days[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, DAYS)) + def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, DAYS)) } class DurationLong(n: Long) { - import DurationImplicits.Classifier + import duration.Classifier def nanoseconds = Duration(n, NANOSECONDS) def nanos = Duration(n, NANOSECONDS) @@ -483,14 +437,14 @@ class DurationLong(n: Long) { def seconds = Duration(n, SECONDS) def second = Duration(n, SECONDS) - def minutes = Duration(n * 60, SECONDS) - def minute = Duration(n * 60, SECONDS) + def minutes = Duration(n, MINUTES) + def minute = Duration(n, MINUTES) - def hours = Duration(n * 3600, SECONDS) - def hour = Duration(n * 3600, SECONDS) + def hours = Duration(n, HOURS) + def hour = Duration(n, HOURS) - def days = Duration(n * 86400, SECONDS) - def day = Duration(n * 86400, SECONDS) + def days = Duration(n, DAYS) + def day = Duration(n, DAYS) def nanoseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, NANOSECONDS)) def nanos[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, NANOSECONDS)) @@ -510,18 +464,18 @@ class DurationLong(n: Long) { def seconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, SECONDS)) def second[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, SECONDS)) - def minutes[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 60, SECONDS)) - def minute[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 60, SECONDS)) + def minutes[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MINUTES)) + def minute[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MINUTES)) - def hours[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 3600, SECONDS)) - def hour[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 3600, SECONDS)) + def hours[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, HOURS)) + def hour[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, HOURS)) - def days[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 86400, SECONDS)) - def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 86400, SECONDS)) + def days[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, DAYS)) + def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, DAYS)) } class DurationDouble(d: Double) { - import DurationImplicits.Classifier + import duration.Classifier def nanoseconds = Duration(d, NANOSECONDS) def nanos = Duration(d, NANOSECONDS) @@ -541,14 +495,14 @@ class DurationDouble(d: Double) { def seconds = Duration(d, SECONDS) def second = Duration(d, SECONDS) - def minutes = Duration(d * 60, SECONDS) - def minute = Duration(d * 60, SECONDS) + def minutes = Duration(d, MINUTES) + def minute = Duration(d, MINUTES) - def hours = Duration(d * 3600, SECONDS) - def hour = Duration(d * 3600, SECONDS) + def hours = Duration(d, HOURS) + def hour = Duration(d, HOURS) - def days = Duration(d * 86400, SECONDS) - def day = Duration(d * 86400, SECONDS) + def days = Duration(d, DAYS) + def day = Duration(d, DAYS) def nanoseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, NANOSECONDS)) def nanos[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, NANOSECONDS)) @@ -568,12 +522,12 @@ class DurationDouble(d: Double) { def seconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, SECONDS)) def second[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, SECONDS)) - def minutes[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d * 60, SECONDS)) - def minute[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d * 60, SECONDS)) + def minutes[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, MINUTES)) + def minute[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, MINUTES)) - def hours[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d * 3600, SECONDS)) - def hour[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d * 3600, SECONDS)) + def hours[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, HOURS)) + def hour[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, HOURS)) - def days[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d * 86400, SECONDS)) - def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d * 86400, SECONDS)) + def days[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, DAYS)) + def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, DAYS)) } diff --git a/src/library/scala/concurrent/util/duration/Classifier.scala b/src/library/scala/concurrent/util/duration/Classifier.scala new file mode 100644 index 0000000000..10faf0a5ce --- /dev/null +++ b/src/library/scala/concurrent/util/duration/Classifier.scala @@ -0,0 +1,9 @@ +package scala.concurrent.util.duration + +import scala.concurrent.util.{ FiniteDuration } + +trait Classifier[C] { + type R + def convert(d: FiniteDuration): R +} + diff --git a/src/library/scala/concurrent/util/duration/IntMult.scala b/src/library/scala/concurrent/util/duration/IntMult.scala new file mode 100644 index 0000000000..94c58fb8c2 --- /dev/null +++ b/src/library/scala/concurrent/util/duration/IntMult.scala @@ -0,0 +1,18 @@ +package scala.concurrent.util.duration + +import scala.concurrent.util.{ Duration } + +/* + * Avoid reflection based invocation by using non-duck type + */ +protected[duration] class IntMult(i: Int) { + def *(d: Duration) = d * i +} + +protected[duration] class LongMult(i: Long) { + def *(d: Duration) = d * i +} + +protected[duration] class DoubleMult(f: Double) { + def *(d: Duration) = d * f +} diff --git a/src/library/scala/concurrent/util/duration/package.scala b/src/library/scala/concurrent/util/duration/package.scala new file mode 100644 index 0000000000..25625054ee --- /dev/null +++ b/src/library/scala/concurrent/util/duration/package.scala @@ -0,0 +1,30 @@ +package scala.concurrent.util + +import java.util.concurrent.TimeUnit + +package object duration { + + object span + implicit object spanConvert extends Classifier[span.type] { + type R = FiniteDuration + def convert(d: FiniteDuration) = d + } + + object fromNow + implicit object fromNowConvert extends Classifier[fromNow.type] { + type R = Deadline + def convert(d: FiniteDuration) = Deadline.now + d + } + + implicit def intToDurationInt(n: Int) = new DurationInt(n) + implicit def longToDurationLong(n: Long) = new DurationLong(n) + implicit def doubleToDurationDouble(d: Double) = new DurationDouble(d) + + implicit def pairIntToDuration(p: (Int, TimeUnit)) = Duration(p._1, p._2) + implicit def pairLongToDuration(p: (Long, TimeUnit)) = Duration(p._1, p._2) + implicit def durationToPair(d: Duration) = (d.length, d.unit) + + implicit def intMult(i: Int) = new IntMult(i) + implicit def longMult(l: Long) = new LongMult(l) + implicit def doubleMult(f: Double) = new DoubleMult(f) +}
\ No newline at end of file diff --git a/src/library/scala/reflect/ArrayTags.scala b/src/library/scala/reflect/ArrayTag.scala index 8df7fe5f4e..8df7fe5f4e 100644 --- a/src/library/scala/reflect/ArrayTags.scala +++ b/src/library/scala/reflect/ArrayTag.scala diff --git a/src/library/scala/reflect/ClassTags.scala b/src/library/scala/reflect/ClassTag.scala index 7138837f0d..7138837f0d 100644 --- a/src/library/scala/reflect/ClassTags.scala +++ b/src/library/scala/reflect/ClassTag.scala diff --git a/src/library/scala/reflect/api/Attachments.scala b/src/library/scala/reflect/api/Attachment.scala index dfd362ebe0..dfd362ebe0 100644 --- a/src/library/scala/reflect/api/Attachments.scala +++ b/src/library/scala/reflect/api/Attachment.scala diff --git a/src/library/scala/reflect/api/StandardNames.scala b/src/library/scala/reflect/api/StandardNames.scala index bfc165f613..d2110ede75 100644 --- a/src/library/scala/reflect/api/StandardNames.scala +++ b/src/library/scala/reflect/api/StandardNames.scala @@ -93,18 +93,13 @@ trait StandardNames { self: Universe => val ZOR: TermName // [Eugene] this doesn't compile. why?! -// val UNARY_~: TermName -// val UNARY_+: TermName -// val UNARY_-: TermName -// val UNARY_!: TermName - val UNARY_TILDE: TermName - val UNARY_PLUS: TermName - val UNARY_MINUS: TermName - val UNARY_NOT: TermName + val UNARY_~ : TermName + val UNARY_+ : TermName + val UNARY_- : TermName + val UNARY_! : TermName // [Eugene] this doesn't compile. why?! -// val ???: TermName - val QQQ: TermName + val ??? : TermName val MODULE_SUFFIX_NAME: TermName val NAME_JOIN_NAME: TermName diff --git a/src/library/scala/reflect/makro/internal/typeTagImpl.scala b/src/library/scala/reflect/makro/internal/Utils.scala index db658fd637..db658fd637 100644 --- a/src/library/scala/reflect/makro/internal/typeTagImpl.scala +++ b/src/library/scala/reflect/makro/internal/Utils.scala |