From 5b73e75943dd89dabda84b0fc3a651837c4a2113 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 21 Apr 2015 14:49:58 +0200 Subject: Remove scala.actors and the actors migration module dependency --- src/actors/scala/actors/AbstractActor.scala | 30 - src/actors/scala/actors/Actor.scala | 411 ---- src/actors/scala/actors/ActorCanReply.scala | 66 - src/actors/scala/actors/ActorProxy.scala | 34 - src/actors/scala/actors/ActorRef.scala | 53 - src/actors/scala/actors/ActorTask.scala | 60 - src/actors/scala/actors/CanReply.scala | 65 - src/actors/scala/actors/Channel.scala | 136 -- src/actors/scala/actors/Combinators.scala | 48 - src/actors/scala/actors/DaemonActor.scala | 24 - src/actors/scala/actors/Debug.scala | 45 - src/actors/scala/actors/Future.scala | 243 --- src/actors/scala/actors/IScheduler.scala | 70 - src/actors/scala/actors/InputChannel.scala | 66 - src/actors/scala/actors/InternalActor.scala | 546 ------ src/actors/scala/actors/InternalReplyReactor.scala | 162 -- src/actors/scala/actors/KillActorControl.scala | 14 - src/actors/scala/actors/LinkedNode.java | 25 - src/actors/scala/actors/LinkedQueue.java | 185 -- src/actors/scala/actors/MQueue.scala | 250 --- src/actors/scala/actors/OutputChannel.scala | 48 - src/actors/scala/actors/ReactChannel.scala | 121 -- src/actors/scala/actors/Reactor.scala | 307 --- src/actors/scala/actors/ReactorCanReply.scala | 90 - src/actors/scala/actors/ReactorTask.scala | 74 - src/actors/scala/actors/ReplyReactor.scala | 13 - src/actors/scala/actors/ReplyReactorTask.scala | 40 - src/actors/scala/actors/Scheduler.scala | 40 - src/actors/scala/actors/SchedulerAdapter.scala | 68 - src/actors/scala/actors/UncaughtException.scala | 34 - src/actors/scala/actors/package.scala | 23 - .../scala/actors/remote/FreshNameCreator.scala | 36 - .../scala/actors/remote/JavaSerializer.scala | 63 - src/actors/scala/actors/remote/NetKernel.scala | 147 -- src/actors/scala/actors/remote/Proxy.scala | 190 -- src/actors/scala/actors/remote/RemoteActor.scala | 132 -- src/actors/scala/actors/remote/Serializer.scala | 58 - src/actors/scala/actors/remote/Service.scala | 24 - src/actors/scala/actors/remote/TcpService.scala | 292 --- src/actors/scala/actors/scheduler/ActorGC.scala | 101 - .../scala/actors/scheduler/DaemonScheduler.scala | 34 - .../actors/scheduler/DelegatingScheduler.scala | 74 - .../actors/scheduler/DrainableForkJoinPool.scala | 11 - .../scala/actors/scheduler/ExecutorScheduler.scala | 95 - .../scala/actors/scheduler/ForkJoinScheduler.scala | 174 -- .../scala/actors/scheduler/QuitControl.scala | 19 - .../scheduler/ResizableThreadPoolScheduler.scala | 197 -- .../actors/scheduler/SingleThreadedScheduler.scala | 69 - .../actors/scheduler/TerminationMonitor.scala | 69 - .../actors/scheduler/TerminationService.scala | 68 - .../scala/actors/scheduler/ThreadPoolConfig.scala | 50 - .../actors/threadpool/AbstractCollection.java | 32 - .../actors/threadpool/AbstractExecutorService.java | 292 --- .../scala/actors/threadpool/AbstractQueue.java | 170 -- src/actors/scala/actors/threadpool/Arrays.java | 811 -------- .../scala/actors/threadpool/AtomicInteger.java | 210 --- .../scala/actors/threadpool/BlockingQueue.java | 344 ---- src/actors/scala/actors/threadpool/Callable.java | 35 - .../actors/threadpool/CancellationException.java | 34 - .../scala/actors/threadpool/CompletionService.java | 97 - .../actors/threadpool/ExecutionException.java | 65 - src/actors/scala/actors/threadpool/Executor.java | 112 -- .../threadpool/ExecutorCompletionService.java | 178 -- .../scala/actors/threadpool/ExecutorService.java | 331 ---- src/actors/scala/actors/threadpool/Executors.java | 667 ------- src/actors/scala/actors/threadpool/Future.java | 142 -- src/actors/scala/actors/threadpool/FutureTask.java | 310 --- .../actors/threadpool/LinkedBlockingQueue.java | 843 --------- src/actors/scala/actors/threadpool/Perf.java | 28 - src/actors/scala/actors/threadpool/Queue.java | 191 -- .../threadpool/RejectedExecutionException.java | 62 - .../threadpool/RejectedExecutionHandler.java | 34 - .../scala/actors/threadpool/RunnableFuture.java | 24 - .../scala/actors/threadpool/SynchronousQueue.java | 833 --------- .../scala/actors/threadpool/ThreadFactory.java | 41 - .../actors/threadpool/ThreadPoolExecutor.java | 1968 -------------------- src/actors/scala/actors/threadpool/TimeUnit.java | 407 ---- .../scala/actors/threadpool/TimeoutException.java | 38 - .../actors/threadpool/helpers/FIFOWaitQueue.java | 85 - .../scala/actors/threadpool/helpers/NanoTimer.java | 29 - .../actors/threadpool/helpers/ThreadHelpers.java | 66 - .../scala/actors/threadpool/helpers/Utils.java | 343 ---- .../scala/actors/threadpool/helpers/WaitQueue.java | 146 -- .../scala/actors/threadpool/locks/CondVar.java | 191 -- .../scala/actors/threadpool/locks/Condition.java | 434 ----- .../scala/actors/threadpool/locks/FIFOCondVar.java | 147 -- src/actors/scala/actors/threadpool/locks/Lock.java | 328 ---- .../actors/threadpool/locks/ReadWriteLock.java | 104 -- .../actors/threadpool/locks/ReentrantLock.java | 959 ---------- .../threadpool/locks/ReentrantReadWriteLock.java | 1341 ------------- src/build/bnd/scala-actors.bnd | 7 - src/build/dbuild-meta-json-gen.scala | 4 - src/build/maven/scala-actors-pom.xml | 51 - src/build/maven/scala-library-all-pom.xml | 5 - src/intellij-14/actors.iml.SAMPLE | 14 - src/intellij-14/scala.ipr.SAMPLE | 1 - src/intellij-14/test-junit.iml.SAMPLE | 1 - src/intellij-14/test.iml.SAMPLE | 1 - src/intellij/actors.iml.SAMPLE | 25 - src/intellij/scala-lang.ipr.SAMPLE | 1 - src/intellij/test-junit.iml.SAMPLE | 1 - src/intellij/test-osgi.iml.SAMPLE | 1 - src/intellij/test.iml.SAMPLE | 1 - src/library/rootdoc.txt | 2 - 104 files changed, 17881 deletions(-) delete mode 100644 src/actors/scala/actors/AbstractActor.scala delete mode 100644 src/actors/scala/actors/Actor.scala delete mode 100644 src/actors/scala/actors/ActorCanReply.scala delete mode 100644 src/actors/scala/actors/ActorProxy.scala delete mode 100644 src/actors/scala/actors/ActorRef.scala delete mode 100644 src/actors/scala/actors/ActorTask.scala delete mode 100644 src/actors/scala/actors/CanReply.scala delete mode 100644 src/actors/scala/actors/Channel.scala delete mode 100644 src/actors/scala/actors/Combinators.scala delete mode 100644 src/actors/scala/actors/DaemonActor.scala delete mode 100644 src/actors/scala/actors/Debug.scala delete mode 100644 src/actors/scala/actors/Future.scala delete mode 100644 src/actors/scala/actors/IScheduler.scala delete mode 100644 src/actors/scala/actors/InputChannel.scala delete mode 100644 src/actors/scala/actors/InternalActor.scala delete mode 100644 src/actors/scala/actors/InternalReplyReactor.scala delete mode 100644 src/actors/scala/actors/KillActorControl.scala delete mode 100644 src/actors/scala/actors/LinkedNode.java delete mode 100644 src/actors/scala/actors/LinkedQueue.java delete mode 100644 src/actors/scala/actors/MQueue.scala delete mode 100644 src/actors/scala/actors/OutputChannel.scala delete mode 100644 src/actors/scala/actors/ReactChannel.scala delete mode 100644 src/actors/scala/actors/Reactor.scala delete mode 100644 src/actors/scala/actors/ReactorCanReply.scala delete mode 100644 src/actors/scala/actors/ReactorTask.scala delete mode 100644 src/actors/scala/actors/ReplyReactor.scala delete mode 100644 src/actors/scala/actors/ReplyReactorTask.scala delete mode 100644 src/actors/scala/actors/Scheduler.scala delete mode 100644 src/actors/scala/actors/SchedulerAdapter.scala delete mode 100644 src/actors/scala/actors/UncaughtException.scala delete mode 100644 src/actors/scala/actors/package.scala delete mode 100644 src/actors/scala/actors/remote/FreshNameCreator.scala delete mode 100644 src/actors/scala/actors/remote/JavaSerializer.scala delete mode 100644 src/actors/scala/actors/remote/NetKernel.scala delete mode 100644 src/actors/scala/actors/remote/Proxy.scala delete mode 100644 src/actors/scala/actors/remote/RemoteActor.scala delete mode 100644 src/actors/scala/actors/remote/Serializer.scala delete mode 100644 src/actors/scala/actors/remote/Service.scala delete mode 100644 src/actors/scala/actors/remote/TcpService.scala delete mode 100644 src/actors/scala/actors/scheduler/ActorGC.scala delete mode 100644 src/actors/scala/actors/scheduler/DaemonScheduler.scala delete mode 100644 src/actors/scala/actors/scheduler/DelegatingScheduler.scala delete mode 100644 src/actors/scala/actors/scheduler/DrainableForkJoinPool.scala delete mode 100644 src/actors/scala/actors/scheduler/ExecutorScheduler.scala delete mode 100644 src/actors/scala/actors/scheduler/ForkJoinScheduler.scala delete mode 100644 src/actors/scala/actors/scheduler/QuitControl.scala delete mode 100644 src/actors/scala/actors/scheduler/ResizableThreadPoolScheduler.scala delete mode 100644 src/actors/scala/actors/scheduler/SingleThreadedScheduler.scala delete mode 100644 src/actors/scala/actors/scheduler/TerminationMonitor.scala delete mode 100644 src/actors/scala/actors/scheduler/TerminationService.scala delete mode 100644 src/actors/scala/actors/scheduler/ThreadPoolConfig.scala delete mode 100644 src/actors/scala/actors/threadpool/AbstractCollection.java delete mode 100644 src/actors/scala/actors/threadpool/AbstractExecutorService.java delete mode 100644 src/actors/scala/actors/threadpool/AbstractQueue.java delete mode 100644 src/actors/scala/actors/threadpool/Arrays.java delete mode 100644 src/actors/scala/actors/threadpool/AtomicInteger.java delete mode 100644 src/actors/scala/actors/threadpool/BlockingQueue.java delete mode 100644 src/actors/scala/actors/threadpool/Callable.java delete mode 100644 src/actors/scala/actors/threadpool/CancellationException.java delete mode 100644 src/actors/scala/actors/threadpool/CompletionService.java delete mode 100644 src/actors/scala/actors/threadpool/ExecutionException.java delete mode 100644 src/actors/scala/actors/threadpool/Executor.java delete mode 100644 src/actors/scala/actors/threadpool/ExecutorCompletionService.java delete mode 100644 src/actors/scala/actors/threadpool/ExecutorService.java delete mode 100644 src/actors/scala/actors/threadpool/Executors.java delete mode 100644 src/actors/scala/actors/threadpool/Future.java delete mode 100644 src/actors/scala/actors/threadpool/FutureTask.java delete mode 100644 src/actors/scala/actors/threadpool/LinkedBlockingQueue.java delete mode 100644 src/actors/scala/actors/threadpool/Perf.java delete mode 100644 src/actors/scala/actors/threadpool/Queue.java delete mode 100644 src/actors/scala/actors/threadpool/RejectedExecutionException.java delete mode 100644 src/actors/scala/actors/threadpool/RejectedExecutionHandler.java delete mode 100644 src/actors/scala/actors/threadpool/RunnableFuture.java delete mode 100644 src/actors/scala/actors/threadpool/SynchronousQueue.java delete mode 100644 src/actors/scala/actors/threadpool/ThreadFactory.java delete mode 100644 src/actors/scala/actors/threadpool/ThreadPoolExecutor.java delete mode 100644 src/actors/scala/actors/threadpool/TimeUnit.java delete mode 100644 src/actors/scala/actors/threadpool/TimeoutException.java delete mode 100644 src/actors/scala/actors/threadpool/helpers/FIFOWaitQueue.java delete mode 100644 src/actors/scala/actors/threadpool/helpers/NanoTimer.java delete mode 100644 src/actors/scala/actors/threadpool/helpers/ThreadHelpers.java delete mode 100644 src/actors/scala/actors/threadpool/helpers/Utils.java delete mode 100644 src/actors/scala/actors/threadpool/helpers/WaitQueue.java delete mode 100644 src/actors/scala/actors/threadpool/locks/CondVar.java delete mode 100644 src/actors/scala/actors/threadpool/locks/Condition.java delete mode 100644 src/actors/scala/actors/threadpool/locks/FIFOCondVar.java delete mode 100644 src/actors/scala/actors/threadpool/locks/Lock.java delete mode 100644 src/actors/scala/actors/threadpool/locks/ReadWriteLock.java delete mode 100644 src/actors/scala/actors/threadpool/locks/ReentrantLock.java delete mode 100644 src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java delete mode 100644 src/build/bnd/scala-actors.bnd delete mode 100644 src/build/maven/scala-actors-pom.xml delete mode 100644 src/intellij-14/actors.iml.SAMPLE delete mode 100644 src/intellij/actors.iml.SAMPLE (limited to 'src') diff --git a/src/actors/scala/actors/AbstractActor.scala b/src/actors/scala/actors/AbstractActor.scala deleted file mode 100644 index 28fe689e91..0000000000 --- a/src/actors/scala/actors/AbstractActor.scala +++ /dev/null @@ -1,30 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.actors - -import scala.language.higherKinds - -/** - * @author Philipp Haller - * - * @define actor actor - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -trait AbstractActor extends OutputChannel[Any] with CanReply[Any, Any] { - - type Future[+R] <: scala.actors.Future[R] - - private[actors] def exiting: Boolean = false - - private[actors] def linkTo(to: AbstractActor): Unit - - private[actors] def unlinkFrom(from: AbstractActor): Unit - - private[actors] def exit(from: AbstractActor, reason: AnyRef): Unit -} diff --git a/src/actors/scala/actors/Actor.scala b/src/actors/scala/actors/Actor.scala deleted file mode 100644 index 293335f720..0000000000 --- a/src/actors/scala/actors/Actor.scala +++ /dev/null @@ -1,411 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.actors - -import scala.util.control.ControlThrowable -import java.util.{Timer, TimerTask} -import scala.language.implicitConversions - -/** - * Provides functions for the definition of actors, as well as actor - * operations, such as `receive`, `react`, `reply`, etc. - * - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -object Actor extends Combinators { - - /** State of an actor. - * - * - '''New''' - - * Not yet started - * - '''Runnable''' - - * Executing - * - '''Suspended''' - - * Suspended, waiting in a `react` - * - '''TimedSuspended''' - - * Suspended, waiting in a `reactWithin` - * - '''Blocked''' - - * Blocked waiting in a `receive` - * - '''TimedBlocked''' - - * Blocked waiting in a `receiveWithin` - * - '''Terminated''' - - * Actor has terminated - */ - object State extends Enumeration { - val New, - Runnable, - Suspended, - TimedSuspended, - Blocked, - TimedBlocked, - Terminated = Value - } - - private[actors] val tl = new ThreadLocal[InternalReplyReactor] - - // timer thread runs as daemon - private[actors] val timer = new Timer(true) - - private[actors] val suspendException = new SuspendActorControl - - /** - * Returns the currently executing actor. Should be used instead - * of `'''this'''` in all blocks of code executed by actors. - * - * @return returns the currently executing actor. - */ - def self: Actor = self(Scheduler).asInstanceOf[Actor] - - private[actors] def self(sched: IScheduler): InternalActor = - rawSelf(sched).asInstanceOf[InternalActor] - - private[actors] def rawSelf: InternalReplyReactor = - rawSelf(Scheduler) - - private[actors] def rawSelf(sched: IScheduler): InternalReplyReactor = { - val s = tl.get - if (s eq null) { - val r = new ActorProxy(Thread.currentThread, sched) - tl.set(r) - r - } else - s - } - - private def parentScheduler: IScheduler = { - val s = tl.get - if (s eq null) Scheduler else s.scheduler - } - - /** - * Resets an actor proxy associated with the current thread. - * It replaces the implicit `ActorProxy` instance - * of the current thread (if any) with a new instance. - * - * This permits to re-use the current thread as an actor - * even if its `ActorProxy` has died for some reason. - */ - def resetProxy() { - val a = tl.get - if ((null ne a) && a.isInstanceOf[ActorProxy]) - tl.set(new ActorProxy(Thread.currentThread, parentScheduler)) - } - - /** - * Removes any reference to an `Actor` instance - * currently stored in thread-local storage. - * - * This allows to release references from threads that are potentially - * long-running or being re-used (e.g. inside a thread pool). Permanent - * references in thread-local storage are a potential memory leak. - */ - def clearSelf() { - tl set null - } - - /** - * Factory method for creating and starting an actor. - * - * @example {{{ - * import scala.actors.Actor._ - * ... - * val a = actor { - * ... - * } - * }}} - * - * @param body the code block to be executed by the newly created actor - * @return the newly created actor. Note that it is automatically started. - */ - def actor(body: => Unit): Actor = { - val a = new Actor { - def act() = body - override final val scheduler: IScheduler = parentScheduler - } - a.start() - a - } - - /** - * Factory method for creating actors whose - * body is defined using a `Responder`. - * - * @example {{{ - * import scala.actors.Actor._ - * import Responder.exec - * ... - * val a = reactor { - * for { - * res <- b !! MyRequest; - * if exec(println("result: "+res)) - * } yield {} - * } - * }}} - * - * @param body the `Responder` to be executed by the newly created actor - * @return the newly created actor. Note that it is automatically started. - */ - def reactor(body: => Responder[Unit]): Actor = { - val a = new Actor { - def act() { - Responder.run(body) - } - override final val scheduler: IScheduler = parentScheduler - } - a.start() - a - } - - /** - * Receives the next message from the mailbox of the current actor `self`. - */ - def ? : Any = self.? - - /** - * Receives a message from the mailbox of `self`. Blocks if no message - * matching any of the cases of `f` can be received. - * - * @example {{{ - * receive { - * case "exit" => println("exiting") - * case 42 => println("got the answer") - * case x:Int => println("got an answer") - * } - * }}} - * - * @param f a partial function specifying patterns and actions - * @return the result of processing the received message - */ - def receive[A](f: PartialFunction[Any, A]): A = - self.receive(f) - - /** - * Receives a message from the mailbox of `self`. Blocks at most `msec` - * milliseconds if no message matching any of the cases of `f` can be - * received. If no message could be received the `TIMEOUT` action is - * executed if specified. - * - * @param msec the time span before timeout - * @param f a partial function specifying patterns and actions - * @return the result of processing the received message - */ - def receiveWithin[R](msec: Long)(f: PartialFunction[Any, R]): R = - self.receiveWithin(msec)(f) - - /** - * Lightweight variant of `receive`. - * - * Actions in `f` have to contain the rest of the computation of `self`, - * as this method will never return. - * - * A common method of continuing the computation is to send a message - * to another actor: - * {{{ - * react { - * case Get(from) => - * react { - * case Put(x) => from ! x - * } - * } - * }}} - * - * Another common method is to use `loop` to continuously `react` to messages: - * {{{ - * loop { - * react { - * case Msg(data) => // process data - * } - * } - * }}} - * - * @param f a partial function specifying patterns and actions - * @return this function never returns - */ - def react(f: PartialFunction[Any, Unit]): Nothing = - rawSelf.react(f) - - /** - * Lightweight variant of `receiveWithin`. - * - * Actions in `f` have to contain the rest of the computation of `self`, - * as this method will never return. - * - * @param msec the time span before timeout - * @param f a partial function specifying patterns and actions - * @return this function never returns - */ - def reactWithin(msec: Long)(f: PartialFunction[Any, Unit]): Nothing = - self.reactWithin(msec)(f) - - def eventloop(f: PartialFunction[Any, Unit]): Nothing = - rawSelf.react(new RecursiveProxyHandler(rawSelf, f)) - - private class RecursiveProxyHandler(a: InternalReplyReactor, f: PartialFunction[Any, Unit]) - extends PartialFunction[Any, Unit] { - def isDefinedAt(m: Any): Boolean = - true // events are immediately removed from the mailbox - def apply(m: Any) { - if (f.isDefinedAt(m)) f(m) - a.react(this) - } - } - - /** - * Returns the actor which sent the last received message. - */ - def sender: OutputChannel[Any] = - rawSelf.internalSender - - /** - * Sends `msg` to the actor waiting in a call to `!?`. - */ - def reply(msg: Any): Unit = - rawSelf.reply(msg) - - /** - * Sends `()` to the actor waiting in a call to `!?`. - */ - def reply(): Unit = - rawSelf.reply(()) - - /** - * Returns the number of messages in `self`'s mailbox - * - * @return the number of messages in `self`'s mailbox - */ - def mailboxSize: Int = rawSelf.mailboxSize - - /** - * Converts a synchronous event-based operation into - * an asynchronous `Responder`. - * - * @example {{{ - * val adder = reactor { - * for { - * _ <- respondOn(react) { case Add(a, b) => reply(a+b) } - * } yield {} - * } - * }}} - */ - def respondOn[A, B](fun: PartialFunction[A, Unit] => Nothing): - PartialFunction[A, B] => Responder[B] = - (caseBlock: PartialFunction[A, B]) => new Responder[B] { - def respond(k: B => Unit) = fun(caseBlock andThen k) - } - - private[actors] trait Body[a] { - def andThen[b](other: => b): Unit - } - - implicit def mkBody[a](body: => a) = new InternalActor.Body[a] { - def andThen[b](other: => b): Unit = rawSelf.seq(body, other) - } - - /** - * Links `self` to actor `to`. - * - * @param to the actor to link to - * @return the parameter actor - */ - def link(to: AbstractActor): AbstractActor = self.link(to) - - /** - * Links `self` to the actor defined by `body`. - * - * @param body the body of the actor to link to - * @return the parameter actor - */ - def link(body: => Unit): Actor = self.link(body) - - /** - * Unlinks `self` from actor `from`. - * - * @param from the actor to unlink from - */ - def unlink(from: AbstractActor): Unit = self.unlink(from) - - /** - * Terminates execution of `self` with the following effect on - * linked actors: - * - * For each linked actor `a` with `trapExit` set to `'''true'''`, - * send message `Exit(self, reason)` to `a`. - * - * For each linked actor `a` with `trapExit` set to `'''false'''` - * (default), call `a.exit(reason)` if `reason != 'normal`. - */ - def exit(reason: AnyRef): Nothing = self.exit(reason) - - /** - * Terminates execution of `self` with the following effect on - * linked actors: - * - * For each linked actor `a` with `trapExit` set to `'''true'''`, - * send message `Exit(self, 'normal)` to `a`. - */ - def exit(): Nothing = rawSelf.exit() - -} - -/** Provides lightweight, concurrent actors. Actors are created by extending - * the `Actor` trait (alternatively, one of the factory methods in its - * companion object can be used). The behavior of an `Actor` subclass is - * defined by implementing its `act` method: - * {{{ - * class MyActor extends Actor { - * def act() { - * // actor behavior goes here - * } - * } - * }}} - * A new `Actor` instance is started by invoking its `start` method. - * - * '''Note:''' care must be taken when invoking thread-blocking methods other - * than those provided by the `Actor` trait or its companion object (such as - * `receive`). Blocking the underlying thread inside an actor may lead to - * starvation of other actors. This also applies to actors hogging their - * thread for a long time between invoking `receive`/`react`. - * - * If actors use blocking operations (for example, methods for blocking I/O), - * there are several options: - * - * - The run-time system can be configured to use a larger thread pool size - * (for example, by setting the `actors.corePoolSize` JVM property). - * - The `scheduler` method of the `Actor` trait can be overridden to return a - * `ResizableThreadPoolScheduler`, which resizes its thread pool to - * avoid starvation caused by actors that invoke arbitrary blocking methods. - * - The `actors.enableForkJoin` JVM property can be set to `false`, in which - * case a `ResizableThreadPoolScheduler` is used by default to execute actors. - * - * The main ideas of the implementation are explained in the two papers - * - * - [[http://lampwww.epfl.ch/~odersky/papers/jmlc06.pdf Event-Based - * Programming without Inversion of Control]], - * Philipp Haller and Martin Odersky, ''Proc. JMLC 2006'', and - * - [[http://lamp.epfl.ch/~phaller/doc/haller07coord.pdf Actors that - * Unify Threads and Events]], - * Philipp Haller and Martin Odersky, ''Proc. COORDINATION 2007''. - * - * @author Philipp Haller - * - * @define actor actor - * @define channel actor's mailbox - */ -@SerialVersionUID(-781154067877019505L) -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -trait Actor extends InternalActor with ReplyReactor { - - override def start(): Actor = synchronized { - super.start() - this - } - - } - diff --git a/src/actors/scala/actors/ActorCanReply.scala b/src/actors/scala/actors/ActorCanReply.scala deleted file mode 100644 index 07191ec65c..0000000000 --- a/src/actors/scala/actors/ActorCanReply.scala +++ /dev/null @@ -1,66 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors - -import scala.concurrent.SyncVar - -/** - * Provides message send operations that - * may result in a response from the receiver. - * - * @author Philipp Haller - */ -private[actors] trait ActorCanReply extends ReactorCanReply { - this: AbstractActor with InternalReplyReactor => - - override def !?(msg: Any): Any = { - val replyCh = new Channel[Any](Actor.self(scheduler)) - send(msg, replyCh) - replyCh.? - } - - override def !?(msec: Long, msg: Any): Option[Any] = { - val replyCh = new Channel[Any](Actor.self(scheduler)) - send(msg, replyCh) - replyCh.receiveWithin(msec) { - case TIMEOUT => None - case x => Some(x) - } - } - - override def !![A](msg: Any, handler: PartialFunction[Any, A]): Future[A] = { - val c = new Channel[A](Actor.self(scheduler)) - val fun = (res: SyncVar[A]) => { - val ftch = new Channel[A](Actor.self(scheduler)) - send(msg, new OutputChannel[Any] { - def !(msg: Any) = - ftch ! handler(msg) - def send(msg: Any, replyTo: OutputChannel[Any]) = - ftch.send(handler(msg), replyTo) - def forward(msg: Any) = - ftch.forward(handler(msg)) - def receiver = - ftch.receiver - }) - ftch.react { - case any => res.set(any) - } - } - val a = new FutureActor[A](fun, c) - a.start() - a - } - - override def !!(msg: Any): Future[Any] = { - val noTransform: PartialFunction[Any, Any] = { case x => x } - this !! (msg, noTransform) - } - -} diff --git a/src/actors/scala/actors/ActorProxy.scala b/src/actors/scala/actors/ActorProxy.scala deleted file mode 100644 index 5e1d3e61de..0000000000 --- a/src/actors/scala/actors/ActorProxy.scala +++ /dev/null @@ -1,34 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors - -import java.lang.Thread - -/** - * Provides a dynamic actor proxy for normal Java threads. - * - * @author Philipp Haller - */ -private[actors] class ActorProxy(t: Thread, override final val scheduler: IScheduler) extends Actor { - - def act() {} - - /** - * Terminates with exit reason `'normal`. - */ - override def exit(): Nothing = { - shouldExit = false - // links - if (!links.isEmpty) - exitLinked() - throw new InterruptedException - } - -} diff --git a/src/actors/scala/actors/ActorRef.scala b/src/actors/scala/actors/ActorRef.scala deleted file mode 100644 index 0da167aede..0000000000 --- a/src/actors/scala/actors/ActorRef.scala +++ /dev/null @@ -1,53 +0,0 @@ -package scala.actors - -import java.util.concurrent.TimeoutException -import scala.concurrent.duration.Duration - -/** - * Trait used for migration of Scala actors to Akka. - */ -@deprecated("ActorRef ought to be used only with the Actor Migration Kit.", "2.10.0") -trait ActorRef { - - /** - * Sends a one-way asynchronous message. E.g. fire-and-forget semantics. - *

- * - * If invoked from within an actor then the actor reference is implicitly passed on as the implicit 'sender' argument. - *

- * - * This actor 'sender' reference is then available in the receiving actor in the 'sender' member variable, - * if invoked from within an Actor. If not then no sender is available. - *

-   *   actor ! message
-   * 
- *

- */ - def !(message: Any)(implicit sender: ActorRef = null): Unit - - /** - * Sends a message asynchronously, returning a future which may eventually hold the reply. - */ - private[actors] def ?(message: Any, timeout: Duration): scala.concurrent.Future[Any] - - /** - * Forwards the message and passes the original sender actor as the sender. - *

- * Works with '!' and '?'. - */ - def forward(message: Any) - - private[actors] def localActor: AbstractActor - -} - -/** - * This is what is used to complete a Future that is returned from an ask/? call, - * when it times out. - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -class AskTimeoutException(message: String, cause: Throwable) extends TimeoutException { - def this(message: String) = this(message, null: Throwable) -} -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -object PoisonPill diff --git a/src/actors/scala/actors/ActorTask.scala b/src/actors/scala/actors/ActorTask.scala deleted file mode 100644 index 21d7a0a1ad..0000000000 --- a/src/actors/scala/actors/ActorTask.scala +++ /dev/null @@ -1,60 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.actors - -/** - * @author Philipp Haller - * @note This class inherits a public var called 'msg' from ReactorTask, - * and also defines a constructor parameter which shadows it (which makes any - * changes to the underlying var invisible.) I can't figure out what's supposed - * to happen, so I renamed the constructor parameter to at least be less confusing. - */ -private[actors] class ActorTask(actor: InternalActor, - fun: () => Unit, - handler: PartialFunction[Any, Any], - initialMsg: Any) - extends ReplyReactorTask(actor, fun, handler, initialMsg) { - - protected override def beginExecution() { - super.beginExecution() - actor.synchronized { // shouldExit guarded by actor - if (actor.shouldExit) - actor.exit() - } - } - - protected override def terminateExecution(e: Throwable) { - val senderInfo = try { Some(actor.internalSender) } catch { - case _: Exception => None - } - // !!! If this is supposed to be setting the current contents of the - // inherited mutable var rather than always the value given in the constructor, - // then it should be changed from initialMsg to msg. - val uncaught = UncaughtException(actor, - if (initialMsg != null) Some(initialMsg) else None, - senderInfo, - Thread.currentThread, - e) - - val todo = actor.synchronized { - val res = if (!actor.links.isEmpty) - actor.exitLinked(uncaught) - else { - super.terminateExecution(e) - () => {} - } - res - } - - todo() - } - -} diff --git a/src/actors/scala/actors/CanReply.scala b/src/actors/scala/actors/CanReply.scala deleted file mode 100644 index 3f2c53f423..0000000000 --- a/src/actors/scala/actors/CanReply.scala +++ /dev/null @@ -1,65 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.actors - -import scala.language.higherKinds - -/** - * Defines result-bearing message send operations. - * - * @author Philipp Haller - * - * @define actor `CanReply` - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -trait CanReply[-T, +R] { - - type Future[+P] <: () => P - - /** - * Sends `msg` to this $actor and awaits reply (synchronous). - * - * @param msg the message to be sent - * @return the reply - */ - def !?(msg: T): R - - /** - * Sends `msg` to this $actor and awaits reply (synchronous) within - * `msec` milliseconds. - * - * @param msec the time span before timeout - * @param msg the message to be sent - * @return `None` in case of timeout, otherwise - * `Some(x)` where `x` is the reply - */ - def !?(msec: Long, msg: T): Option[R] - - /** - * Sends `msg` to this $actor and immediately returns a future representing - * the reply value. - * - * @param msg the message to be sent - * @return the future - */ - def !!(msg: T): Future[R] - - /** - * Sends `msg` to this $actor and immediately returns a future representing - * the reply value. The reply is post-processed using the partial function - * `handler`. This also allows to recover a more precise type for the reply - * value. - * - * @param msg the message to be sent - * @param handler the function to be applied to the response - * @return the future - */ - def !![P](msg: T, handler: PartialFunction[R, P]): Future[P] - -} diff --git a/src/actors/scala/actors/Channel.scala b/src/actors/scala/actors/Channel.scala deleted file mode 100644 index ddf7b329c8..0000000000 --- a/src/actors/scala/actors/Channel.scala +++ /dev/null @@ -1,136 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.actors - -import scala.concurrent.SyncVar - -/** - * Used to pattern match on values that were sent to some channel `Chan,,n,,` - * by the current actor `self`. - * - * @example {{{ - * receive { - * case Chan1 ! msg1 => ... - * case Chan2 ! msg2 => ... - * } - * }}} - * - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -case class ! [a](ch: Channel[a], msg: a) - -/** - * Provides a means for typed communication among actors. Only the - * actor creating an instance of a `Channel` may receive from it. - * - * @author Philipp Haller - * - * @define actor channel - * @define channel channel - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -class Channel[Msg](val receiver: InternalActor) extends InputChannel[Msg] with OutputChannel[Msg] with CanReply[Msg, Any] { - - type Future[+P] = scala.actors.Future[P] - - def this() = this(Actor.self) - - def !(msg: Msg) { - receiver ! scala.actors.!(this, msg) - } - - def send(msg: Msg, replyTo: OutputChannel[Any]) { - receiver.send(scala.actors.!(this, msg), replyTo) - } - - def forward(msg: Msg) { - receiver forward scala.actors.!(this, msg) - } - - def receive[R](f: PartialFunction[Msg, R]): R = { - val C = this.asInstanceOf[Channel[Any]] - receiver.receive { - case C ! msg if (f.isDefinedAt(msg.asInstanceOf[Msg])) => f(msg.asInstanceOf[Msg]) - } - } - - def ? : Msg = receive { - case x => x - } - - def receiveWithin[R](msec: Long)(f: PartialFunction[Any, R]): R = { - val C = this.asInstanceOf[Channel[Any]] - receiver.receiveWithin(msec) { - case C ! msg if (f.isDefinedAt(msg)) => f(msg) - case TIMEOUT => f(TIMEOUT) - } - } - - def react(f: PartialFunction[Msg, Unit]): Nothing = { - val C = this.asInstanceOf[Channel[Any]] - receiver.react { - case C ! msg if (f.isDefinedAt(msg.asInstanceOf[Msg])) => f(msg.asInstanceOf[Msg]) - } - } - - def reactWithin(msec: Long)(f: PartialFunction[Any, Unit]): Nothing = { - val C = this.asInstanceOf[Channel[Any]] - receiver.reactWithin(msec) { - case C ! msg if (f.isDefinedAt(msg)) => f(msg) - case TIMEOUT => f(TIMEOUT) - } - } - - def !?(msg: Msg): Any = { - val replyCh = new Channel[Any](Actor.self(receiver.scheduler)) - receiver.send(scala.actors.!(this, msg), replyCh) - replyCh.receive { - case x => x - } - } - - def !?(msec: Long, msg: Msg): Option[Any] = { - val replyCh = new Channel[Any](Actor.self(receiver.scheduler)) - receiver.send(scala.actors.!(this, msg), replyCh) - replyCh.receiveWithin(msec) { - case TIMEOUT => None - case x => Some(x) - } - } - - def !![A](msg: Msg, handler: PartialFunction[Any, A]): Future[A] = { - val c = new Channel[A](Actor.self(receiver.scheduler)) - val fun = (res: SyncVar[A]) => { - val ftch = new Channel[A](Actor.self(receiver.scheduler)) - receiver.send(scala.actors.!(this, msg), new OutputChannel[Any] { - def !(msg: Any) = - ftch ! handler(msg) - def send(msg: Any, replyTo: OutputChannel[Any]) = - ftch.send(handler(msg), replyTo) - def forward(msg: Any) = - ftch.forward(handler(msg)) - def receiver = - ftch.receiver - }) - ftch.react { - case any => res.set(any) - } - } - val a = new FutureActor[A](fun, c) - a.start() - a - } - - def !!(msg: Msg): Future[Any] = { - val noTransform: PartialFunction[Any, Any] = { case x => x } - this !! (msg, noTransform) - } - -} diff --git a/src/actors/scala/actors/Combinators.scala b/src/actors/scala/actors/Combinators.scala deleted file mode 100644 index 64dbaf06e4..0000000000 --- a/src/actors/scala/actors/Combinators.scala +++ /dev/null @@ -1,48 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.actors - -import scala.language.implicitConversions - -private[actors] trait Combinators { - - /** - * Enables the composition of suspendable closures using `andThen`, - * `loop`, `loopWhile`, etc. - */ - implicit def mkBody[a](body: => a): InternalActor.Body[a] - - /** - * Repeatedly executes `body`. - * - * @param body the block to be executed - */ - def loop(body: => Unit): Unit = body andThen loop(body) - - /** - * Repeatedly executes `body` while the condition `cond` is `true`. - * - * @param cond the condition to test - * @param body the block to be executed - */ - def loopWhile(cond: => Boolean)(body: => Unit): Unit = - if (cond) { body andThen loopWhile(cond)(body) } - else continue - - /** - * Continues with the execution of the closure registered as - * continuation following `andThen`. Continues with the execution - * of the next loop iteration when invoked inside the body of `loop` - * or `loopWhile`. - */ - def continue(): Unit = throw new KillActorControl - -} diff --git a/src/actors/scala/actors/DaemonActor.scala b/src/actors/scala/actors/DaemonActor.scala deleted file mode 100644 index 04a4b4a40c..0000000000 --- a/src/actors/scala/actors/DaemonActor.scala +++ /dev/null @@ -1,24 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.actors - -import scheduler.DaemonScheduler - -/** - * Base trait for actors with daemon semantics. - * - * Unlike a regular `Actor`, an active `DaemonActor` will not - * prevent an application terminating, much like a daemon thread. - * - * @author Erik Engbrecht - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -trait DaemonActor extends Actor { - override def scheduler: IScheduler = DaemonScheduler -} diff --git a/src/actors/scala/actors/Debug.scala b/src/actors/scala/actors/Debug.scala deleted file mode 100644 index 31ef53bdbe..0000000000 --- a/src/actors/scala/actors/Debug.scala +++ /dev/null @@ -1,45 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors - -/** - * Provides methods for generating debugging output. - * - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -object Debug extends Logger("") {} - -private[actors] class Logger(tag: String) { - private var lev = 2 - - def level = lev - def level_= (lev: Int) = { this.lev = lev } - - private val tagString = if (tag == "") "" else " ["+tag+"]" - - def info(s: String) = - if (lev > 2) System.out.println("Info" + tagString + ": " + s) - - def warning(s: String) = - if (lev > 1) System.err.println("Warning" + tagString + ": " + s) - - def error(s: String) = - if (lev > 0) System.err.println("Error" + tagString + ": " + s) - - def doInfo(b: => Unit) = - if (lev > 2) b - - def doWarning(b: => Unit) = - if (lev > 1) b - - def doError(b: => Unit) = - if (lev > 0) b -} diff --git a/src/actors/scala/actors/Future.scala b/src/actors/scala/actors/Future.scala deleted file mode 100644 index 4421c7a07a..0000000000 --- a/src/actors/scala/actors/Future.scala +++ /dev/null @@ -1,243 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors - -import scala.actors.scheduler.DaemonScheduler -import scala.concurrent.SyncVar - -/** A function of arity 0, returing a value of type `T` that, - * when applied, blocks the current actor (`Actor.self`) - * until the future's value is available. - * - * A future can be queried to find out whether its value - * is already available without blocking. - * - * @author Philipp Haller - */ -@deprecated("Use the scala.concurrent.Future instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -abstract class Future[+T] extends Responder[T] with Function0[T] { - - @volatile - private[actors] var fvalue: Option[Any] = None - private[actors] def fvalueTyped = fvalue.get.asInstanceOf[T] - - /** Tests whether the future's result is available. - * - * @return `true` if the future's result is available, - * `false` otherwise. - */ - def isSet: Boolean - - /** Returns an input channel that can be used to receive the future's result. - * - * @return the future's input channel - */ - def inputChannel: InputChannel[T] - -} - -private case object Eval - -private class FutureActor[T](fun: SyncVar[T] => Unit, channel: Channel[T]) extends Future[T] with DaemonActor { - - var enableChannel = false // guarded by this - - def isSet = !fvalue.isEmpty - - def apply(): T = { - if (fvalue.isEmpty) { - this !? Eval - } - fvalueTyped - } - - def respond(k: T => Unit) { - if (isSet) k(fvalueTyped) - else { - val ft = this !! Eval - ft.inputChannel.react { - case _ => k(fvalueTyped) - } - } - } - - def inputChannel: InputChannel[T] = { - synchronized { - if (!enableChannel) { - if (isSet) - channel ! fvalueTyped - enableChannel = true - } - } - channel - } - - def act() { - val res = new SyncVar[T] - - { - fun(res) - } andThen { - - synchronized { - val v = res.get - fvalue = Some(v) - if (enableChannel) - channel ! v - } - - loop { - react { - // This is calling ReplyReactor#reply(msg: Any). - // Was: reply(). Now: reply(()). - case Eval => reply(()) - } - } - } - } -} - -/** Methods that operate on futures. - * - * @author Philipp Haller - */ -@deprecated("Use the object scala.concurrent.Future instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -object Futures { - - /** Arranges for the asynchronous execution of `body`, - * returning a future representing the result. - * - * @param body the computation to be carried out asynchronously - * @return the future representing the result of the - * computation - */ - def future[T](body: => T): Future[T] = { - val c = new Channel[T](Actor.self(DaemonScheduler)) - val a = new FutureActor[T](_.set(body), c) - a.start() - a - } - - /** Creates a future that resolves after a given time span. - * - * @param timespan the time span in ms after which the future resolves - * @return the future - */ - def alarm(timespan: Long): Future[Unit] = { - val c = new Channel[Unit](Actor.self(DaemonScheduler)) - val fun = (res: SyncVar[Unit]) => { - Actor.reactWithin(timespan) { - case TIMEOUT => res.set({}) - } - } - val a = new FutureActor[Unit](fun, c) - a.start() - a - } - - /** Waits for the first result returned by one of two - * given futures. - * - * @param ft1 the first future - * @param ft2 the second future - * @return the result of the future that resolves first - */ - def awaitEither[A, B >: A](ft1: Future[A], ft2: Future[B]): B = { - val FutCh1 = ft1.inputChannel - val FutCh2 = ft2.inputChannel - Actor.receive { - case FutCh1 ! arg1 => arg1.asInstanceOf[B] - case FutCh2 ! arg2 => arg2.asInstanceOf[B] - } - } - - /** Waits until either all futures are resolved or a given - * time span has passed. Results are collected in a list of - * options. The result of a future that resolved during the - * time span is its value wrapped in `Some`. The result of a - * future that did not resolve during the time span is `None`. - * - * Note that some of the futures might already have been awaited, - * in which case their value is returned wrapped in `Some`. - * Passing a timeout of 0 causes `awaitAll` to return immediately. - * - * @param timeout the time span in ms after which waiting is - * aborted - * @param fts the futures to be awaited - * @return the list of optional future values - * @throws java.lang.IllegalArgumentException if timeout is negative, - * or timeout + `System.currentTimeMillis()` is negative. - */ - def awaitAll(timeout: Long, fts: Future[Any]*): List[Option[Any]] = { - val resultsMap: scala.collection.mutable.Map[Int, Option[Any]] = new scala.collection.mutable.HashMap[Int, Option[Any]] - - var cnt = 0 - val mappedFts = fts.map(ft => - ({cnt+=1; cnt-1}, ft)) - - val unsetFts = mappedFts.filter((p: Tuple2[Int, Future[Any]]) => { - if (p._2.isSet) { resultsMap(p._1) = Some(p._2()); false } - else { resultsMap(p._1) = None; true } - }) - - val partFuns = unsetFts.map((p: Tuple2[Int, Future[Any]]) => { - val FutCh = p._2.inputChannel - val singleCase: PartialFunction[Any, Tuple2[Int, Any]] = { - case FutCh ! any => (p._1, any) - } - singleCase - }) - - val thisActor = Actor.self - val timerTask = new java.util.TimerTask { - def run() { thisActor ! TIMEOUT } - } - Actor.timer.schedule(timerTask, timeout) - - def awaitWith(partFuns: Seq[PartialFunction[Any, Tuple2[Int, Any]]]) { - val reaction: PartialFunction[Any, Unit] = new PartialFunction[Any, Unit] { - def isDefinedAt(msg: Any) = msg match { - case TIMEOUT => true - case _ => partFuns exists (_ isDefinedAt msg) - } - def apply(msg: Any): Unit = msg match { - case TIMEOUT => // do nothing - case _ => { - val pfOpt = partFuns find (_ isDefinedAt msg) - val pf = pfOpt.get // succeeds always - val (idx, subres) = pf(msg) - resultsMap(idx) = Some(subres) - - val partFunsRest = partFuns filter (_ != pf) - // wait on rest of partial functions - if (partFunsRest.length > 0) - awaitWith(partFunsRest) - } - } - } - Actor.receive(reaction) - } - - if (partFuns.length > 0) - awaitWith(partFuns) - - var results: List[Option[Any]] = Nil - val size = resultsMap.size - for (i <- 0 until size) { - results = resultsMap(size - i - 1) :: results - } - - // cancel scheduled timer task - timerTask.cancel() - - results - } - -} diff --git a/src/actors/scala/actors/IScheduler.scala b/src/actors/scala/actors/IScheduler.scala deleted file mode 100644 index 9d61d48561..0000000000 --- a/src/actors/scala/actors/IScheduler.scala +++ /dev/null @@ -1,70 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors - -/** - * A common interface for all schedulers used to execute actor tasks. - * - * Subclasses of `Actor` that override its `scheduler` member must provide - * an `IScheduler` implementation. - * - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -trait IScheduler { - - /** Submits a closure for execution. - * - * @param fun the closure to be executed - */ - def execute(fun: => Unit): Unit - - /** Submits a `Runnable` for execution. - * - * @param task the task to be executed - */ - def execute(task: Runnable): Unit - - def executeFromActor(task: Runnable): Unit = - execute(task) - - /** Shuts down the scheduler. */ - def shutdown(): Unit - - /** When the scheduler is active, it can execute tasks. - * - * @return `'''true'''`, if the scheduler is active, otherwise false. - */ - def isActive: Boolean - - /** Registers a newly created actor with this scheduler. - * - * @param a the actor to be registered - */ - def newActor(a: TrackedReactor): Unit - - /** Unregisters an actor from this scheduler, because it - * has terminated. - * - * @param a the actor to be registered - */ - def terminated(a: TrackedReactor): Unit - - /** Registers a closure to be executed when the specified - * actor terminates. - * - * @param a the actor - * @param f the closure to be registered - */ - def onTerminate(a: TrackedReactor)(f: => Unit): Unit - - def managedBlock(blocker: scala.concurrent.ManagedBlocker): Unit - -} diff --git a/src/actors/scala/actors/InputChannel.scala b/src/actors/scala/actors/InputChannel.scala deleted file mode 100644 index d2dd6d24df..0000000000 --- a/src/actors/scala/actors/InputChannel.scala +++ /dev/null @@ -1,66 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors - -/** - * A common interface for all channels from which values can be received. - * - * @author Philipp Haller - * - * @define channel `InputChannel` - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -trait InputChannel[+Msg] { - - /** - * Receives a message from this $channel. - * - * @param f a partial function with message patterns and actions - * @return result of processing the received value - */ - def receive[R](f: PartialFunction[Msg, R]): R - - /** - * Receives a message from this $channel within - * a certain time span. - * - * @param msec the time span before timeout - * @param f a partial function with message patterns and actions - * @return result of processing the received value - */ - def receiveWithin[R](msec: Long)(f: PartialFunction[Any, R]): R - - /** - * Receives a message from this $channel. - * - * This method never returns. Therefore, the rest of the computation - * has to be contained in the actions of the partial function. - * - * @param f a partial function with message patterns and actions - */ - def react(f: PartialFunction[Msg, Unit]): Nothing - - /** - * Receives a message from this $channel within - * a certain time span. - * - * This method never returns. Therefore, the rest of the computation - * has to be contained in the actions of the partial function. - * - * @param msec the time span before timeout - * @param f a partial function with message patterns and actions - */ - def reactWithin(msec: Long)(f: PartialFunction[Any, Unit]): Nothing - - /** - * Receives the next message from this $channel. - */ - def ? : Msg -} diff --git a/src/actors/scala/actors/InternalActor.scala b/src/actors/scala/actors/InternalActor.scala deleted file mode 100644 index 5045ea56e8..0000000000 --- a/src/actors/scala/actors/InternalActor.scala +++ /dev/null @@ -1,546 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ -package scala.actors -import java.util.TimerTask -import scala.util.control.ControlThrowable - -private[actors] object InternalActor { - private[actors] trait Body[a] { - def andThen[b](other: => b): Unit - } -} - -private[actors] trait InternalActor extends AbstractActor with InternalReplyReactor with ActorCanReply with InputChannel[Any] with Serializable { - - /* The following two fields are only used when the actor - * suspends by blocking its underlying thread, for example, - * when waiting in a receive or synchronous send. - */ - @volatile - private[actors] var isSuspended = false - - /* This field is used to communicate the received message from - * the invocation of send to the place where the thread of - * the receiving actor resumes inside receive/receiveWithin. - */ - @volatile - private var received: Option[Any] = None - - protected[actors] override def scheduler: IScheduler = Scheduler - - private[actors] override def startSearch(msg: Any, replyTo: OutputChannel[Any], handler: PartialFunction[Any, Any]) = - if (isSuspended) { - () => - synchronized { - mailbox.append(msg, replyTo) - resumeActor() - } - } else super.startSearch(msg, replyTo, handler) - - // we override this method to check `shouldExit` before suspending - private[actors] override def searchMailbox(startMbox: MQueue[Any], - handler: PartialFunction[Any, Any], - resumeOnSameThread: Boolean) { - var tmpMbox = startMbox - var done = false - while (!done) { - val qel = tmpMbox.extractFirst((msg: Any, replyTo: OutputChannel[Any]) => { - senders = List(replyTo) - handler.isDefinedAt(msg) - }) - if (tmpMbox ne mailbox) - tmpMbox.foreach((m, s) => mailbox.append(m, s)) - if (null eq qel) { - synchronized { - // in mean time new stuff might have arrived - if (!sendBuffer.isEmpty) { - tmpMbox = new MQueue[Any]("Temp") - drainSendBuffer(tmpMbox) - // keep going - } else { - // very important to check for `shouldExit` at this point - // since linked actors might have set it after we checked - // last time (e.g., at the beginning of `react`) - if (shouldExit) exit() - waitingFor = handler - // see Reactor.searchMailbox - throw Actor.suspendException - } - } - } else { - resumeReceiver((qel.msg, qel.session), handler, resumeOnSameThread) - done = true - } - } - } - - private[actors] override def makeReaction(fun: () => Unit, handler: PartialFunction[Any, Any], msg: Any): Runnable = - new ActorTask(this, fun, handler, msg) - - /** See the companion object's `receive` method. */ - def receive[R](f: PartialFunction[Any, R]): R = { - assert(Actor.self(scheduler) == this, "receive from channel belonging to other actor") - - synchronized { - if (shouldExit) exit() // links - drainSendBuffer(mailbox) - } - - var done = false - while (!done) { - val qel = mailbox.extractFirst((m: Any, replyTo: OutputChannel[Any]) => { - senders = replyTo :: senders - val matches = f.isDefinedAt(m) - senders = senders.tail - matches - }) - if (null eq qel) { - synchronized { - // in mean time new stuff might have arrived - if (!sendBuffer.isEmpty) { - drainSendBuffer(mailbox) - // keep going - } else { - waitingFor = f - isSuspended = true - scheduler.managedBlock(blocker) - drainSendBuffer(mailbox) - // keep going - } - } - } else { - received = Some(qel.msg) - senders = qel.session :: senders - done = true - } - } - - val result = f(received.get) - received = None - senders = senders.tail - result - } - - /** See the companion object's `receiveWithin` method. */ - def receiveWithin[R](msec: Long)(f: PartialFunction[Any, R]): R = { - assert(Actor.self(scheduler) == this, "receive from channel belonging to other actor") - - synchronized { - if (shouldExit) exit() // links - drainSendBuffer(mailbox) - } - - // first, remove spurious TIMEOUT message from mailbox if any - mailbox.extractFirst((m: Any, replyTo: OutputChannel[Any]) => m == TIMEOUT) - - val receiveTimeout = () => { - if (f.isDefinedAt(TIMEOUT)) { - received = Some(TIMEOUT) - senders = this :: senders - } else - sys.error("unhandled timeout") - } - - var done = false - while (!done) { - val qel = mailbox.extractFirst((m: Any, replyTo: OutputChannel[Any]) => { - senders = replyTo :: senders - val matches = f.isDefinedAt(m) - senders = senders.tail - matches - }) - if (null eq qel) { - val todo = synchronized { - // in mean time new stuff might have arrived - if (!sendBuffer.isEmpty) { - drainSendBuffer(mailbox) - // keep going - () => {} - } else if (msec == 0L) { - done = true - receiveTimeout - } else { - if (onTimeout.isEmpty) { - if (!f.isDefinedAt(TIMEOUT)) - sys.error("unhandled timeout") - - val thisActor = this - onTimeout = Some(new TimerTask { - def run() { - thisActor.send(TIMEOUT, thisActor) - } - }) - Actor.timer.schedule(onTimeout.get, msec) - } - - // It is possible that !onTimeout.isEmpty, but TIMEOUT is not yet in mailbox - // See SI-4759 - waitingFor = f - received = None - isSuspended = true - scheduler.managedBlock(blocker) - drainSendBuffer(mailbox) - // keep going - () => {} - } - } - todo() - } else { - synchronized { - if (!onTimeout.isEmpty) { - onTimeout.get.cancel() - onTimeout = None - } - } - received = Some(qel.msg) - senders = qel.session :: senders - done = true - } - } - - val result = f(received.get) - received = None - senders = senders.tail - result - } - - /** See the companion object's `react` method. */ - override def react(handler: PartialFunction[Any, Unit]): Nothing = { - synchronized { - if (shouldExit) exit() - } - super.react(handler) - } - - /** See the companion object's `reactWithin` method. */ - override def reactWithin(msec: Long)(handler: PartialFunction[Any, Unit]): Nothing = { - synchronized { - if (shouldExit) exit() - } - super.reactWithin(msec)(handler) - } - - /** Receives the next message from the mailbox */ - def ? : Any = receive { - case x => x - } - - // guarded by lock of this - // never throws SuspendActorControl - private[actors] override def scheduleActor(f: PartialFunction[Any, Any], msg: Any) = - if (f eq null) { - // do nothing (timeout is handled instead) - } else { - val task = new ActorTask(this, null, f, msg) - scheduler executeFromActor task - } - - /* Used for notifying scheduler when blocking inside receive/receiveWithin. */ - private object blocker extends scala.concurrent.ManagedBlocker { - def block() = { - InternalActor.this.suspendActor() - true - } - def isReleasable = - !InternalActor.this.isSuspended - } - - private def suspendActor() = synchronized { - while (isSuspended) { - try { - wait() - } catch { - case _: InterruptedException => - } - } - // links: check if we should exit - if (shouldExit) exit() - } - - private def resumeActor() { - isSuspended = false - notify() - } - - private[actors] override def exiting = synchronized { - _state == Actor.State.Terminated - } - - // guarded by this - private[actors] override def dostart() { - // Reset various flags. - // - // Note that we do *not* reset `trapExit`. The reason is that - // users should be able to set the field in the constructor - // and before `act` is called. - exitReason = 'normal - shouldExit = false - - super.dostart() - } - - override def start(): InternalActor = synchronized { - super.start() - this - } - - /** State of this actor */ - override def getState: Actor.State.Value = synchronized { - if (isSuspended) { - if (onTimeout.isEmpty) - Actor.State.Blocked - else - Actor.State.TimedBlocked - } else - super.getState - } - - // guarded by this - private[actors] var links: List[AbstractActor] = Nil - - /** - * Links self to actor to. - * - * @param to the actor to link to - * @return the parameter actor - */ - def link(to: AbstractActor): AbstractActor = { - assert(Actor.self(scheduler) == this, "link called on actor different from self") - this linkTo to - to linkTo this - to - } - - /** - * Links self to actor to. - * - * @param to the actor to link to - * @return the parameter actor - */ - def link(to: ActorRef): ActorRef = { - this.link(to.localActor) - to - } - - /** - * Unidirectional linking. For migration purposes only - */ - private[actors] def watch(subject: ActorRef): ActorRef = { - assert(Actor.self(scheduler) == this, "link called on actor different from self") - subject.localActor linkTo this - subject - } - - /** - * Unidirectional linking. For migration purposes only - */ - private[actors] def unwatch(subject: ActorRef): ActorRef = { - assert(Actor.self(scheduler) == this, "link called on actor different from self") - subject.localActor unlinkFrom this - subject - } - - /** - * Links self to the actor defined by body. - * - * @param body the body of the actor to link to - * @return the parameter actor - */ - def link(body: => Unit): Actor = { - assert(Actor.self(scheduler) == this, "link called on actor different from self") - val a = new Actor { - def act() = body - override final val scheduler: IScheduler = InternalActor.this.scheduler - } - link(a) - a.start() - a - } - - private[actors] def linkTo(to: AbstractActor) = synchronized { - links = to :: links - } - - /** - * Unlinks self from actor from. - */ - def unlink(from: AbstractActor) { - assert(Actor.self(scheduler) == this, "unlink called on actor different from self") - this unlinkFrom from - from unlinkFrom this - } - - /** - * Unlinks self from actor from. - */ - def unlink(from: ActorRef) { - unlink(from.localActor) - } - - private[actors] def unlinkFrom(from: AbstractActor) = synchronized { - links = links.filterNot(from.==) - } - - @volatile - private[actors] var _trapExit = false - - def trapExit = _trapExit - - def trapExit_=(value: Boolean) = _trapExit = value - - // guarded by this - private var exitReason: AnyRef = 'normal - // guarded by this - private[actors] var shouldExit = false - - /** - *

- * Terminates execution of self with the following - * effect on linked actors: - *

- *

- * For each linked actor a with - * trapExit set to true, send message - * Exit(self, reason) to a. - *

- *

- * For each linked actor a with - * trapExit set to false (default), - * call a.exit(reason) if - * reason != 'normal. - *

- */ - protected[actors] def exit(reason: AnyRef): Nothing = { - synchronized { - exitReason = reason - } - exit() - } - - /** - * Terminates with exit reason 'normal. - */ - protected[actors] override def exit(): Nothing = { - val todo = synchronized { - if (!links.isEmpty) - exitLinked() - else - () => {} - } - todo() - super.exit() - } - - // Assume !links.isEmpty - // guarded by this - private[actors] def exitLinked(): () => Unit = { - _state = Actor.State.Terminated - // reset waitingFor, otherwise getState returns Suspended - waitingFor = Reactor.waitingForNone - // remove this from links - val mylinks = links.filterNot(this.==) - // unlink actors - mylinks.foreach(unlinkFrom(_)) - // return closure that locks linked actors - () => { - mylinks.foreach((linked: AbstractActor) => { - linked.synchronized { - if (!linked.exiting) { - linked.unlinkFrom(this) - linked.exit(this, exitReason) - } - } - }) - } - } - - // Assume !links.isEmpty - // guarded by this - private[actors] def exitLinked(reason: AnyRef): () => Unit = { - exitReason = reason - exitLinked() - } - - // Assume !this.exiting - private[actors] def exit(from: AbstractActor, reason: AnyRef) { - if (trapExit) { - this ! Exit(from, reason) - } else if (reason != 'normal) - stop(reason) - } - - /* Requires qualified private, because RemoteActor must - * register a termination handler. - */ - private[actors] def onTerminate(f: => Unit) { - scheduler.onTerminate(this) { f } - } - - - private[actors] def stop(reason: AnyRef): Unit = { - synchronized { - shouldExit = true - exitReason = reason - // resume this Actor in a way that - // causes it to exit - // (because shouldExit == true) - if (isSuspended) - resumeActor() - else if (waitingFor ne Reactor.waitingForNone) { - waitingFor = Reactor.waitingForNone - // it doesn't matter what partial function we are passing here - val task = new ActorTask(this, null, waitingFor, null) - scheduler execute task - /* Here we should not throw a SuspendActorControl, - since the current method is called from an actor that - is in the process of exiting. - - Therefore, the contract for scheduleActor is that - it never throws a SuspendActorControl. - */ - } - } - } -} - -/** - * Used as the timeout pattern in - * - * receiveWithin and - * - * reactWithin. - * - * @example {{{ - * receiveWithin(500) { - * case (x, y) => ... - * case TIMEOUT => ... - * } - * }}} - * - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -case object TIMEOUT - -/** - * Sent to an actor - * with `trapExit` set to `true` whenever one of its linked actors - * terminates. - * - * @param from the actor that terminated - * @param reason the reason that caused the actor to terminate - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -case class Exit(from: AbstractActor, reason: AnyRef) - -/** - * Manages control flow of actor executions. - * - * @author Philipp Haller - */ -private[actors] class SuspendActorControl extends ControlThrowable diff --git a/src/actors/scala/actors/InternalReplyReactor.scala b/src/actors/scala/actors/InternalReplyReactor.scala deleted file mode 100644 index c744984fd8..0000000000 --- a/src/actors/scala/actors/InternalReplyReactor.scala +++ /dev/null @@ -1,162 +0,0 @@ -package scala.actors - -import java.util.{TimerTask} - -/** - * Extends the [[scala.actors.Reactor]] - * trait with methods to reply to the sender of a message. - * Sending a message to a ReplyReactor implicitly - * passes a reference to the sender together with the message. - * - * @author Philipp Haller - * - * @define actor `ReplyReactor` - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -trait InternalReplyReactor extends Reactor[Any] with ReactorCanReply { - - /* A list of the current senders. The head of the list is - * the sender of the message that was received last. - */ - @volatile - private[actors] var senders: List[OutputChannel[Any]] = List() - - /* This option holds a TimerTask when the actor waits in a - * reactWithin. The TimerTask is cancelled when the actor - * resumes. - * - * guarded by this - */ - private[actors] var onTimeout: Option[TimerTask] = None - - /** - * Returns the $actor which sent the last received message. - */ - protected[actors] def internalSender: OutputChannel[Any] = senders.head - - /** - * Replies with msg to the sender. - */ - protected[actors] def reply(msg: Any) { - internalSender ! msg - } - - override def !(msg: Any) { - send(msg, Actor.rawSelf(scheduler)) - } - - override def forward(msg: Any) { - send(msg, Actor.sender) - } - - private[actors] override def resumeReceiver(item: (Any, OutputChannel[Any]), handler: PartialFunction[Any, Any], onSameThread: Boolean) { - synchronized { - if (!onTimeout.isEmpty) { - onTimeout.get.cancel() - onTimeout = None - } - } - senders = List(item._2) - super.resumeReceiver(item, handler, onSameThread) - } - - private[actors] override def searchMailbox(startMbox: MQueue[Any], - handler: PartialFunction[Any, Any], - resumeOnSameThread: Boolean) { - var tmpMbox = startMbox - var done = false - while (!done) { - val qel = tmpMbox.extractFirst((msg: Any, replyTo: OutputChannel[Any]) => { - senders = List(replyTo) - handler.isDefinedAt(msg) - }) - if (tmpMbox ne mailbox) - tmpMbox.foreach((m, s) => mailbox.append(m, s)) - if (null eq qel) { - synchronized { - // in mean time new stuff might have arrived - if (!sendBuffer.isEmpty) { - tmpMbox = new MQueue[Any]("Temp") - drainSendBuffer(tmpMbox) - // keep going - } else { - waitingFor = handler - // see Reactor.searchMailbox - throw Actor.suspendException - } - } - } else { - resumeReceiver((qel.msg, qel.session), handler, resumeOnSameThread) - done = true - } - } - } - - private[actors] override def makeReaction(fun: () => Unit, handler: PartialFunction[Any, Any], msg: Any): Runnable = - new ReplyReactorTask(this, fun, handler, msg) - - protected[actors] override def react(handler: PartialFunction[Any, Unit]): Nothing = { - assert(Actor.rawSelf(scheduler) == this, "react on channel belonging to other actor") - super.react(handler) - } - - - /** - * Receives a message from this $actor's mailbox within a certain - * time span. - * - * This method never returns. Therefore, the rest of the computation - * has to be contained in the actions of the partial function. - * - * @param msec the time span before timeout - * @param handler a partial function with message patterns and actions - */ - protected[actors] def reactWithin(msec: Long)(handler: PartialFunction[Any, Unit]): Nothing = { - assert(Actor.rawSelf(scheduler) == this, "react on channel belonging to other actor") - - synchronized { drainSendBuffer(mailbox) } - - // first, remove spurious TIMEOUT message from mailbox if any - mailbox.extractFirst((m: Any, replyTo: OutputChannel[Any]) => m == TIMEOUT) - - while (true) { - val qel = mailbox.extractFirst((m: Any, replyTo: OutputChannel[Any]) => { - senders = List(replyTo) - handler isDefinedAt m - }) - if (null eq qel) { - synchronized { - // in mean time new messages might have arrived - if (!sendBuffer.isEmpty) { - drainSendBuffer(mailbox) - // keep going - } else if (msec == 0L) { - // throws Actor.suspendException - resumeReceiver((TIMEOUT, this), handler, false) - } else { - waitingFor = handler - val thisActor = this - onTimeout = Some(new TimerTask { - def run() { thisActor.send(TIMEOUT, thisActor) } - }) - Actor.timer.schedule(onTimeout.get, msec) - throw Actor.suspendException - } - } - } else - resumeReceiver((qel.msg, qel.session), handler, false) - } - throw Actor.suspendException - } - - override def getState: Actor.State.Value = synchronized { - if (waitingFor ne Reactor.waitingForNone) { - if (onTimeout.isEmpty) - Actor.State.Suspended - else - Actor.State.TimedSuspended - } else - _state - } - -} diff --git a/src/actors/scala/actors/KillActorControl.scala b/src/actors/scala/actors/KillActorControl.scala deleted file mode 100644 index 0f94bbc8dc..0000000000 --- a/src/actors/scala/actors/KillActorControl.scala +++ /dev/null @@ -1,14 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.actors - -import scala.util.control.ControlThrowable -import java.lang.{InterruptedException, Runnable} - -private[actors] class KillActorControl extends ControlThrowable diff --git a/src/actors/scala/actors/LinkedNode.java b/src/actors/scala/actors/LinkedNode.java deleted file mode 100644 index bf8ca02a74..0000000000 --- a/src/actors/scala/actors/LinkedNode.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - File: LinkedNode.java - - Originally written by Doug Lea and released into the public domain. - This may be used for any purposes whatsoever without acknowledgment. - Thanks for the assistance and support of Sun Microsystems Labs, - and everyone contributing, testing, and using this code. - - History: - Date Who What - 11Jun1998 dl Create public version - 25may2000 dl Change class access to public - 26nov2001 dl Added no-arg constructor, all public access. -*/ - -package scala.actors; - -/** A standard linked list node used in various queue classes **/ -public class LinkedNode { - public Object value; - public LinkedNode next; - public LinkedNode() {} - public LinkedNode(Object x) { value = x; } - public LinkedNode(Object x, LinkedNode n) { value = x; next = n; } -} diff --git a/src/actors/scala/actors/LinkedQueue.java b/src/actors/scala/actors/LinkedQueue.java deleted file mode 100644 index 3f7b93c386..0000000000 --- a/src/actors/scala/actors/LinkedQueue.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - File: LinkedQueue.java - - Originally written by Doug Lea and released into the public domain. - This may be used for any purposes whatsoever without acknowledgment. - Thanks for the assistance and support of Sun Microsystems Labs, - and everyone contributing, testing, and using this code. - - History: - Date Who What - 11Jun1998 dl Create public version - 25aug1998 dl added peek - 10dec1998 dl added isEmpty - 10oct1999 dl lock on node object to ensure visibility -*/ - -package scala.actors; - -/** - * A linked list based channel implementation. - * The algorithm avoids contention between puts - * and takes when the queue is not empty. - * Normally a put and a take can proceed simultaneously. - * (Although it does not allow multiple concurrent puts or takes.) - * This class tends to perform more efficiently than - * other Channel implementations in producer/consumer - * applications. - *

[ Introduction to this package. ] - **/ - -public class LinkedQueue { - - - /** - * Dummy header node of list. The first actual node, if it exists, is always - * at head_.next. After each take, the old first node becomes the head. - **/ - protected LinkedNode head_; - - /** - * Helper monitor for managing access to last node. - **/ - protected final Object putLock_ = new Object(); - - /** - * The last node of list. Put() appends to list, so modifies last_ - **/ - protected LinkedNode last_; - - /** - * The number of threads waiting for a take. - * Notifications are provided in put only if greater than zero. - * The bookkeeping is worth it here since in reasonably balanced - * usages, the notifications will hardly ever be necessary, so - * the call overhead to notify can be eliminated. - **/ - protected int waitingForTake_ = 0; - - public LinkedQueue() { - head_ = new LinkedNode(null); - last_ = head_; - } - - /** Main mechanics for put/offer **/ - protected void insert(Object x) { - synchronized(putLock_) { - LinkedNode p = new LinkedNode(x); - synchronized(last_) { - last_.next = p; - last_ = p; - } - if (waitingForTake_ > 0) - putLock_.notify(); - } - } - - /** Main mechanics for take/poll **/ - protected synchronized Object extract() { - synchronized(head_) { - Object x = null; - LinkedNode first = head_.next; - if (first != null) { - x = first.value; - first.value = null; - head_ = first; - } - return x; - } - } - - - public void put(Object x) throws InterruptedException { - if (x == null) throw new IllegalArgumentException(); - if (Thread.interrupted()) throw new InterruptedException(); - insert(x); - } - - public boolean offer(Object x, long msecs) throws InterruptedException { - if (x == null) throw new IllegalArgumentException(); - if (Thread.interrupted()) throw new InterruptedException(); - insert(x); - return true; - } - - public Object take() throws InterruptedException { - if (Thread.interrupted()) throw new InterruptedException(); - // try to extract. If fail, then enter wait-based retry loop - Object x = extract(); - if (x != null) - return x; - else { - synchronized(putLock_) { - try { - ++waitingForTake_; - for (;;) { - x = extract(); - if (x != null) { - --waitingForTake_; - return x; - } - else { - putLock_.wait(); - } - } - } - catch(InterruptedException ex) { - --waitingForTake_; - putLock_.notify(); - throw ex; - } - } - } - } - - public Object peek() { - synchronized(head_) { - LinkedNode first = head_.next; - if (first != null) - return first.value; - else - return null; - } - } - - - public boolean isEmpty() { - synchronized(head_) { - return head_.next == null; - } - } - - public Object poll(long msecs) throws InterruptedException { - if (Thread.interrupted()) throw new InterruptedException(); - Object x = extract(); - if (x != null) - return x; - else { - synchronized(putLock_) { - try { - long waitTime = msecs; - long start = (msecs <= 0)? 0 : System.currentTimeMillis(); - ++waitingForTake_; - for (;;) { - x = extract(); - if (x != null || waitTime <= 0) { - --waitingForTake_; - return x; - } - else { - putLock_.wait(waitTime); - waitTime = msecs - (System.currentTimeMillis() - start); - } - } - } - catch(InterruptedException ex) { - --waitingForTake_; - putLock_.notify(); - throw ex; - } - } - } - } -} - - diff --git a/src/actors/scala/actors/MQueue.scala b/src/actors/scala/actors/MQueue.scala deleted file mode 100644 index d766ecc6e8..0000000000 --- a/src/actors/scala/actors/MQueue.scala +++ /dev/null @@ -1,250 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.actors - -private[actors] class MQueueElement[Msg >: Null](val msg: Msg, val session: OutputChannel[Any], var next: MQueueElement[Msg]) { - def this() = this(null, null, null) - def this(msg: Msg, session: OutputChannel[Any]) = this(msg, session, null) -} - -private[actors] class MQueue[Msg >: Null](protected val label: String) { - protected var first: MQueueElement[Msg] = null - protected var last: MQueueElement[Msg] = null // last eq null iff list is empty - private var _size = 0 - - def size = _size - final def isEmpty = last eq null - - protected def changeSize(diff: Int) { - _size += diff - } - - def prepend(other: MQueue[Msg]) { - if (!other.isEmpty) { - other.last.next = first - first = other.first - } - } - - def clear() { - first = null - last = null - _size = 0 - } - - - def append(msg: Msg, session: OutputChannel[Any]) { - changeSize(1) // size always increases by 1 - val el = new MQueueElement(msg, session) - - if (isEmpty) first = el - else last.next = el - - last = el - } - - def append(el: MQueueElement[Msg]) { - changeSize(1) // size always increases by 1 - - if (isEmpty) first = el - else last.next = el - - last = el - } - - def foreach(f: (Msg, OutputChannel[Any]) => Unit) { - var curr = first - while (curr != null) { - f(curr.msg, curr.session) - curr = curr.next - } - } - - def foreachAppend(target: MQueue[Msg]) { - var curr = first - while (curr != null) { - target.append(curr) - curr = curr.next - } - } - - def foreachDequeue(target: MQueue[Msg]) { - var curr = first - while (curr != null) { - target.append(curr) - curr = curr.next - } - first = null - last = null - _size = 0 - } - - def foldLeft[B](z: B)(f: (B, Msg) => B): B = { - var acc = z - var curr = first - while (curr != null) { - acc = f(acc, curr.msg) - curr = curr.next - } - acc - } - - /** Returns the n-th message that satisfies the predicate `p` - * without removing it. - */ - def get(n: Int)(p: Msg => Boolean): Option[Msg] = { - var pos = 0 - - def test(msg: Msg): Boolean = - p(msg) && (pos == n || { pos += 1; false }) - - var curr = first - while (curr != null) - if (test(curr.msg)) return Some(curr.msg) // early return - else curr = curr.next - - None - } - - /** Removes the n-th message that satisfies the predicate p. - */ - def remove(n: Int)(p: (Msg, OutputChannel[Any]) => Boolean): Option[(Msg, OutputChannel[Any])] = - removeInternal(n)(p) map (x => (x.msg, x.session)) - - /** Extracts the first message that satisfies the predicate `p` - * or `'''null'''` if `p` fails for all of them. - */ - def extractFirst(p: (Msg, OutputChannel[Any]) => Boolean): MQueueElement[Msg] = - removeInternal(0)(p).orNull - - def extractFirst(pf: PartialFunction[Msg, Any]): MQueueElement[Msg] = { - if (isEmpty) // early return - return null - - // special handling if returning the head - if (pf.isDefinedAt(first.msg)) { - val res = first - first = first.next - if (res eq last) - last = null - - changeSize(-1) - res - } - else { - var curr = first.next // init to element #2 - var prev = first - - while (curr != null) { - if (pf.isDefinedAt(curr.msg)) { - prev.next = curr.next - if (curr eq last) - last = prev - - changeSize(-1) - return curr // early return - } - else { - prev = curr - curr = curr.next - } - } - // not found - null - } - } - - private def removeInternal(n: Int)(p: (Msg, OutputChannel[Any]) => Boolean): Option[MQueueElement[Msg]] = { - var pos = 0 - - def foundMsg(x: MQueueElement[Msg]) = { - changeSize(-1) - Some(x) - } - def test(msg: Msg, session: OutputChannel[Any]): Boolean = - p(msg, session) && (pos == n || { pos += 1 ; false }) - - if (isEmpty) // early return - return None - - // special handling if returning the head - if (test(first.msg, first.session)) { - val res = first - first = first.next - if (res eq last) - last = null - - foundMsg(res) - } - else { - var curr = first.next // init to element #2 - var prev = first - - while (curr != null) { - if (test(curr.msg, curr.session)) { - prev.next = curr.next - if (curr eq last) - last = prev - - return foundMsg(curr) // early return - } - else { - prev = curr - curr = curr.next - } - } - // not found - None - } - } -} - -/** Debugging trait. - */ -private[actors] trait MessageQueueTracer extends MQueue[Any] -{ - private val queueNumber = MessageQueueTracer.getQueueNumber - - override def append(msg: Any, session: OutputChannel[Any]) { - super.append(msg, session) - printQueue("APPEND %s" format msg) - } - override def get(n: Int)(p: Any => Boolean): Option[Any] = { - val res = super.get(n)(p) - printQueue("GET %s" format res) - res - } - override def remove(n: Int)(p: (Any, OutputChannel[Any]) => Boolean): Option[(Any, OutputChannel[Any])] = { - val res = super.remove(n)(p) - printQueue("REMOVE %s" format res) - res - } - override def extractFirst(p: (Any, OutputChannel[Any]) => Boolean): MQueueElement[Any] = { - val res = super.extractFirst(p) - printQueue("EXTRACT_FIRST %s" format res) - res - } - - private def printQueue(msg: String) = { - def firstMsg = if (first eq null) "null" else first.msg - def lastMsg = if (last eq null) "null" else last.msg - - println("[%s size=%d] [%s] first = %s, last = %s".format(this, size, msg, firstMsg, lastMsg)) - } - override def toString() = "%s:%d".format(label, queueNumber) -} - -private[actors] object MessageQueueTracer { - // for tracing purposes - private var queueNumberAssigner = 0 - private def getQueueNumber = synchronized { - queueNumberAssigner += 1 - queueNumberAssigner - } -} diff --git a/src/actors/scala/actors/OutputChannel.scala b/src/actors/scala/actors/OutputChannel.scala deleted file mode 100644 index f0f475e123..0000000000 --- a/src/actors/scala/actors/OutputChannel.scala +++ /dev/null @@ -1,48 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.actors - -/** - * A common interface for all channels to which values can be sent. - * - * @author Philipp Haller - * - * @define actor `OutputChannel` - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -trait OutputChannel[-Msg] { - - /** - * Sends `msg` to this $actor (asynchronous). - * - * @param msg the message to send - */ - def !(msg: Msg): Unit - - /** - * Sends `msg` to this $actor (asynchronous) supplying - * explicit reply destination. - * - * @param msg the message to send - * @param replyTo the reply destination - */ - def send(msg: Msg, replyTo: OutputChannel[Any]): Unit - - /** - * Forwards `msg` to this $actor (asynchronous). - * - * @param msg the message to forward - */ - def forward(msg: Msg): Unit - - /** - * Returns the `Actor` that is receiving from this $actor. - */ - def receiver: InternalActor -} diff --git a/src/actors/scala/actors/ReactChannel.scala b/src/actors/scala/actors/ReactChannel.scala deleted file mode 100644 index 7e34681fb6..0000000000 --- a/src/actors/scala/actors/ReactChannel.scala +++ /dev/null @@ -1,121 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors - -/** - * @author Philipp Haller - */ -private[actors] class ReactChannel[Msg](receiver: InternalReplyReactor) extends InputChannel[Msg] { - - private case class SendToReactor(channel: ReactChannel[Msg], msg: Msg) - - /** - * Sends a message to this ReactChannel. - * - * @param msg the message to be sent - */ - def !(msg: Msg) { - receiver ! SendToReactor(this, msg) - } - - /** - * Sends a message to this `ReactChannel` (asynchronous) supplying - * explicit reply destination. - * - * @param msg the message to send - * @param replyTo the reply destination - */ - def send(msg: Msg, replyTo: OutputChannel[Any]) { - receiver.send(SendToReactor(this, msg), replyTo) - } - - /** - * Forwards `msg` to `'''this'''` keeping the last sender as sender - * instead of `self`. - */ - def forward(msg: Msg) { - receiver forward SendToReactor(this, msg) - } - - /** - * Receives a message from this `ReactChannel`. - * - * This method ''never'' returns. Therefore, the rest of the computation - * has to be contained in the actions of the partial function. - * - * @param f a partial function with message patterns and actions - */ - def react(f: PartialFunction[Msg, Unit]): Nothing = { - val C = this - receiver.react { - case SendToReactor(C, msg) if (f.isDefinedAt(msg.asInstanceOf[Msg])) => - f(msg.asInstanceOf[Msg]) - } - } - - /** - * Receives a message from this `ReactChannel` within a certain time span. - * - * This method ''never'' returns. Therefore, the rest of the computation - * has to be contained in the actions of the partial function. - * - * @param msec the time span before timeout - * @param f a partial function with message patterns and actions - */ - def reactWithin(msec: Long)(f: PartialFunction[Any, Unit]): Nothing = { - val C = this - val recvActor = receiver.asInstanceOf[Actor] - recvActor.reactWithin(msec) { - case C ! msg if (f.isDefinedAt(msg.asInstanceOf[Msg])) => - f(msg.asInstanceOf[Msg]) - case TIMEOUT => f(TIMEOUT) - } - } - - /** - * Receives a message from this `ReactChannel`. - * - * @param f a partial function with message patterns and actions - * @return result of processing the received value - */ - def receive[R](f: PartialFunction[Msg, R]): R = { - val C = this - val recvActor = receiver.asInstanceOf[Actor] - recvActor.receive { - case C ! msg if (f.isDefinedAt(msg.asInstanceOf[Msg])) => - f(msg.asInstanceOf[Msg]) - } - } - - /** - * Receives a message from this `ReactChannel` within a certain time span. - * - * @param msec the time span before timeout - * @param f a partial function with message patterns and actions - * @return result of processing the received value - */ - def receiveWithin[R](msec: Long)(f: PartialFunction[Any, R]): R = { - val C = this - val recvActor = receiver.asInstanceOf[Actor] - recvActor.receiveWithin(msec) { - case C ! msg if (f.isDefinedAt(msg.asInstanceOf[Msg])) => - f(msg.asInstanceOf[Msg]) - case TIMEOUT => f(TIMEOUT) - } - } - - /** - * Receives the next message from this `ReactChannel`. - */ - def ? : Msg = receive { - case x => x - } - -} diff --git a/src/actors/scala/actors/Reactor.scala b/src/actors/scala/actors/Reactor.scala deleted file mode 100644 index aa985b3a17..0000000000 --- a/src/actors/scala/actors/Reactor.scala +++ /dev/null @@ -1,307 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors - -import scala.actors.scheduler.{DelegatingScheduler, ExecutorScheduler, - ForkJoinScheduler, ThreadPoolConfig} -import java.util.concurrent.{ThreadPoolExecutor, TimeUnit, LinkedBlockingQueue} -import scala.language.implicitConversions - -private[actors] object Reactor { - - val scheduler = new DelegatingScheduler { - def makeNewScheduler: IScheduler = { - val sched = if (!ThreadPoolConfig.useForkJoin) { - // default is non-daemon - val workQueue = new LinkedBlockingQueue[Runnable] - ExecutorScheduler( - new ThreadPoolExecutor(ThreadPoolConfig.corePoolSize, - ThreadPoolConfig.maxPoolSize, - 60000L, - TimeUnit.MILLISECONDS, - workQueue, - new ThreadPoolExecutor.CallerRunsPolicy)) - } else { - // default is non-daemon, non-fair - val s = new ForkJoinScheduler(ThreadPoolConfig.corePoolSize, ThreadPoolConfig.maxPoolSize, false, false) - s.start() - s - } - Debug.info(this+": starting new "+sched+" ["+sched.getClass+"]") - sched - } - } - - val waitingForNone: PartialFunction[Any, Unit] = new PartialFunction[Any, Unit] { - def isDefinedAt(x: Any) = false - def apply(x: Any) {} - } -} - -/** - * Super trait of all actor traits. - * - * @author Philipp Haller - * - * @define actor reactor - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -trait Reactor[Msg >: Null] extends OutputChannel[Msg] with Combinators { - - /* The $actor's mailbox. */ - private[actors] val mailbox = new MQueue[Msg]("Reactor") - - // guarded by this - private[actors] val sendBuffer = new MQueue[Msg]("SendBuffer") - - /* Whenever this $actor executes on some thread, `waitingFor` is - * guaranteed to be equal to `Reactor.waitingForNone`. - * - * In other words, whenever `waitingFor` is not equal to - * `Reactor.waitingForNone`, this $actor is guaranteed not to execute - * on some thread. - * - * If the $actor waits in a `react`, `waitingFor` holds the - * message handler that `react` was called with. - * - * guarded by this - */ - private[actors] var waitingFor: PartialFunction[Msg, Any] = - Reactor.waitingForNone - - // guarded by this - private[actors] var _state: Actor.State.Value = Actor.State.New - - /** - * The $actor's behavior is specified by implementing this method. - */ - def act(): Unit - - /** - * This partial function is applied to exceptions that propagate out of - * this $actor's body. - */ - protected[actors] def exceptionHandler: PartialFunction[Exception, Unit] = - Map() - - protected[actors] def scheduler: IScheduler = - Reactor.scheduler - - protected[actors] def mailboxSize: Int = - mailbox.size - - def send(msg: Msg, replyTo: OutputChannel[Any]) { - val todo = synchronized { - if (waitingFor ne Reactor.waitingForNone) { - val savedWaitingFor = waitingFor - waitingFor = Reactor.waitingForNone - startSearch(msg, replyTo, savedWaitingFor) - } else { - sendBuffer.append(msg, replyTo) - () => { /* do nothing */ } - } - } - todo() - } - - private[actors] def startSearch(msg: Msg, replyTo: OutputChannel[Any], handler: PartialFunction[Msg, Any]) = - () => scheduler execute makeReaction(() => { - val startMbox = new MQueue[Msg]("Start") - synchronized { startMbox.append(msg, replyTo) } - searchMailbox(startMbox, handler, true) - }) - - private[actors] final def makeReaction(fun: () => Unit): Runnable = - makeReaction(fun, null, null) - - /* This method is supposed to be overridden. */ - private[actors] def makeReaction(fun: () => Unit, handler: PartialFunction[Msg, Any], msg: Msg): Runnable = - new ReactorTask(this, fun, handler, msg) - - private[actors] def resumeReceiver(item: (Msg, OutputChannel[Any]), handler: PartialFunction[Msg, Any], onSameThread: Boolean) { - if (onSameThread) - makeReaction(null, handler, item._1).run() - else - scheduleActor(handler, item._1) - - /* Here, we throw a SuspendActorControl to avoid - terminating this actor when the current ReactorTask - is finished. - - The SuspendActorControl skips the termination code - in ReactorTask. - */ - throw Actor.suspendException - } - - def !(msg: Msg) { - send(msg, null) - } - - def forward(msg: Msg) { - send(msg, null) - } - - def receiver: Actor = this.asInstanceOf[Actor] - - // guarded by this - private[actors] def drainSendBuffer(mbox: MQueue[Msg]) { - sendBuffer.foreachDequeue(mbox) - } - - private[actors] def searchMailbox(startMbox: MQueue[Msg], - handler: PartialFunction[Msg, Any], - resumeOnSameThread: Boolean) { - var tmpMbox = startMbox - var done = false - while (!done) { - val qel = tmpMbox.extractFirst(handler) - if (tmpMbox ne mailbox) - tmpMbox.foreachAppend(mailbox) - if (null eq qel) { - synchronized { - // in mean time new stuff might have arrived - if (!sendBuffer.isEmpty) { - tmpMbox = new MQueue[Msg]("Temp") - drainSendBuffer(tmpMbox) - // keep going - } else { - waitingFor = handler - /* Here, we throw a SuspendActorControl to avoid - terminating this actor when the current ReactorTask - is finished. - - The SuspendActorControl skips the termination code - in ReactorTask. - */ - throw Actor.suspendException - } - } - } else { - resumeReceiver((qel.msg, qel.session), handler, resumeOnSameThread) - done = true - } - } - } - - /** - * Receives a message from this $actor's mailbox. - * - * This method never returns. Therefore, the rest of the computation - * has to be contained in the actions of the partial function. - * - * @param handler a partial function with message patterns and actions - */ - protected def react(handler: PartialFunction[Msg, Unit]): Nothing = { - synchronized { drainSendBuffer(mailbox) } - searchMailbox(mailbox, handler, false) - throw Actor.suspendException - } - - /* This method is guaranteed to be executed from inside - * an $actor's act method. - * - * assume handler != null - * - * never throws SuspendActorControl - */ - private[actors] def scheduleActor(handler: PartialFunction[Msg, Any], msg: Msg) { - scheduler executeFromActor makeReaction(null, handler, msg) - } - - private[actors] def preAct() = {} - - // guarded by this - private[actors] def dostart() { - _state = Actor.State.Runnable - scheduler newActor this - scheduler execute makeReaction(() => { - preAct() - act() - }, null, null) - } - - /** - * Starts this $actor. This method is idempotent. - */ - def start(): Reactor[Msg] = synchronized { - if (_state == Actor.State.New) - dostart() - this - } - - /** - * Restarts this $actor. - * - * @throws java.lang.IllegalStateException if the $actor is not in state `Actor.State.Terminated` - */ - def restart(): Unit = synchronized { - if (_state == Actor.State.Terminated) - dostart() - else - throw new IllegalStateException("restart only in state "+Actor.State.Terminated) - } - - /** Returns the execution state of this $actor. - * - * @return the execution state - */ - def getState: Actor.State.Value = synchronized { - if (waitingFor ne Reactor.waitingForNone) - Actor.State.Suspended - else - _state - } - - implicit def mkBody[A](body: => A) = new InternalActor.Body[A] { - def andThen[B](other: => B): Unit = Reactor.this.seq(body, other) - } - - /* This closure is used to implement control-flow operations - * built on top of `seq`. Note that the only invocation of - * `kill` is supposed to be inside `ReactorTask.run`. - */ - @volatile - private[actors] var kill: () => Unit = - () => { exit() } - - private[actors] def seq[a, b](first: => a, next: => b): Unit = { - val killNext = this.kill - this.kill = () => { - this.kill = killNext - - // to avoid stack overflow: - // instead of directly executing `next`, - // schedule as continuation - scheduleActor({ case _ => next }, null) - throw Actor.suspendException - } - first - throw new KillActorControl - } - - protected[actors] def exit(): Nothing = { - terminated() - throw Actor.suspendException - } - - private[actors] def internalPostStop() = {} - - private[actors] def terminated() { - synchronized { - _state = Actor.State.Terminated - // reset waitingFor, otherwise getState returns Suspended - waitingFor = Reactor.waitingForNone - } - internalPostStop() - scheduler.terminated(this) - } - -} diff --git a/src/actors/scala/actors/ReactorCanReply.scala b/src/actors/scala/actors/ReactorCanReply.scala deleted file mode 100644 index e30efcbed8..0000000000 --- a/src/actors/scala/actors/ReactorCanReply.scala +++ /dev/null @@ -1,90 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors - -/** - * Provides message send operations that - * may result in a response from the receiver. - * - * @author Philipp Haller - */ -private[actors] trait ReactorCanReply extends CanReply[Any, Any] { - _: InternalReplyReactor => - - type Future[+P] = scala.actors.Future[P] - - def !?(msg: Any): Any = - (this !! msg)() - - def !?(msec: Long, msg: Any): Option[Any] = { - val myself = Actor.rawSelf(this.scheduler) - val res = new scala.concurrent.SyncVar[Any] - val out = new OutputChannel[Any] { - def !(msg: Any) = - res set msg - def send(msg: Any, replyTo: OutputChannel[Any]) = - res set msg - def forward(msg: Any) = - res set msg - def receiver = - myself.asInstanceOf[Actor] - } - this.send(msg, out) - res.get(msec) - } - - def !!(msg: Any): Future[Any] = - this !! (msg, { case x => x }) - - def !![A](msg: Any, handler: PartialFunction[Any, A]): Future[A] = { - val myself = Actor.rawSelf(this.scheduler) - val ftch = new ReactChannel[A](myself) - val res = new scala.concurrent.SyncVar[A] - - val out = new OutputChannel[Any] { - def !(msg: Any) = { - val msg1 = handler(msg) - ftch ! msg1 - res set msg1 - } - def send(msg: Any, replyTo: OutputChannel[Any]) = { - val msg1 = handler(msg) - ftch.send(msg1, replyTo) - res set msg1 - } - def forward(msg: Any) = { - val msg1 = handler(msg) - ftch forward msg1 - res set msg1 - } - def receiver = - myself.asInstanceOf[Actor] - } - - this.send(msg, out) - - new Future[A] { - def apply() = { - if (!isSet) - fvalue = Some(res.get) - - fvalueTyped - } - def respond(k: A => Unit): Unit = - if (isSet) k(fvalueTyped) - else inputChannel.react { - case any => fvalue = Some(any); k(fvalueTyped) - } - def isSet = - !fvalue.isEmpty - def inputChannel = ftch - } - } -} diff --git a/src/actors/scala/actors/ReactorTask.scala b/src/actors/scala/actors/ReactorTask.scala deleted file mode 100644 index 1ca061b40d..0000000000 --- a/src/actors/scala/actors/ReactorTask.scala +++ /dev/null @@ -1,74 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors - -import java.lang.Runnable -import java.util.concurrent.Callable - -import scala.concurrent.forkjoin.RecursiveAction - -/** - * @author Philipp Haller - */ -private[actors] class ReactorTask[Msg >: Null](var reactor: Reactor[Msg], - var fun: () => Any, - var handler: PartialFunction[Msg, Any], - var msg: Msg) - extends RecursiveAction with Callable[Unit] with Runnable { - - def run() { - try { - beginExecution() - try { - if (fun eq null) - handler(msg) - else - fun() - } catch { - case _: KillActorControl => - // do nothing - - case e: Exception if reactor.exceptionHandler.isDefinedAt(e) => - reactor.exceptionHandler(e) - } - reactor.kill() - } - catch { - case _: SuspendActorControl => - // do nothing (continuation is already saved) - - case e: Throwable => - terminateExecution(e) - reactor.terminated() - if (!e.isInstanceOf[Exception]) - throw e - } finally { - suspendExecution() - this.reactor = null - this.fun = null - this.handler = null - this.msg = null - } - } - - def call() = run() - - def compute() = run() - - protected def beginExecution() {} - - protected def suspendExecution() {} - - protected def terminateExecution(e: Throwable) { - Console.err.println(reactor+": caught "+e) - e.printStackTrace() - } - -} diff --git a/src/actors/scala/actors/ReplyReactor.scala b/src/actors/scala/actors/ReplyReactor.scala deleted file mode 100644 index 01e6da000f..0000000000 --- a/src/actors/scala/actors/ReplyReactor.scala +++ /dev/null @@ -1,13 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ -package scala.actors - -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -trait ReplyReactor extends InternalReplyReactor { - protected[actors] def sender: OutputChannel[Any] = super.internalSender -} diff --git a/src/actors/scala/actors/ReplyReactorTask.scala b/src/actors/scala/actors/ReplyReactorTask.scala deleted file mode 100644 index ea9070fab7..0000000000 --- a/src/actors/scala/actors/ReplyReactorTask.scala +++ /dev/null @@ -1,40 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.actors - -/** - * @author Philipp Haller - * @note This class inherits a public var called 'reactor' from ReactorTask, - * and also defines a constructor parameter which shadows it (which makes any - * changes to the underlying var invisible.) I can't figure out what's supposed - * to happen, so I renamed the constructor parameter to at least be less confusing. - */ -private[actors] class ReplyReactorTask(replyReactor: InternalReplyReactor, - fun: () => Unit, - handler: PartialFunction[Any, Any], - msg: Any) - extends ReactorTask(replyReactor, fun, handler, msg) { - - var saved: InternalReplyReactor = _ - - protected override def beginExecution() { - saved = Actor.tl.get - // !!! If this is supposed to be setting the current contents of the - // inherited mutable var rather than always the value given in the constructor, - // then it should be changed to "set reactor". - Actor.tl set replyReactor - } - - protected override def suspendExecution() { - Actor.tl set saved - } - -} diff --git a/src/actors/scala/actors/Scheduler.scala b/src/actors/scala/actors/Scheduler.scala deleted file mode 100644 index 67c8e5cd10..0000000000 --- a/src/actors/scala/actors/Scheduler.scala +++ /dev/null @@ -1,40 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors - -import scheduler.{DelegatingScheduler, ForkJoinScheduler, ResizableThreadPoolScheduler, ThreadPoolConfig} - -/** - * Used by [[scala.actors.Actor]] instances to - * execute tasks of an actor execution. - * - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -object Scheduler extends DelegatingScheduler { - - Debug.info("initializing "+this+"...") - - def makeNewScheduler: IScheduler = { - val sched = if (!ThreadPoolConfig.useForkJoin) { - // default is non-daemon - val s = new ResizableThreadPoolScheduler(false) - s.start() - s - } else { - // default is non-daemon, fair - val s = new ForkJoinScheduler - s.start() - s - } - Debug.info(this+": starting new "+sched+" ["+sched.getClass+"]") - sched - } -} diff --git a/src/actors/scala/actors/SchedulerAdapter.scala b/src/actors/scala/actors/SchedulerAdapter.scala deleted file mode 100644 index b8e66dd6cc..0000000000 --- a/src/actors/scala/actors/SchedulerAdapter.scala +++ /dev/null @@ -1,68 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors - -/** Adapts - * the behavior of the standard [[scala.actors.Scheduler]] object. - * - * Providing an implementation for the - * execute(f: => Unit) method is sufficient to - * obtain a concrete IScheduler implementation. - * - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -trait SchedulerAdapter extends IScheduler { - - /** Submits a Runnable for execution. - * - * @param task the task to be executed - */ - def execute(task: Runnable): Unit = - execute { task.run() } - - /** Shuts down the scheduler. - */ - def shutdown(): Unit = - Scheduler.shutdown() - - /** When the scheduler is active, it can execute tasks. - */ - def isActive: Boolean = - Scheduler.isActive - - /** Registers a newly created actor with this scheduler. - * - * @param a the actor to be registered - */ - def newActor(a: TrackedReactor) = - Scheduler.newActor(a) - - /** Unregisters an actor from this scheduler, because it - * has terminated. - * - * @param a the actor to be unregistered - */ - def terminated(a: TrackedReactor) = - Scheduler.terminated(a) - - /** Registers a closure to be executed when the specified - * actor terminates. - * - * @param a the actor - * @param f the closure to be registered - */ - def onTerminate(a: TrackedReactor)(f: => Unit) = - Scheduler.onTerminate(a)(f) - - def managedBlock(blocker: scala.concurrent.ManagedBlocker) { - blocker.block() - } -} diff --git a/src/actors/scala/actors/UncaughtException.scala b/src/actors/scala/actors/UncaughtException.scala deleted file mode 100644 index 02b916a3b5..0000000000 --- a/src/actors/scala/actors/UncaughtException.scala +++ /dev/null @@ -1,34 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.actors - -/** - * The exit reason when an actor fails to catch an exception. - * - * @param actor the actor that threw the exception - * @param message the message the actor was processing, or None if no message (e.g. on initial startup) - * @param sender the sender of the most recent message - * @param thread the thread on which the actor was running - * @param cause the uncaught exception - * - * @author Philipp Haller - * @author Erik Engbrecht - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -case class UncaughtException(actor: InternalActor, - message: Option[Any], - sender: Option[OutputChannel[Any]], - thread: Thread, - cause: Throwable) -extends Exception(cause) { - - override def toString() = - "UncaughtException("+actor+","+message+","+sender+","+cause+")" - -} diff --git a/src/actors/scala/actors/package.scala b/src/actors/scala/actors/package.scala deleted file mode 100644 index ae960860cf..0000000000 --- a/src/actors/scala/actors/package.scala +++ /dev/null @@ -1,23 +0,0 @@ -package scala - -/** - * A library that provides both asynchronous and synchronous messaging to allow - * for concurrent programming without explicit synchronization. - * - * == Guide == - * - * A detailed guide for the actors library is available - * [[http://docs.scala-lang.org/overviews/core/actors.html]]. - * - * == Getting Started == - * - * A starting point for using the actors library would be [[scala.actors.Reactor]], - * [[scala.actors.ReplyReactor]], or [[scala.actors.Actor]] or their companion objects. - * - * @note As of release 2.10.1, replaced by akka.actor package. For migration of existing actors refer to the Actors Migration Guide. - */ -package object actors { - - // type of Reactors tracked by termination detector - private[actors] type TrackedReactor = Reactor[A] forSome { type A >: Null } -} diff --git a/src/actors/scala/actors/remote/FreshNameCreator.scala b/src/actors/scala/actors/remote/FreshNameCreator.scala deleted file mode 100644 index f7cf29387e..0000000000 --- a/src/actors/scala/actors/remote/FreshNameCreator.scala +++ /dev/null @@ -1,36 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors -package remote - -object FreshNameCreator { - - protected var counter = 0 - protected val counters = new scala.collection.mutable.HashMap[String, Int] - - /** - * Create a fresh name with the given prefix. It is guaranteed - * that the returned name has never been returned by a previous - * call to this function (provided the prefix does not end in a digit). - */ - def newName(prefix: String): Symbol = { - val count = counters.get(prefix) match { - case Some(last) => last + 1 - case None => 0 - } - counters.update(prefix, count) - Symbol(prefix + count) - } - - def newName(): Symbol = { - counter += 1 - Symbol("$" + counter + "$") - } -} diff --git a/src/actors/scala/actors/remote/JavaSerializer.scala b/src/actors/scala/actors/remote/JavaSerializer.scala deleted file mode 100644 index 7549bbf429..0000000000 --- a/src/actors/scala/actors/remote/JavaSerializer.scala +++ /dev/null @@ -1,63 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors -package remote - -import java.io.{ByteArrayInputStream, ByteArrayOutputStream, - ObjectInputStream, ObjectOutputStream, InputStream, - ObjectStreamClass} - -/** - * @author Guy Oliver - */ -private[remote] class CustomObjectInputStream(in: InputStream, cl: ClassLoader) -extends ObjectInputStream(in) { - override def resolveClass(cd: ObjectStreamClass): Class[_] = - try { - cl.loadClass(cd.getName()) - } catch { - case cnf: ClassNotFoundException => - super.resolveClass(cd) - } - override def resolveProxyClass(interfaces: Array[String]): Class[_] = - try { - val ifaces = interfaces map { iface => cl.loadClass(iface) } - java.lang.reflect.Proxy.getProxyClass(cl, ifaces: _*) - } catch { - case e: ClassNotFoundException => - super.resolveProxyClass(interfaces) - } -} - -/** - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -class JavaSerializer(serv: Service, cl: ClassLoader) extends Serializer(serv) { - def serialize(o: AnyRef): Array[Byte] = { - val bos = new ByteArrayOutputStream() - val out = new ObjectOutputStream(bos) - out.writeObject(o) - out.flush() - bos.toByteArray() - } - - def deserialize(bytes: Array[Byte]): AnyRef = { - val bis = new ByteArrayInputStream(bytes) - - // use custom stream only if cl != null - val in = if (cl != null) - new CustomObjectInputStream(bis, cl) - else - new ObjectInputStream(bis) - - in.readObject() - } -} diff --git a/src/actors/scala/actors/remote/NetKernel.scala b/src/actors/scala/actors/remote/NetKernel.scala deleted file mode 100644 index 57d7af6d26..0000000000 --- a/src/actors/scala/actors/remote/NetKernel.scala +++ /dev/null @@ -1,147 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors -package remote - -import scala.collection.mutable - -case class NamedSend(senderLoc: Locator, receiverLoc: Locator, data: Array[Byte], session: Symbol) - -case class RemoteApply0(senderLoc: Locator, receiverLoc: Locator, rfun: Function2[AbstractActor, Proxy, Unit]) -case class LocalApply0(rfun: Function2[AbstractActor, Proxy, Unit], a: AbstractActor) - -case class SendTo(a: OutputChannel[Any], msg: Any, session: Symbol) -case object Terminate - -case class Locator(node: Node, name: Symbol) - -/** - * @version 0.9.17 - * @author Philipp Haller - */ -private[remote] class NetKernel(service: Service) { - - def sendToNode(node: Node, msg: AnyRef) = { - val bytes = service.serializer.serialize(msg) - service.send(node, bytes) - } - - def namedSend(senderLoc: Locator, receiverLoc: Locator, - msg: AnyRef, session: Symbol) { - val bytes = service.serializer.serialize(msg) - sendToNode(receiverLoc.node, NamedSend(senderLoc, receiverLoc, bytes, session)) - } - - private val actors = new mutable.HashMap[Symbol, OutputChannel[Any]] - private val names = new mutable.HashMap[OutputChannel[Any], Symbol] - - def register(name: Symbol, a: OutputChannel[Any]): Unit = synchronized { - actors(name) = a - names(a) = name - } - - def getOrCreateName(from: OutputChannel[Any]) = names.get(from) match { - case None => - val freshName = FreshNameCreator.newName("remotesender") - register(freshName, from) - freshName - case Some(name) => - name - } - - def send(node: Node, name: Symbol, msg: AnyRef): Unit = - send(node, name, msg, 'nosession) - - def send(node: Node, name: Symbol, msg: AnyRef, session: Symbol) { - val senderLoc = Locator(service.node, getOrCreateName(Actor.self(Scheduler))) - val receiverLoc = Locator(node, name) - namedSend(senderLoc, receiverLoc, msg, session) - } - - def forward(from: OutputChannel[Any], node: Node, name: Symbol, msg: AnyRef, session: Symbol) { - val senderLoc = Locator(service.node, getOrCreateName(from)) - val receiverLoc = Locator(node, name) - namedSend(senderLoc, receiverLoc, msg, session) - } - - def remoteApply(node: Node, name: Symbol, from: OutputChannel[Any], rfun: Function2[AbstractActor, Proxy, Unit]) { - val senderLoc = Locator(service.node, getOrCreateName(from)) - val receiverLoc = Locator(node, name) - sendToNode(receiverLoc.node, RemoteApply0(senderLoc, receiverLoc, rfun)) - } - - def createProxy(node: Node, sym: Symbol): Proxy = { - val p = new Proxy(node, sym, this) - proxies((node, sym)) = p - p - } - - val proxies = new mutable.HashMap[(Node, Symbol), Proxy] - - def getOrCreateProxy(senderNode: Node, senderName: Symbol): Proxy = - proxies.synchronized { - proxies.get((senderNode, senderName)) match { - case Some(senderProxy) => senderProxy - case None => createProxy(senderNode, senderName) - } - } - - /* Register proxy if no other proxy has been registered. - */ - def registerProxy(senderNode: Node, senderName: Symbol, p: Proxy): Unit = - proxies.synchronized { - proxies.get((senderNode, senderName)) match { - case Some(senderProxy) => // do nothing - case None => proxies((senderNode, senderName)) = p - } - } - - def processMsg(senderNode: Node, msg: AnyRef): Unit = synchronized { - msg match { - case cmd@RemoteApply0(senderLoc, receiverLoc, rfun) => - Debug.info(this+": processing "+cmd) - actors.get(receiverLoc.name) match { - case Some(a) => - val senderProxy = getOrCreateProxy(senderLoc.node, senderLoc.name) - senderProxy.send(LocalApply0(rfun, a.asInstanceOf[AbstractActor]), null) - - case None => - // message is lost - Debug.info(this+": lost message") - } - - case cmd@NamedSend(senderLoc, receiverLoc, data, session) => - Debug.info(this+": processing "+cmd) - actors.get(receiverLoc.name) match { - case Some(a) => - try { - val msg = service.serializer.deserialize(data) - val senderProxy = getOrCreateProxy(senderLoc.node, senderLoc.name) - senderProxy.send(SendTo(a, msg, session), null) - } catch { - case e: Exception => - Debug.error(this+": caught "+e) - } - - case None => - // message is lost - Debug.info(this+": lost message") - } - } - } - - def terminate() { - // tell all proxies to terminate - proxies.values foreach { _.send(Terminate, null) } - - // tell service to terminate - service.terminate() - } -} diff --git a/src/actors/scala/actors/remote/Proxy.scala b/src/actors/scala/actors/remote/Proxy.scala deleted file mode 100644 index 2cb03544f2..0000000000 --- a/src/actors/scala/actors/remote/Proxy.scala +++ /dev/null @@ -1,190 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors -package remote - -import scala.collection.mutable - -/** - * @author Philipp Haller - */ -private[remote] class Proxy(node: Node, name: Symbol, @transient var kernel: NetKernel) extends AbstractActor with Serializable { - import java.io.{IOException, ObjectOutputStream, ObjectInputStream} - - type Future[+P] = scala.actors.Future[P] - - @transient - private[remote] var del: Actor = null - startDelegate() - - @throws(classOf[IOException]) - private def writeObject(out: ObjectOutputStream) { - out.defaultWriteObject() - } - - @throws(classOf[ClassNotFoundException]) @throws(classOf[IOException]) - private def readObject(in: ObjectInputStream) { - in.defaultReadObject() - setupKernel() - startDelegate() - } - - private def startDelegate() { - del = new DelegateActor(this, node, name, kernel) - del.start() - } - - private def setupKernel() { - kernel = RemoteActor.someNetKernel - kernel.registerProxy(node, name, this) - } - - def !(msg: Any): Unit = - del ! msg - - def send(msg: Any, replyCh: OutputChannel[Any]): Unit = - del.send(msg, replyCh) - - def forward(msg: Any): Unit = - del.forward(msg) - - def receiver: Actor = - del - - def !?(msg: Any): Any = - del !? msg - - def !?(msec: Long, msg: Any): Option[Any] = - del !? (msec, msg) - - def !!(msg: Any): Future[Any] = - del !! msg - - def !![A](msg: Any, f: PartialFunction[Any, A]): Future[A] = - del !! (msg, f) - - def linkTo(to: AbstractActor): Unit = - del ! Apply0(new LinkToFun) - - def unlinkFrom(from: AbstractActor): Unit = - del ! Apply0(new UnlinkFromFun) - - def exit(from: AbstractActor, reason: AnyRef): Unit = - del ! Apply0(new ExitFun(reason)) - - override def toString() = - name+"@"+node -} - -// Proxy is private[remote], but these classes are public and use it in a public -// method signature. That makes the only method they have non-overridable. -// So I made them final, which seems appropriate anyway. - -final class LinkToFun extends Function2[AbstractActor, Proxy, Unit] with Serializable { - def apply(target: AbstractActor, creator: Proxy) { - target.linkTo(creator) - } - override def toString = - "" -} - -final class UnlinkFromFun extends Function2[AbstractActor, Proxy, Unit] with Serializable { - def apply(target: AbstractActor, creator: Proxy) { - target.unlinkFrom(creator) - } - override def toString = - "" -} - -final class ExitFun(reason: AnyRef) extends Function2[AbstractActor, Proxy, Unit] with Serializable { - def apply(target: AbstractActor, creator: Proxy) { - target.exit(creator, reason) - } - override def toString = - "("+reason.toString+")" -} - -private[remote] case class Apply0(rfun: Function2[AbstractActor, Proxy, Unit]) - -/** - * @author Philipp Haller - */ -private[remote] class DelegateActor(creator: Proxy, node: Node, name: Symbol, kernel: NetKernel) extends Actor { - var channelMap = new mutable.HashMap[Symbol, OutputChannel[Any]] - var sessionMap = new mutable.HashMap[OutputChannel[_], Symbol] - - def act() { - Actor.loop { - react { - case cmd@Apply0(rfun) => - kernel.remoteApply(node, name, sender, rfun) - - case cmd@LocalApply0(rfun, target) => - rfun(target, creator) - - // Request from remote proxy. - // `this` is local proxy. - case cmd@SendTo(out, msg, session) => - if (session.name == "nosession") { - // local send - out.send(msg, this) - } else { - // is this an active session? - channelMap.get(session) match { - case None => - // create a new reply channel... - val replyCh = new Channel[Any](this) - // ...that maps to session - sessionMap(replyCh) = session - // local send - out.send(msg, replyCh) - - // finishes request-reply cycle - case Some(replyCh) => - channelMap -= session - replyCh ! msg - } - } - - case cmd@Terminate => - exit() - - // local proxy receives response to - // reply channel - case ch ! resp => - // lookup session ID - sessionMap.get(ch) match { - case Some(sid) => - sessionMap -= ch - val msg = resp.asInstanceOf[AnyRef] - // send back response - kernel.forward(sender, node, name, msg, sid) - - case None => - Debug.info(this+": cannot find session for "+ch) - } - - // remote proxy receives request - case msg: AnyRef => - // find out whether it's a synchronous send - if (sender.getClass.toString.contains("Channel")) { - // create fresh session ID... - val fresh = FreshNameCreator.newName(node+"@"+name) - // ...that maps to reply channel - channelMap(fresh) = sender - kernel.forward(sender, node, name, msg, fresh) - } else { - kernel.forward(sender, node, name, msg, 'nosession) - } - } - } - } - -} diff --git a/src/actors/scala/actors/remote/RemoteActor.scala b/src/actors/scala/actors/remote/RemoteActor.scala deleted file mode 100644 index 2daf9ceb43..0000000000 --- a/src/actors/scala/actors/remote/RemoteActor.scala +++ /dev/null @@ -1,132 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.actors -package remote - - -/** - * This object provides methods for creating, registering, and - * selecting remotely accessible actors. - * - * A remote actor is typically created like this: - * {{{ - * actor { - * alive(9010) - * register('myName, self) - * - * // behavior - * } - * }}} - * It can be accessed by an actor running on a (possibly) - * different node by selecting it in the following way: - * {{{ - * actor { - * // ... - * val c = select(Node("127.0.0.1", 9010), 'myName) - * c ! msg - * // ... - * } - * }}} - * - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -object RemoteActor { - - private val kernels = new scala.collection.mutable.HashMap[InternalActor, NetKernel] - - /* If set to null (default), the default class loader - * of java.io.ObjectInputStream is used for deserializing - * objects sent as messages. - */ - private var cl: ClassLoader = null - - def classLoader: ClassLoader = cl - def classLoader_=(x: ClassLoader) { cl = x } - - /** - * Makes self remotely accessible on TCP port - * port. - */ - def alive(port: Int): Unit = synchronized { - createNetKernelOnPort(port) - } - - private def createNetKernelOnPort(port: Int): NetKernel = { - val serv = TcpService(port, cl) - val kern = serv.kernel - val s = Actor.self(Scheduler) - kernels(s) = kern - - s.onTerminate { - Debug.info("alive actor "+s+" terminated") - // remove mapping for `s` - kernels -= s - // terminate `kern` when it does - // not appear as value any more - if (!kernels.valuesIterator.contains(kern)) { - Debug.info("terminating "+kern) - // terminate NetKernel - kern.terminate() - } - } - - kern - } - - /** - * Registers a under name on this - * node. - */ - def register(name: Symbol, a: Actor): Unit = synchronized { - val kernel = kernels.get(Actor.self(Scheduler)) match { - case None => - val serv = TcpService(TcpService.generatePort, cl) - kernels(Actor.self(Scheduler)) = serv.kernel - serv.kernel - case Some(k) => - k - } - kernel.register(name, a) - } - - private def selfKernel = kernels.get(Actor.self(Scheduler)) match { - case None => - // establish remotely accessible - // return path (sender) - createNetKernelOnPort(TcpService.generatePort) - case Some(k) => - k - } - - /** - * Returns (a proxy for) the actor registered under - * name on node. - */ - def select(node: Node, sym: Symbol): AbstractActor = synchronized { - selfKernel.getOrCreateProxy(node, sym) - } - - private[remote] def someNetKernel: NetKernel = - kernels.valuesIterator.next -} - - -/** - * This class represents a machine node on a TCP network. - * - * @param address the host name, or null for the loopback address. - * @param port the port number. - * - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -case class Node(address: String, port: Int) diff --git a/src/actors/scala/actors/remote/Serializer.scala b/src/actors/scala/actors/remote/Serializer.scala deleted file mode 100644 index 7be4aa6583..0000000000 --- a/src/actors/scala/actors/remote/Serializer.scala +++ /dev/null @@ -1,58 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.actors -package remote - - -import java.lang.ClassNotFoundException - -import java.io.{DataInputStream, DataOutputStream, EOFException, IOException} - -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -abstract class Serializer(val service: Service) { - def serialize(o: AnyRef): Array[Byte] - def deserialize(a: Array[Byte]): AnyRef - - @throws(classOf[IOException]) - private def readBytes(inputStream: DataInputStream): Array[Byte] = { - try { - val length = inputStream.readInt() - val bytes = new Array[Byte](length) - inputStream.readFully(bytes, 0, length) - bytes - } - catch { - case npe: NullPointerException => - throw new EOFException("Connection closed.") - } - } - - @throws(classOf[IOException]) @throws(classOf[ClassNotFoundException]) - def readObject(inputStream: DataInputStream): AnyRef = { - val bytes = readBytes(inputStream) - deserialize(bytes) - } - - @throws(classOf[IOException]) - private def writeBytes(outputStream: DataOutputStream, bytes: Array[Byte]) { - val length = bytes.length; - // original length - outputStream.writeInt(length) - outputStream.write(bytes, 0, length) - outputStream.flush() - } - - @throws(classOf[IOException]) - def writeObject(outputStream: DataOutputStream, obj: AnyRef) { - val bytes = serialize(obj) - writeBytes(outputStream, bytes) - } -} diff --git a/src/actors/scala/actors/remote/Service.scala b/src/actors/scala/actors/remote/Service.scala deleted file mode 100644 index d102df1970..0000000000 --- a/src/actors/scala/actors/remote/Service.scala +++ /dev/null @@ -1,24 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors -package remote - -/** - * @version 0.9.10 - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -trait Service { - val kernel = new NetKernel(this) - val serializer: Serializer - def node: Node - def send(node: Node, data: Array[Byte]): Unit - def terminate(): Unit -} diff --git a/src/actors/scala/actors/remote/TcpService.scala b/src/actors/scala/actors/remote/TcpService.scala deleted file mode 100644 index 69e5c46c52..0000000000 --- a/src/actors/scala/actors/remote/TcpService.scala +++ /dev/null @@ -1,292 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.actors -package remote - - -import java.io.{DataInputStream, DataOutputStream, IOException} -import java.lang.{Thread, SecurityException} -import java.net.{InetAddress, InetSocketAddress, ServerSocket, Socket, SocketTimeoutException, UnknownHostException} - -import scala.collection.mutable -import scala.util.Random - -/* Object TcpService. - * - * @version 0.9.9 - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -object TcpService { - private val random = new Random - private val ports = new mutable.HashMap[Int, TcpService] - - def apply(port: Int, cl: ClassLoader): TcpService = - ports.get(port) match { - case Some(service) => - service - case None => - val service = new TcpService(port, cl) - ports(port) = service - service.start() - Debug.info("created service at "+service.node) - service - } - - def generatePort: Int = { - var portnum = 0 - try { - portnum = 8000 + random.nextInt(500) - val socket = new ServerSocket(portnum) - socket.close() - } - catch { - case ioe: IOException => - // this happens when trying to open a socket twice - // at the same port - // try again - generatePort - case se: SecurityException => - // do nothing - } - portnum - } - - private val connectTimeoutMillis = { - val propName = "scala.actors.tcpSocket.connectTimeoutMillis" - val defaultTimeoutMillis = 0 - sys.props get propName flatMap { - timeout => - try { - val to = timeout.toInt - Debug.info(s"Using socket timeout $to") - Some(to) - } catch { - case e: NumberFormatException => - Debug.warning(s"""Could not parse $propName = "$timeout" as an Int""") - None - } - } getOrElse defaultTimeoutMillis - } - - var BufSize: Int = 65536 -} - -/* Class TcpService. - * - * @version 0.9.10 - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -class TcpService(port: Int, cl: ClassLoader) extends Thread with Service { - val serializer: JavaSerializer = new JavaSerializer(this, cl) - - private val internalNode = new Node(InetAddress.getLocalHost().getHostAddress(), port) - def node: Node = internalNode - - private val pendingSends = new mutable.HashMap[Node, List[Array[Byte]]] - - /** - * Sends a byte array to another node on the network. - * If the node is not yet up, up to `TcpService.BufSize` - * messages are buffered. - */ - def send(node: Node, data: Array[Byte]): Unit = synchronized { - - def bufferMsg(t: Throwable) { - // buffer message, so that it can be re-sent - // when remote net kernel comes up - (pendingSends.get(node): @unchecked) match { - case None => - pendingSends(node) = List(data) - case Some(msgs) if msgs.length < TcpService.BufSize => - pendingSends(node) = data :: msgs - } - } - - // retrieve worker thread (if any) that already has connection - getConnection(node) match { - case None => - // we are not connected, yet - try { - val newWorker = connect(node) - - // any pending sends? - pendingSends.get(node) match { - case None => - // do nothing - case Some(msgs) => - msgs.reverse foreach {newWorker transmit _} - pendingSends -= node - } - - newWorker transmit data - } catch { - case uhe: UnknownHostException => - bufferMsg(uhe) - case ioe: IOException => - bufferMsg(ioe) - case se: SecurityException => - // do nothing - } - case Some(worker) => - worker transmit data - } - } - - def terminate() { - shouldTerminate = true - try { - new Socket(internalNode.address, internalNode.port) - } catch { - case ce: java.net.ConnectException => - Debug.info(this+": caught "+ce) - } - } - - private var shouldTerminate = false - - override def run() { - try { - val socket = new ServerSocket(port) - while (!shouldTerminate) { - Debug.info(this+": waiting for new connection on port "+port+"...") - val nextClient = socket.accept() - if (!shouldTerminate) { - val worker = new TcpServiceWorker(this, nextClient) - Debug.info("Started new "+worker) - worker.readNode - worker.start() - } else - nextClient.close() - } - } catch { - case e: Exception => - Debug.info(this+": caught "+e) - } finally { - Debug.info(this+": shutting down...") - connections foreach { case (_, worker) => worker.halt } - } - } - - // connection management - - private val connections = - new mutable.HashMap[Node, TcpServiceWorker] - - private[actors] def addConnection(node: Node, worker: TcpServiceWorker) = synchronized { - connections(node) = worker - } - - def getConnection(n: Node) = synchronized { - connections.get(n) - } - - def isConnected(n: Node): Boolean = synchronized { - !connections.get(n).isEmpty - } - - def connect(n: Node): TcpServiceWorker = synchronized { - val socket = new Socket() - val start = System.nanoTime - try { - socket.connect(new InetSocketAddress(n.address, n.port), TcpService.connectTimeoutMillis) - } catch { - case e: SocketTimeoutException => - Debug.warning(f"Timed out connecting to $n after ${(System.nanoTime - start) / math.pow(10, 9)}%.3f seconds") - throw e - } - val worker = new TcpServiceWorker(this, socket) - worker.sendNode(n) - worker.start() - addConnection(n, worker) - worker - } - - def disconnectNode(n: Node) = synchronized { - connections.get(n) match { - case None => - // do nothing - case Some(worker) => - connections -= n - worker.halt - } - } - - def isReachable(node: Node): Boolean = - if (isConnected(node)) true - else try { - connect(node) - return true - } catch { - case uhe: UnknownHostException => false - case ioe: IOException => false - case se: SecurityException => false - } - - def nodeDown(mnode: Node): Unit = synchronized { - connections -= mnode - } -} - - -private[actors] class TcpServiceWorker(parent: TcpService, so: Socket) extends Thread { - val datain = new DataInputStream(so.getInputStream) - val dataout = new DataOutputStream(so.getOutputStream) - - var connectedNode: Node = _ - - def sendNode(n: Node) { - connectedNode = n - parent.serializer.writeObject(dataout, parent.node) - } - - def readNode() { - val node = parent.serializer.readObject(datain) - node match { - case n: Node => - connectedNode = n - parent.addConnection(n, this) - } - } - - def transmit(data: Array[Byte]): Unit = synchronized { - Debug.info(this+": transmitting data...") - dataout.writeInt(data.length) - dataout.write(data) - dataout.flush() - } - - var running = true - - def halt() = synchronized { - so.close() - running = false - } - - override def run() { - try { - while (running) { - val msg = parent.serializer.readObject(datain); - parent.kernel.processMsg(connectedNode, msg) - } - } - catch { - case ioe: IOException => - Debug.info(this+": caught "+ioe) - parent nodeDown connectedNode - case e: Exception => - Debug.info(this+": caught "+e) - parent nodeDown connectedNode - } - Debug.info(this+": service terminated at "+parent.node) - } -} diff --git a/src/actors/scala/actors/scheduler/ActorGC.scala b/src/actors/scala/actors/scheduler/ActorGC.scala deleted file mode 100644 index a27799d132..0000000000 --- a/src/actors/scala/actors/scheduler/ActorGC.scala +++ /dev/null @@ -1,101 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors -package scheduler - -import java.lang.ref.{Reference, WeakReference, ReferenceQueue} -import scala.collection.mutable - -/** - * ActorGC keeps track of the number of live actors being managed by a - * a scheduler so that it can shutdown when all of the actors it manages have - * either been explicitly terminated or garbage collected. - * - * When an actor is started, it is registered with the ActorGC via the - * `newActor` method, and when an actor is knowingly terminated - * (e.g. act method finishes, exit explicitly called, an exception is thrown), - * the ActorGC is informed via the `terminated` method. - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -trait ActorGC extends TerminationMonitor { - self: IScheduler => - - /** Actors are added to refQ in newActor. */ - private val refQ = new ReferenceQueue[TrackedReactor] - - /** - * This is a set of references to all the actors registered with - * this ActorGC. It is maintained so that the WeakReferences will - * not be GC'd before the actors to which they point. - */ - private val refSet = new mutable.HashSet[Reference[t] forSome { type t <: TrackedReactor }] - - /** newActor is invoked whenever a new actor is started. */ - override def newActor(a: TrackedReactor) = synchronized { - // registers a reference to the actor with the ReferenceQueue - val wr = new WeakReference[TrackedReactor](a, refQ) - refSet += wr - activeActors += 1 - } - - /** Checks for actors that have become garbage. */ - protected override def gc() = synchronized { - // check for unreachable actors - def drainRefQ() { - val wr = refQ.poll - if (wr != null) { - activeActors -= 1 - refSet -= wr - // continue draining - drainRefQ() - } - } - drainRefQ() - } - - /** Prints some status information on currently managed actors. */ - protected def status() { - println(this+": size of refSet: "+refSet.size) - } - - /** Checks whether all actors have terminated. */ - override private[actors] def allActorsTerminated: Boolean = synchronized { - activeActors <= 0 - } - - override def onTerminate(a: TrackedReactor)(f: => Unit): Unit = synchronized { - terminationHandlers += (a -> (() => f)) - } - - override def terminated(a: TrackedReactor) = { - super.terminated(a) - - synchronized { - // find the weak reference that points to the terminated actor, if any - refSet.find((ref: Reference[t] forSome { type t <: TrackedReactor }) => ref.get() == a) match { - case Some(r) => - // invoking clear will not cause r to be enqueued - r.clear() - refSet -= r.asInstanceOf[Reference[t] forSome { type t <: TrackedReactor }] - case None => - // do nothing - } - } - } - - private[actors] def getPendingCount = synchronized { - activeActors - } - - private[actors] def setPendingCount(cnt: Int) = synchronized { - activeActors = cnt - } - -} diff --git a/src/actors/scala/actors/scheduler/DaemonScheduler.scala b/src/actors/scala/actors/scheduler/DaemonScheduler.scala deleted file mode 100644 index b21a1aa3e6..0000000000 --- a/src/actors/scala/actors/scheduler/DaemonScheduler.scala +++ /dev/null @@ -1,34 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.actors -package scheduler - -/** - * Default scheduler for actors with daemon semantics, such as those backing futures. - * - * @author Erik Engbrecht - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -object DaemonScheduler extends DelegatingScheduler { - - protected def makeNewScheduler(): IScheduler = { - val sched = if (!ThreadPoolConfig.useForkJoin) { - val s = new ResizableThreadPoolScheduler(true) - s.start() - s - } else { - val s = new ForkJoinScheduler(true) - s.start() - s - } - Debug.info(this+": starting new "+sched+" ["+sched.getClass+"]") - sched - } - -} diff --git a/src/actors/scala/actors/scheduler/DelegatingScheduler.scala b/src/actors/scala/actors/scheduler/DelegatingScheduler.scala deleted file mode 100644 index b8a81d11a9..0000000000 --- a/src/actors/scala/actors/scheduler/DelegatingScheduler.scala +++ /dev/null @@ -1,74 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.actors -package scheduler - -import scala.concurrent.ManagedBlocker - -/** - * @author Erik Engbrecht - */ -private[actors] trait DelegatingScheduler extends IScheduler { - protected def makeNewScheduler(): IScheduler - - protected var sched: IScheduler = null - - final def impl = synchronized { - if ((sched eq null) || (!sched.isActive)) - sched = makeNewScheduler() - sched - } - - final def impl_= (scheduler: IScheduler): Unit = synchronized { - //TODO: if there is already a scheduler, should it be shutdown? - sched = scheduler - } - - /** - * Always active because it will just make a new scheduler if required - */ - def isActive: Boolean = true - - def execute(fun: => Unit) = impl.execute(fun) - - def execute(task: Runnable) = impl.execute(task) - - override def executeFromActor(task: Runnable) = impl.executeFromActor(task) - - def shutdown(): Unit = synchronized { - if (sched ne null) { - sched.shutdown() - sched = null - } - } - - def newActor(actor: TrackedReactor) = synchronized { - val createNew = if (sched eq null) - true - else sched.synchronized { - if (!sched.isActive) - true - else { - sched.newActor(actor) - false - } - } - if (createNew) { - sched = makeNewScheduler() - sched.newActor(actor) - } - } - - def terminated(actor: TrackedReactor) = impl.terminated(actor) - - def onTerminate(actor: TrackedReactor)(f: => Unit) = impl.onTerminate(actor)(f) - - override def managedBlock(blocker: ManagedBlocker): Unit = - impl.managedBlock(blocker) -} diff --git a/src/actors/scala/actors/scheduler/DrainableForkJoinPool.scala b/src/actors/scala/actors/scheduler/DrainableForkJoinPool.scala deleted file mode 100644 index 37710ec037..0000000000 --- a/src/actors/scala/actors/scheduler/DrainableForkJoinPool.scala +++ /dev/null @@ -1,11 +0,0 @@ -package scala.actors -package scheduler - -import java.util.Collection -import scala.concurrent.forkjoin.{ForkJoinPool, ForkJoinTask} - -private class DrainableForkJoinPool(parallelism: Int, maxPoolSize: Int) extends ForkJoinPool(parallelism, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true) { - - override def drainTasksTo(c: Collection[ _ >: ForkJoinTask[_]]): Int = - super.drainTasksTo(c) -} diff --git a/src/actors/scala/actors/scheduler/ExecutorScheduler.scala b/src/actors/scala/actors/scheduler/ExecutorScheduler.scala deleted file mode 100644 index 4d3ebc3c04..0000000000 --- a/src/actors/scala/actors/scheduler/ExecutorScheduler.scala +++ /dev/null @@ -1,95 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors -package scheduler - -import java.util.concurrent.{Callable, ExecutorService} -import scala.concurrent.ThreadPoolRunner - -/** - * The ExecutorScheduler object is used to create - * ExecutorScheduler instances. - * - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -object ExecutorScheduler { - - private def start(sched: ExecutorScheduler): ExecutorScheduler = { - sched.start() - sched - } - - /** Creates an ExecutorScheduler using the provided - * ExecutorService. - * - * @param exec the executor to use - * @return the scheduler - */ - def apply(exec: ExecutorService): ExecutorScheduler = - start(new ExecutorScheduler { - val executor: ExecutorService = exec - }) - - /** Creates an ExecutorScheduler using the provided - * ExecutorService. - * - * @param exec the executor to use - * @param term whether the scheduler should automatically terminate - * @return the scheduler - */ - def apply(exec: ExecutorService, term: Boolean): ExecutorScheduler = - start(new ExecutorScheduler { - val executor: ExecutorService = exec - override val terminate = term - }) - -} - -/** - * The ExecutorScheduler class uses an - * ExecutorService to execute Actors. - * - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -trait ExecutorScheduler extends Thread - with IScheduler with TerminationService - with ThreadPoolRunner { - - def execute(task: Runnable) { - super[ThreadPoolRunner].execute(task.asInstanceOf[Task[Unit]]) - } - - private class RunCallable(fun: => Unit) extends Callable[Unit] with Runnable { - def call() { fun } - def run() { fun } - } - - /** Submits a closure for execution. - * - * @param fun the closure to be executed - */ - override def execute(fun: => Unit) { - super[ThreadPoolRunner].execute((new RunCallable(fun)).asInstanceOf[Task[Unit]]) - } - - /** This method is called when the scheduler shuts down. - */ - def onShutdown(): Unit = - executor.shutdown() - - /** The scheduler is active if the underlying ExecutorService - * has not been shut down. - */ - def isActive = - (executor ne null) && !executor.isShutdown - -} diff --git a/src/actors/scala/actors/scheduler/ForkJoinScheduler.scala b/src/actors/scala/actors/scheduler/ForkJoinScheduler.scala deleted file mode 100644 index 75a98db6c8..0000000000 --- a/src/actors/scala/actors/scheduler/ForkJoinScheduler.scala +++ /dev/null @@ -1,174 +0,0 @@ -package scala.actors -package scheduler - -import java.util.{Collection, ArrayList} -import scala.concurrent.forkjoin._ - -/** The ForkJoinScheduler is backed by a lightweight - * fork-join task execution framework. - * - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -class ForkJoinScheduler(val initCoreSize: Int, val maxSize: Int, daemon: Boolean, fair: Boolean) - extends Runnable with IScheduler with TerminationMonitor { - - private var pool = makeNewPool() // guarded by this - private var terminating = false // guarded by this - private var snapshoting = false // guarded by this - - // this has to be a java.util.Collection, since this is what - // the ForkJoinPool returns. - private var drainedTasks: Collection[ForkJoinTask[_]] = null - - protected val CHECK_FREQ = 10 - - // this random number generator is only used in fair mode - private lazy val random = new java.util.Random // guarded by random - - def this(d: Boolean, f: Boolean) { - this(ThreadPoolConfig.corePoolSize, ThreadPoolConfig.maxPoolSize, d, f) - } - - def this(d: Boolean) { - this(d, true) // default is fair - } - - def this() { - this(false) // default is non-daemon - } - - private def makeNewPool(): DrainableForkJoinPool = { - val p = new DrainableForkJoinPool(initCoreSize, maxSize) - Debug.info(this+": parallelism "+p.getParallelism()) - p - } - - /** Starts this scheduler. - */ - def start() { - try { - val t = new Thread(this) - t.setDaemon(daemon) - t.setName("ForkJoinScheduler") - t.start() - } catch { - case e: Exception => - Debug.info(this+": could not create scheduler thread: "+e) - } - } - - override def run() { - try { - while (true) { - this.synchronized { - try { - wait(CHECK_FREQ.toLong) - } catch { - case _: InterruptedException => - } - - if (terminating) - throw new QuitControl - - if (allActorsTerminated) { - Debug.info(this+": all actors terminated") - terminating = true - throw new QuitControl - } - - if (!snapshoting) { - gc() - } else if (pool.isQuiescent()) { - val list = new ArrayList[ForkJoinTask[_]] - val num = pool.drainTasksTo(list) - Debug.info(this+": drained "+num+" tasks") - drainedTasks = list - terminating = true - throw new QuitControl - } - } - } - } catch { - case _: QuitControl => - Debug.info(this+": initiating shutdown...") - while (!pool.isQuiescent()) { - try { - Thread.sleep(10) - } catch { - case ignore: InterruptedException => - } - } - pool.shutdown() - // allow thread to exit - } - } - - // TODO: when do we pass a task that is not a RecursiveAction? - def execute(task: Runnable) { - pool.execute(task) - } - - override def executeFromActor(task: Runnable) { - // in fair mode: 2% chance of submitting to global task queue - if (fair && random.synchronized { random.nextInt(50) == 1 }) - pool.execute(task) - else - task.asInstanceOf[RecursiveAction].fork() - } - - /** Submits a closure for execution. - * - * @param fun the closure to be executed - */ - def execute(fun: => Unit): Unit = - execute(new Runnable { - def run() { fun } - }) - - /** Shuts down the scheduler. - */ - def shutdown(): Unit = synchronized { - terminating = true - } - - def isActive = synchronized { - !terminating && (pool ne null) && !pool.isShutdown() - } - - override def managedBlock(blocker: scala.concurrent.ManagedBlocker) { - ForkJoinPool.managedBlock(new ForkJoinPool.ManagedBlocker { - def block = blocker.block() - def isReleasable() = blocker.isReleasable - }) - } - - /** Suspends the scheduler. All threads that were in use by the - * scheduler and its internal thread pool are terminated. - */ - def snapshot() = synchronized { - snapshoting = true - } - - /** Resumes the execution of the scheduler if it was previously - * suspended using ForkJoinScheduler.snapshot. - */ - def restart() { - synchronized { - if (!snapshoting) - sys.error("snapshot has not been invoked") - else if (isActive) - sys.error("scheduler is still active") - else - snapshoting = false - - pool = makeNewPool() - } - val iter = drainedTasks.iterator() - while (iter.hasNext()) { - pool.execute(iter.next()) - } - start() - } - -} diff --git a/src/actors/scala/actors/scheduler/QuitControl.scala b/src/actors/scala/actors/scheduler/QuitControl.scala deleted file mode 100644 index b3e288aaff..0000000000 --- a/src/actors/scala/actors/scheduler/QuitControl.scala +++ /dev/null @@ -1,19 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.actors.scheduler - -import scala.util.control.ControlThrowable - -/** - * The `QuitControl` class is used to manage control flow of certain - * schedulers. - * - * @author Philipp Haller - */ -private[scheduler] class QuitControl extends ControlThrowable diff --git a/src/actors/scala/actors/scheduler/ResizableThreadPoolScheduler.scala b/src/actors/scala/actors/scheduler/ResizableThreadPoolScheduler.scala deleted file mode 100644 index 342579db6c..0000000000 --- a/src/actors/scala/actors/scheduler/ResizableThreadPoolScheduler.scala +++ /dev/null @@ -1,197 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.actors.scheduler - -import scala.actors.threadpool.{ThreadPoolExecutor, TimeUnit, LinkedBlockingQueue, - ThreadFactory} -import scala.actors.{Debug, IScheduler} -import scala.concurrent.ManagedBlocker - -/** - * This scheduler class uses a `ThreadPoolExecutor` to execute `Actor`s. - * - * The scheduler attempts to shut down itself and the underlying - * `ThreadPoolExecutor` only if `terminate` is set to true. Otherwise, - * the scheduler must be shut down explicitly. - * - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -class ResizableThreadPoolScheduler(protected val terminate: Boolean, - protected val daemon: Boolean) - extends Thread with IScheduler with TerminationMonitor { - - setDaemon(daemon) - - // guarded by this - private var terminating = false - // guarded by this - private var suspending = false - - // this has to be a java.util.Collection, since this is what - // the ForkJoinPool returns. - @volatile - private var drainedTasks: java.util.List[_] = null - - // guarded by this - private var coreSize = ThreadPoolConfig.corePoolSize - private val maxSize = ThreadPoolConfig.maxPoolSize - private val numCores = Runtime.getRuntime().availableProcessors() - - protected val CHECK_FREQ = 10 - - private class DaemonThreadFactory extends ThreadFactory { - def newThread(r: Runnable): Thread = { - val t = new Thread(r) - t.setDaemon(daemon) - t - } - } - private val threadFac = new DaemonThreadFactory - - private def makeNewPool(): ThreadPoolExecutor = { - val workQueue = new LinkedBlockingQueue - new ThreadPoolExecutor(coreSize, - maxSize, - 60000L, - TimeUnit.MILLISECONDS, - workQueue, - threadFac, - new ThreadPoolExecutor.CallerRunsPolicy) - } - - // guarded by this - private var executor = makeNewPool() - - Debug.info(this+": corePoolSize = "+coreSize+", maxPoolSize = "+maxSize) - - def this(d: Boolean) { - this(true, d) - } - - def this() { - this(false) - } - - private def numWorkersBlocked = { - executor.mainLock.lock() - val iter = executor.workers.iterator() - var numBlocked = 0 - while (iter.hasNext()) { - val w = iter.next().asInstanceOf[ThreadPoolExecutor#Worker] - if (w.tryLock()) { - // worker is idle - w.unlock() - } else { - val s = w.thread.getState() - if (s == Thread.State.WAITING || s == Thread.State.TIMED_WAITING) - numBlocked += 1 - } - } - executor.mainLock.unlock() - numBlocked - } - - override def run() { - try { - while (true) { - this.synchronized { - try { - wait(CHECK_FREQ.toLong) - } catch { - case _: InterruptedException => - } - - if (terminating) - throw new QuitControl - - if (!suspending) { - gc() - - // check if we need more worker threads - val activeBlocked = numWorkersBlocked - if (coreSize - activeBlocked < numCores && coreSize < maxSize) { - coreSize = numCores + activeBlocked - executor.setCorePoolSize(coreSize) - } else if (terminate && allActorsTerminated) { - // if all worker threads idle terminate - if (executor.getActiveCount() == 0) { - Debug.info(this+": initiating shutdown...") - Debug.info(this+": corePoolSize = "+coreSize+", maxPoolSize = "+maxSize) - - terminating = true - throw new QuitControl - } - } - } else { - drainedTasks = executor.shutdownNow() - Debug.info(this+": drained "+drainedTasks.size()+" tasks") - terminating = true - throw new QuitControl - } - } // sync - } - } catch { - case _: QuitControl => - executor.shutdown() - // allow thread to exit - } - } - - def execute(task: Runnable): Unit = - executor execute task - - def execute(fun: => Unit): Unit = - executor.execute(new Runnable { - def run() { fun } - }) - - /** Shuts down the scheduler. - */ - def shutdown(): Unit = synchronized { - terminating = true - } - - def isActive = synchronized { - !terminating && (executor ne null) && !executor.isShutdown() - } - - def managedBlock(blocker: ManagedBlocker) { - blocker.block() - } - - /** Suspends the scheduler. All threads that were in use by the - * scheduler and its internal thread pool are terminated. - */ - def snapshot() = synchronized { - suspending = true - } - - /** Resumes the execution of the scheduler if it was previously - * suspended using `snapshot`. - */ - def restart() { - synchronized { - if (!suspending) - sys.error("snapshot has not been invoked") - else if (isActive) - sys.error("scheduler is still active") - else - suspending = false - - executor = makeNewPool() - } - val iter = drainedTasks.iterator() - while (iter.hasNext()) { - executor.execute(iter.next().asInstanceOf[Runnable]) - } - start() - } - -} diff --git a/src/actors/scala/actors/scheduler/SingleThreadedScheduler.scala b/src/actors/scala/actors/scheduler/SingleThreadedScheduler.scala deleted file mode 100644 index 03b235fe74..0000000000 --- a/src/actors/scala/actors/scheduler/SingleThreadedScheduler.scala +++ /dev/null @@ -1,69 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors -package scheduler - -import scala.collection.mutable - -/** - * This scheduler executes actor tasks on the current thread. - * - * @author Philipp Haller - */ -@deprecated("Use the akka.actor package instead. For migration from the scala.actors package refer to the Actors Migration Guide.", "2.11.0") -class SingleThreadedScheduler extends IScheduler { - - private val tasks = new mutable.Queue[Runnable] - - /** The maximum number of nested tasks that are run - * without unwinding the call stack. - */ - protected val maxNesting = 10 - - private var curNest = 0 - private var isShutdown = false - - def execute(task: Runnable) { - if (curNest < maxNesting) { - curNest += 1 - task.run() - } else { - curNest = 0 - tasks += task - } - } - - def execute(fun: => Unit): Unit = - execute(new Runnable { - def run() { fun } - }) - - def shutdown() { - isShutdown = false - while (!tasks.isEmpty) { - val task = tasks.dequeue() - task.run() - } - isShutdown = true - } - - def newActor(actor: TrackedReactor) {} - def terminated(actor: TrackedReactor) {} - - // TODO: run termination handlers at end of shutdown. - def onTerminate(actor: TrackedReactor)(f: => Unit) {} - - def isActive = - !isShutdown - - def managedBlock(blocker: scala.concurrent.ManagedBlocker) { - blocker.block() - } -} diff --git a/src/actors/scala/actors/scheduler/TerminationMonitor.scala b/src/actors/scala/actors/scheduler/TerminationMonitor.scala deleted file mode 100644 index 9f26ca8d69..0000000000 --- a/src/actors/scala/actors/scheduler/TerminationMonitor.scala +++ /dev/null @@ -1,69 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.actors -package scheduler - -import scala.collection.mutable - -private[scheduler] trait TerminationMonitor { - _: IScheduler => - - protected var activeActors = 0 - protected val terminationHandlers = new mutable.HashMap[TrackedReactor, () => Unit] - private var started = false - - /** newActor is invoked whenever a new actor is started. */ - def newActor(a: TrackedReactor) = synchronized { - activeActors += 1 - if (!started) - started = true - } - - /** Registers a closure to be executed when the specified - * actor terminates. - * - * @param a the actor - * @param f the closure to be registered - */ - def onTerminate(a: TrackedReactor)(f: => Unit): Unit = synchronized { - terminationHandlers += (a -> (() => f)) - } - - /** Registers that the specified actor has terminated. - * - * @param a the actor that has terminated - */ - def terminated(a: TrackedReactor) = { - // obtain termination handler (if any) - val todo = synchronized { - terminationHandlers.get(a) match { - case Some(handler) => - terminationHandlers -= a - handler - case None => - () => { /* do nothing */ } - } - } - - // invoke termination handler (if any) - todo() - - synchronized { - activeActors -= 1 - } - } - - /** Checks whether all actors have terminated. */ - private[actors] def allActorsTerminated: Boolean = synchronized { - started && activeActors <= 0 - } - - /** Checks for actors that have become garbage. */ - protected def gc() {} -} diff --git a/src/actors/scala/actors/scheduler/TerminationService.scala b/src/actors/scala/actors/scheduler/TerminationService.scala deleted file mode 100644 index ed1805ee1e..0000000000 --- a/src/actors/scala/actors/scheduler/TerminationService.scala +++ /dev/null @@ -1,68 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors -package scheduler - -import java.lang.{Thread, InterruptedException} - -/** - * The TerminationService class starts a new thread - * that is used to check regularly if the scheduler can be - * shut down, because all started actors are known to - * have terminated. - * - * @author Philipp Haller - */ -private[scheduler] trait TerminationService extends TerminationMonitor { - _: Thread with IScheduler => - - private var terminating = false - - /** Indicates whether the scheduler should terminate when all - * actors have terminated. - */ - protected val terminate = true - - protected val CHECK_FREQ = 50 - - def onShutdown(): Unit - - override def run() { - try { - while (true) { - this.synchronized { - try { - wait(CHECK_FREQ.toLong) - } catch { - case _: InterruptedException => - } - - if (terminating || (terminate && allActorsTerminated)) - throw new QuitControl - - gc() - } - } - } catch { - case _: QuitControl => - Debug.info(this+": initiating shutdown...") - // invoke shutdown hook - onShutdown() - // allow thread to exit - } - } - - /** Shuts down the scheduler. - */ - def shutdown(): Unit = synchronized { - terminating = true - } - -} diff --git a/src/actors/scala/actors/scheduler/ThreadPoolConfig.scala b/src/actors/scala/actors/scheduler/ThreadPoolConfig.scala deleted file mode 100644 index bfd4e7ac40..0000000000 --- a/src/actors/scala/actors/scheduler/ThreadPoolConfig.scala +++ /dev/null @@ -1,50 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.actors -package scheduler - -import scala.util.Properties.{ javaVersion, javaVmVendor, isJavaAtLeast, propIsSetTo, propOrNone } - -/** - * @author Erik Engbrecht - * @author Philipp Haller - */ -private[actors] object ThreadPoolConfig { - private val rt = Runtime.getRuntime() - private val minNumThreads = 4 - - private def getIntegerProp(propName: String): Option[Int] = - try propOrNone(propName) map (_.toInt) - catch { case _: SecurityException | _: NumberFormatException => None } - - val corePoolSize = getIntegerProp("actors.corePoolSize") match { - case Some(i) if i > 0 => i - case _ => { - val byCores = rt.availableProcessors() * 2 - if (byCores > minNumThreads) byCores else minNumThreads - } - } - - val maxPoolSize = { - val preMaxSize = getIntegerProp("actors.maxPoolSize") getOrElse 256 - if (preMaxSize >= corePoolSize) preMaxSize else corePoolSize - } - - private[actors] def useForkJoin: Boolean = - try !propIsSetTo("actors.enableForkJoin", "false") && - (propIsSetTo("actors.enableForkJoin", "true") || { - Debug.info(this+": java.version = "+javaVersion) - Debug.info(this+": java.vm.vendor = "+javaVmVendor) - isJavaAtLeast("1.6") - }) - catch { - case _: SecurityException => false - } -} diff --git a/src/actors/scala/actors/threadpool/AbstractCollection.java b/src/actors/scala/actors/threadpool/AbstractCollection.java deleted file mode 100644 index 195a0064ab..0000000000 --- a/src/actors/scala/actors/threadpool/AbstractCollection.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Written by Dawid Kurzyniec, based on public domain code written by Doug Lea - * and publicly available documentation, and released to the public domain, as - * explained at http://creativecommons.org/licenses/publicdomain - */ - -package scala.actors.threadpool; -import scala.actors.threadpool.helpers.Utils; - -/** - * Overrides toArray() and toArray(Object[]) in AbstractCollection to provide - * implementations valid for concurrent collections. - * - * @author Doug Lea - * @author Dawid Kurzyniec - */ -public abstract class AbstractCollection extends java.util.AbstractCollection { - - /** - * Sole constructor. (For invocation by subclass constructors, typically - * implicit.) - */ - protected AbstractCollection() { super(); } - - public Object[] toArray() { - return Utils.collectionToArray(this); - } - - public Object[] toArray(Object[] a) { - return Utils.collectionToArray(this, a); - } -} diff --git a/src/actors/scala/actors/threadpool/AbstractExecutorService.java b/src/actors/scala/actors/threadpool/AbstractExecutorService.java deleted file mode 100644 index 4a12aa3c28..0000000000 --- a/src/actors/scala/actors/threadpool/AbstractExecutorService.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -import scala.actors.threadpool.helpers.*; -import java.util.Collection; -import java.util.ArrayList; -import java.util.List; -import java.util.Iterator; - -/** - * Provides default implementations of {@link ExecutorService} - * execution methods. This class implements the submit, - * invokeAny and invokeAll methods using a - * {@link RunnableFuture} returned by newTaskFor, which defaults - * to the {@link FutureTask} class provided in this package. For example, - * the implementation of submit(Runnable) creates an - * associated RunnableFuture that is executed and - * returned. Subclasses may override the newTaskFor methods - * to return RunnableFuture implementations other than - * FutureTask. - * - *

Extension example. Here is a sketch of a class - * that customizes {@link ThreadPoolExecutor} to use - * a CustomTask class instead of the default FutureTask: - *

- * public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
- *
- *   static class CustomTask<V> implements RunnableFuture<V> {...}
- *
- *   protected <V> RunnableFuture<V> newTaskFor(Callable<V> c) {
- *       return new CustomTask<V>(c);
- *   }
- *   protected <V> RunnableFuture<V> newTaskFor(Runnable r, V v) {
- *       return new CustomTask<V>(r, v);
- *   }
- *   // ... add constructors, etc.
- * }
- * 
- * @since 1.5 - * @author Doug Lea - */ -public abstract class AbstractExecutorService implements ExecutorService { - - /** - * Returns a RunnableFuture for the given runnable and default - * value. - * - * @param runnable the runnable task being wrapped - * @param value the default value for the returned future - * @return a RunnableFuture which when run will run the - * underlying runnable and which, as a Future, will yield - * the given value as its result and provide for cancellation of - * the underlying task. - * @since 1.6 - */ - protected RunnableFuture newTaskFor(Runnable runnable, Object value) { - return new FutureTask(runnable, value); - } - - /** - * Returns a RunnableFuture for the given callable task. - * - * @param callable the callable task being wrapped - * @return a RunnableFuture which when run will call the - * underlying callable and which, as a Future, will yield - * the callable's result as its result and provide for - * cancellation of the underlying task. - * @since 1.6 - */ - protected RunnableFuture newTaskFor(Callable callable) { - return new FutureTask(callable); - } - - /** - * @throws RejectedExecutionException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - */ - public Future submit(Runnable task) { - if (task == null) throw new NullPointerException(); - RunnableFuture ftask = newTaskFor(task, null); - execute(ftask); - return ftask; - } - - /** - * @throws RejectedExecutionException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - */ - public Future submit(Runnable task, Object result) { - if (task == null) throw new NullPointerException(); - RunnableFuture ftask = newTaskFor(task, result); - execute(ftask); - return ftask; - } - - /** - * @throws RejectedExecutionException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - */ - public Future submit(Callable task) { - if (task == null) throw new NullPointerException(); - RunnableFuture ftask = newTaskFor(task); - execute(ftask); - return ftask; - } - - /** - * the main mechanics of invokeAny. - */ - private Object doInvokeAny(Collection tasks, - boolean timed, long nanos) - throws InterruptedException, ExecutionException, TimeoutException { - if (tasks == null) - throw new NullPointerException(); - int ntasks = tasks.size(); - if (ntasks == 0) - throw new IllegalArgumentException(); - List futures = new ArrayList(ntasks); - ExecutorCompletionService ecs = - new ExecutorCompletionService(this); - - // For efficiency, especially in executors with limited - // parallelism, check to see if previously submitted tasks are - // done before submitting more of them. This interleaving - // plus the exception mechanics account for messiness of main - // loop. - - try { - // Record exceptions so that if we fail to obtain any - // result, we can throw the last exception we got. - ExecutionException ee = null; - long lastTime = (timed)? Utils.nanoTime() : 0; - Iterator it = tasks.iterator(); - - // Start one task for sure; the rest incrementally - futures.add(ecs.submit((Callable)it.next())); - --ntasks; - int active = 1; - - for (;;) { - Future f = ecs.poll(); - if (f == null) { - if (ntasks > 0) { - --ntasks; - futures.add(ecs.submit((Callable)it.next())); - ++active; - } - else if (active == 0) - break; - else if (timed) { - f = ecs.poll(nanos, TimeUnit.NANOSECONDS); - if (f == null) - throw new TimeoutException(); - long now = Utils.nanoTime(); - nanos -= now - lastTime; - lastTime = now; - } - else - f = ecs.take(); - } - if (f != null) { - --active; - try { - return f.get(); - } catch (InterruptedException ie) { - throw ie; - } catch (ExecutionException eex) { - ee = eex; - } catch (RuntimeException rex) { - ee = new ExecutionException(rex); - } - } - } - - if (ee == null) - ee = new ExecutionException(); - throw ee; - - } finally { - for (Iterator f = futures.iterator(); f.hasNext();) - ((Future)f.next()).cancel(true); - } - } - - public Object invokeAny(Collection tasks) - throws InterruptedException, ExecutionException { - try { - return doInvokeAny(tasks, false, 0); - } catch (TimeoutException cannotHappen) { - assert false; - return null; - } - } - - public Object invokeAny(Collection tasks, - long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - return doInvokeAny(tasks, true, unit.toNanos(timeout)); - } - - public List invokeAll(Collection tasks) throws InterruptedException { - if (tasks == null) - throw new NullPointerException(); - List futures = new ArrayList(tasks.size()); - boolean done = false; - try { - for (Iterator t = tasks.iterator(); t.hasNext();) { - RunnableFuture f = newTaskFor((Callable)t.next()); - futures.add(f); - execute(f); - } - for (Iterator i = futures.iterator(); i.hasNext();) { - Future f = (Future) i.next(); - if (!f.isDone()) { - try { - f.get(); - } catch (CancellationException ignore) { - } catch (ExecutionException ignore) { - } - } - } - done = true; - return futures; - } finally { - if (!done) - for (Iterator i = futures.iterator(); i.hasNext();) { - Future f = (Future) i.next(); - f.cancel(true); - } - } - } - - public List invokeAll(Collection tasks, - long timeout, TimeUnit unit) - throws InterruptedException { - if (tasks == null || unit == null) - throw new NullPointerException(); - long nanos = unit.toNanos(timeout); - List futures = new ArrayList(tasks.size()); - boolean done = false; - try { - for (Iterator t = tasks.iterator(); t.hasNext();) - futures.add(newTaskFor((Callable)t.next())); - - long lastTime = Utils.nanoTime(); - - // Interleave time checks and calls to execute in case - // executor doesn't have any/much parallelism. - Iterator it = futures.iterator(); - while (it.hasNext()) { - execute((Runnable)(it.next())); - long now = Utils.nanoTime(); - nanos -= (now - lastTime); - lastTime = now; - if (nanos <= 0) - return futures; - } - - for (Iterator i = futures.iterator(); i.hasNext();) { - Future f = (Future)i.next(); - if (!f.isDone()) { - if (nanos <= 0) - return futures; - try { - f.get(nanos, TimeUnit.NANOSECONDS); - } catch (CancellationException ignore) { - } catch (ExecutionException ignore) { - } catch (TimeoutException toe) { - return futures; - } - long now = Utils.nanoTime(); - nanos -= now - lastTime; - lastTime = now; - } - } - done = true; - return futures; - } finally { - if (!done) - for (Iterator i = futures.iterator(); i.hasNext();) { - Future f = (Future) i.next(); - f.cancel(true); - } - } - } - -} diff --git a/src/actors/scala/actors/threadpool/AbstractQueue.java b/src/actors/scala/actors/threadpool/AbstractQueue.java deleted file mode 100644 index 84ddc136bc..0000000000 --- a/src/actors/scala/actors/threadpool/AbstractQueue.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -import java.util.Iterator; -import java.util.Collection; -import java.util.NoSuchElementException; - -/** - * This class provides skeletal implementations of some {@link Queue} - * operations. The implementations in this class are appropriate when - * the base implementation does not allow null - * elements. Methods {@link #add add}, {@link #remove remove}, and - * {@link #element element} are based on {@link #offer offer}, {@link - * #poll poll}, and {@link #peek peek}, respectively but throw - * exceptions instead of indicating failure via false or - * null returns. - * - *

A Queue implementation that extends this class must - * minimally define a method {@link Queue#offer} which does not permit - * insertion of null elements, along with methods {@link - * Queue#peek}, {@link Queue#poll}, {@link Collection#size}, and a - * {@link Collection#iterator} supporting {@link - * Iterator#remove}. Typically, additional methods will be overridden - * as well. If these requirements cannot be met, consider instead - * subclassing {@link AbstractCollection}. - * - *

This class is a member of the - * - * Java Collections Framework. - * - * @since 1.5 - * @author Doug Lea - */ -public abstract class AbstractQueue - extends AbstractCollection - implements Queue { - - /** - * Constructor for use by subclasses. - */ - protected AbstractQueue() { - } - - /** - * Inserts the specified element into this queue if it is possible to do so - * immediately without violating capacity restrictions, returning - * true upon success and throwing an IllegalStateException - * if no space is currently available. - * - *

This implementation returns true if offer succeeds, - * else throws an IllegalStateException. - * - * @param e the element to add - * @return true (as specified by {@link Collection#add}) - * @throws IllegalStateException if the element cannot be added at this - * time due to capacity restrictions - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this queue - * @throws NullPointerException if the specified element is null and - * this queue does not permit null elements - * @throws IllegalArgumentException if some property of this element - * prevents it from being added to this queue - */ - public boolean add(Object e) { - if (offer(e)) - return true; - else - throw new IllegalStateException("Queue full"); - } - - /** - * Retrieves and removes the head of this queue. This method differs - * from {@link #poll poll} only in that it throws an exception if this - * queue is empty. - * - *

This implementation returns the result of poll - * unless the queue is empty. - * - * @return the head of this queue - * @throws NoSuchElementException if this queue is empty - */ - public Object remove() { - Object x = poll(); - if (x != null) - return x; - else - throw new NoSuchElementException(); - } - - - /** - * Retrieves, but does not remove, the head of this queue. This method - * differs from {@link #peek peek} only in that it throws an exception if - * this queue is empty. - * - *

This implementation returns the result of peek - * unless the queue is empty. - * - * @return the head of this queue - * @throws NoSuchElementException if this queue is empty - */ - public Object element() { - Object x = peek(); - if (x != null) - return x; - else - throw new NoSuchElementException(); - } - - /** - * Removes all of the elements from this queue. - * The queue will be empty after this call returns. - * - *

This implementation repeatedly invokes {@link #poll poll} until it - * returns null. - */ - public void clear() { - while (poll() != null) - ; - } - - /** - * Adds all of the elements in the specified collection to this - * queue. Attempts to addAll of a queue to itself result in - * IllegalArgumentException. Further, the behavior of - * this operation is undefined if the specified collection is - * modified while the operation is in progress. - * - *

This implementation iterates over the specified collection, - * and adds each element returned by the iterator to this - * queue, in turn. A runtime exception encountered while - * trying to add an element (including, in particular, a - * null element) may result in only some of the elements - * having been successfully added when the associated exception is - * thrown. - * - * @param c collection containing elements to be added to this queue - * @return true if this queue changed as a result of the call - * @throws ClassCastException if the class of an element of the specified - * collection prevents it from being added to this queue - * @throws NullPointerException if the specified collection contains a - * null element and this queue does not permit null elements, - * or if the specified collection is null - * @throws IllegalArgumentException if some property of an element of the - * specified collection prevents it from being added to this - * queue, or if the specified collection is this queue - * @throws IllegalStateException if not all the elements can be added at - * this time due to insertion restrictions - * @see #add(Object) - */ - public boolean addAll(Collection c) { - if (c == null) - throw new NullPointerException(); - if (c == this) - throw new IllegalArgumentException(); - boolean modified = false; - Iterator e = c.iterator(); - while (e.hasNext()) { - if (add(e.next())) - modified = true; - } - return modified; - } - -} diff --git a/src/actors/scala/actors/threadpool/Arrays.java b/src/actors/scala/actors/threadpool/Arrays.java deleted file mode 100644 index 85e7c8fa00..0000000000 --- a/src/actors/scala/actors/threadpool/Arrays.java +++ /dev/null @@ -1,811 +0,0 @@ -/* - * Written by Dawid Kurzyniec, based on code written by Doug Lea with assistance - * from members of JCP JSR-166 Expert Group. Released to the public domain, - * as explained at http://creativecommons.org/licenses/publicdomain. - */ - -package scala.actors.threadpool; - -import java.lang.reflect.Array; -import java.util.List; -import java.util.ArrayList; -import java.util.Comparator; - -public class Arrays { - - private Arrays() {} - - public static void sort(long[] a) { - java.util.Arrays.sort(a); - } - - public static void sort(long[] a, int fromIndex, int toIndex) { - java.util.Arrays.sort(a, fromIndex, toIndex); - } - - public static void sort(int[] a) { - java.util.Arrays.sort(a); - } - - public static void sort(int[] a, int fromIndex, int toIndex) { - java.util.Arrays.sort(a, fromIndex, toIndex); - } - - public static void sort(short[] a) { - java.util.Arrays.sort(a); - } - - public static void sort(short[] a, int fromIndex, int toIndex) { - java.util.Arrays.sort(a, fromIndex, toIndex); - } - - public static void sort(char[] a) { - java.util.Arrays.sort(a); - } - - public static void sort(char[] a, int fromIndex, int toIndex) { - java.util.Arrays.sort(a, fromIndex, toIndex); - } - - public static void sort(byte[] a) { - java.util.Arrays.sort(a); - } - - public static void sort(byte[] a, int fromIndex, int toIndex) { - java.util.Arrays.sort(a, fromIndex, toIndex); - } - - public static void sort(double[] a) { - java.util.Arrays.sort(a); - } - - public static void sort(double[] a, int fromIndex, int toIndex) { - java.util.Arrays.sort(a, fromIndex, toIndex); - } - - public static void sort(float[] a) { - java.util.Arrays.sort(a); - } - - public static void sort(float[] a, int fromIndex, int toIndex) { - java.util.Arrays.sort(a, fromIndex, toIndex); - } - - - public static void sort(Object[] a) { - java.util.Arrays.sort(a); - } - - public static void sort(Object[] a, int fromIndex, int toIndex) { - java.util.Arrays.sort(a, fromIndex, toIndex); - } - - public static void sort(Object[] a, Comparator c) { - java.util.Arrays.sort(a, c); - } - - public static void sort(Object[] a, int fromIndex, int toIndex, Comparator c) { - java.util.Arrays.sort(a, fromIndex, toIndex, c); - } - - - // Searching - - public static int binarySearch(long[] a, long key) { - return java.util.Arrays.binarySearch(a, key); - } - - public static int binarySearch(int[] a, int key) { - return java.util.Arrays.binarySearch(a, key); - } - - public static int binarySearch(short[] a, short key) { - return java.util.Arrays.binarySearch(a, key); - } - - public static int binarySearch(char[] a, char key) { - return java.util.Arrays.binarySearch(a, key); - } - - public static int binarySearch(byte[] a, byte key) { - return java.util.Arrays.binarySearch(a, key); - } - - public static int binarySearch(double[] a, double key) { - return java.util.Arrays.binarySearch(a, key); - } - - public static int binarySearch(float[] a, float key) { - return java.util.Arrays.binarySearch(a, key); - } - - public static int binarySearch(Object[] a, Object key) { - return java.util.Arrays.binarySearch(a, key); - } - - public static int binarySearch(Object[] a, Object key, Comparator c) { - return java.util.Arrays.binarySearch(a, key, c); - } - - - // Equality Testing - - public static boolean equals(long[] a, long[] a2) { - return java.util.Arrays.equals(a, a2); - } - - public static boolean equals(int[] a, int[] a2) { - return java.util.Arrays.equals(a, a2); - } - - public static boolean equals(short[] a, short a2[]) { - return java.util.Arrays.equals(a, a2); - } - - public static boolean equals(char[] a, char[] a2) { - return java.util.Arrays.equals(a, a2); - } - - public static boolean equals(byte[] a, byte[] a2) { - return java.util.Arrays.equals(a, a2); - } - - public static boolean equals(boolean[] a, boolean[] a2) { - return java.util.Arrays.equals(a, a2); - } - - public static boolean equals(double[] a, double[] a2) { - return java.util.Arrays.equals(a, a2); - } - - public static boolean equals(float[] a, float[] a2) { - return java.util.Arrays.equals(a, a2); - } - - public static boolean equals(Object[] a, Object[] a2) { - return java.util.Arrays.equals(a, a2); - } - - - // Filling - - public static void fill(long[] a, long val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(long[] a, int fromIndex, int toIndex, long val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - public static void fill(int[] a, int val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(int[] a, int fromIndex, int toIndex, int val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - public static void fill(short[] a, short val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(short[] a, int fromIndex, int toIndex, short val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - public static void fill(char[] a, char val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(char[] a, int fromIndex, int toIndex, char val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - public static void fill(byte[] a, byte val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(byte[] a, int fromIndex, int toIndex, byte val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - public static void fill(boolean[] a, boolean val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(boolean[] a, int fromIndex, int toIndex, - boolean val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - public static void fill(double[] a, double val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(double[] a, int fromIndex, int toIndex,double val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - public static void fill(float[] a, float val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(float[] a, int fromIndex, int toIndex, float val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - public static void fill(Object[] a, Object val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(Object[] a, int fromIndex, int toIndex, Object val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - - // Cloning - - /** - * @since 1.6 - */ - public static Object[] copyOf(Object[] original, int newLength) { - return copyOf(original, newLength, original.getClass()); - } - - /** - * @since 1.6 - */ - public static Object[] copyOf(Object[] original, int newLength, Class newType) { - Object[] arr = (newType == Object[].class) ? new Object[newLength] : - (Object[])Array.newInstance(newType.getComponentType(), newLength); - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static byte[] copyOf(byte[] original, int newLength) { - byte[] arr = new byte[newLength]; - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static short[] copyOf(short[] original, int newLength) { - short[] arr = new short[newLength]; - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static int[] copyOf(int[] original, int newLength) { - int[] arr = new int[newLength]; - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static long[] copyOf(long[] original, int newLength) { - long[] arr = new long[newLength]; - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static char[] copyOf(char[] original, int newLength) { - char[] arr = new char[newLength]; - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static float[] copyOf(float[] original, int newLength) { - float[] arr = new float[newLength]; - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static double[] copyOf(double[] original, int newLength) { - double[] arr = new double[newLength]; - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static boolean[] copyOf(boolean[] original, int newLength) { - boolean[] arr = new boolean[newLength]; - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static Object[] copyOfRange(Object[] original, int from, int to) { - return copyOfRange(original, from, to, original.getClass()); - } - - /** - * @since 1.6 - */ - public static Object[] copyOfRange(Object[] original, int from, int to, Class newType) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - Object[] arr = (newType == Object[].class) ? new Object[newLength] : - (Object[])Array.newInstance(newType.getComponentType(), newLength); - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static byte[] copyOfRange(byte[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - byte[] arr = new byte[newLength]; - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static short[] copyOfRange(short[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - short[] arr = new short[newLength]; - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static int[] copyOfRange(int[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - int[] arr = new int[newLength]; - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static long[] copyOfRange(long[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - long[] arr = new long[newLength]; - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static char[] copyOfRange(char[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - char[] arr = new char[newLength]; - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static float[] copyOfRange(float[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - float[] arr = new float[newLength]; - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static double[] copyOfRange(double[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - double[] arr = new double[newLength]; - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static boolean[] copyOfRange(boolean[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - boolean[] arr = new boolean[newLength]; - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - - public static List asList(Object[] a) { - return java.util.Arrays.asList(a); - } - - /** - * @since 1.5 - */ - public static int hashCode(long a[]) { - if (a == null) return 0; - int hash = 1; - for (int i=0; i>> 32)); - } - return hash; - } - - /** - * @since 1.5 - */ - public static int hashCode(int a[]) { - if (a == null) return 0; - int hash = 1; - for (int i=0; i>> 32)); - } - return hash; - } - - /** - * @since 1.5 - */ - public static int hashCode(Object a[]) { - if (a == null) return 0; - int hash = 1; - for (int i=0; i0) buf.append(", "); - Object e = a[i]; - if (e == null) { - buf.append("null"); - } - else if (!e.getClass().isArray()) { - buf.append(e.toString()); - } - else if (e instanceof Object[]) { - if (seen.contains(e)) buf.append("[...]"); - else deepToString((Object[])e, buf, seen); - } - else { - // primitive arr - buf.append( - (e instanceof byte[]) ? toString( (byte[]) e) : - (e instanceof short[]) ? toString( (short[]) e) : - (e instanceof int[]) ? toString( (int[]) e) : - (e instanceof long[]) ? toString( (long[]) e) : - (e instanceof char[]) ? toString( (char[]) e) : - (e instanceof boolean[]) ? toString( (boolean[]) e) : - (e instanceof float[]) ? toString( (float[]) e) : - (e instanceof double[]) ? toString( (double[]) e) : ""); - } - } - buf.append(']'); - seen.remove(seen.size()-1); - } -} diff --git a/src/actors/scala/actors/threadpool/AtomicInteger.java b/src/actors/scala/actors/threadpool/AtomicInteger.java deleted file mode 100644 index eedb84512a..0000000000 --- a/src/actors/scala/actors/threadpool/AtomicInteger.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -/** - * An {@code int} value that may be updated atomically. See the - * {@link edu.emory.mathcs.backport.java.util.concurrent.atomic} package specification for - * description of the properties of atomic variables. An - * {@code AtomicInteger} is used in applications such as atomically - * incremented counters, and cannot be used as a replacement for an - * {@link java.lang.Integer}. However, this class does extend - * {@code Number} to allow uniform access by tools and utilities that - * deal with numerically-based classes. - * - * @since 1.5 - * @author Doug Lea -*/ -public class AtomicInteger extends Number implements java.io.Serializable { - private static final long serialVersionUID = 6214790243416807050L; - - private volatile int value; - - /** - * Creates a new AtomicInteger with the given initial value. - * - * @param initialValue the initial value - */ - public AtomicInteger(int initialValue) { - value = initialValue; - } - - /** - * Creates a new AtomicInteger with initial value {@code 0}. - */ - public AtomicInteger() { - } - - /** - * Gets the current value. - * - * @return the current value - */ - public final int get() { - return value; - } - - /** - * Sets to the given value. - * - * @param newValue the new value - */ - public final synchronized void set(int newValue) { - value = newValue; - } - - /** - * Eventually sets to the given value. - * - * @param newValue the new value - * @since 1.6 - */ - public final synchronized void lazySet(int newValue) { - value = newValue; - } - - /** - * Atomically sets to the given value and returns the old value. - * - * @param newValue the new value - * @return the previous value - */ - public final synchronized int getAndSet(int newValue) { - int old = value; - value = newValue; - return old; - } - - /** - * Atomically sets the value to the given updated value - * if the current value {@code ==} the expected value. - * - * @param expect the expected value - * @param update the new value - * @return true if successful. False return indicates that - * the actual value was not equal to the expected value. - */ - public final synchronized boolean compareAndSet(int expect, int update) { - if (value == expect) { - value = update; - return true; - } - else { - return false; - } - } - - /** - * Atomically sets the value to the given updated value - * if the current value {@code ==} the expected value. - * - *

May fail spuriously - * and does not provide ordering guarantees, so is only rarely an - * appropriate alternative to {@code compareAndSet}. - * - * @param expect the expected value - * @param update the new value - * @return true if successful. - */ - public final synchronized boolean weakCompareAndSet(int expect, int update) { - if (value == expect) { - value = update; - return true; - } - else { - return false; - } - } - - - /** - * Atomically increments by one the current value. - * - * @return the previous value - */ - public final synchronized int getAndIncrement() { - return value++; - } - - - /** - * Atomically decrements by one the current value. - * - * @return the previous value - */ - public final synchronized int getAndDecrement() { - return value--; - } - - - /** - * Atomically adds the given value to the current value. - * - * @param delta the value to add - * @return the previous value - */ - public final synchronized int getAndAdd(int delta) { - int old = value; - value += delta; - return old; - } - - /** - * Atomically increments by one the current value. - * - * @return the updated value - */ - public final synchronized int incrementAndGet() { - return ++value; - } - - /** - * Atomically decrements by one the current value. - * - * @return the updated value - */ - public final synchronized int decrementAndGet() { - return --value; - } - - - /** - * Atomically adds the given value to the current value. - * - * @param delta the value to add - * @return the updated value - */ - public final synchronized int addAndGet(int delta) { - return value += delta; - } - - /** - * Returns the String representation of the current value. - * @return the String representation of the current value. - */ - public String toString() { - return Integer.toString(get()); - } - - - public int intValue() { - return get(); - } - - public long longValue() { - return (long)get(); - } - - public float floatValue() { - return (float)get(); - } - - public double doubleValue() { - return (double)get(); - } - -} diff --git a/src/actors/scala/actors/threadpool/BlockingQueue.java b/src/actors/scala/actors/threadpool/BlockingQueue.java deleted file mode 100644 index 4b8c201b85..0000000000 --- a/src/actors/scala/actors/threadpool/BlockingQueue.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -import java.util.Collection; -import java.util.Queue; - -/** - * A {@link java.util.Queue} that additionally supports operations - * that wait for the queue to become non-empty when retrieving an - * element, and wait for space to become available in the queue when - * storing an element. - * - *

BlockingQueue methods come in four forms, with different ways - * of handling operations that cannot be satisfied immediately, but may be - * satisfied at some point in the future: - * one throws an exception, the second returns a special value (either - * null or false, depending on the operation), the third - * blocks the current thread indefinitely until the operation can succeed, - * and the fourth blocks for only a given maximum time limit before giving - * up. These methods are summarized in the following table: - * - *

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Throws exceptionSpecial valueBlocksTimes out
Insert{@link #add add(e)}{@link #offer offer(e)}{@link #put put(e)}{@link #offer(Object, long, TimeUnit) offer(e, time, unit)}
Remove{@link #remove remove()}{@link #poll poll()}{@link #take take()}{@link #poll(long, TimeUnit) poll(time, unit)}
Examine{@link #element element()}{@link #peek peek()}not applicablenot applicable
- * - *

A BlockingQueue does not accept null elements. - * Implementations throw NullPointerException on attempts - * to add, put or offer a null. A - * null is used as a sentinel value to indicate failure of - * poll operations. - * - *

A BlockingQueue may be capacity bounded. At any given - * time it may have a remainingCapacity beyond which no - * additional elements can be put without blocking. - * A BlockingQueue without any intrinsic capacity constraints always - * reports a remaining capacity of Integer.MAX_VALUE. - * - *

BlockingQueue implementations are designed to be used - * primarily for producer-consumer queues, but additionally support - * the {@link java.util.Collection} interface. So, for example, it is - * possible to remove an arbitrary element from a queue using - * remove(x). However, such operations are in general - * not performed very efficiently, and are intended for only - * occasional use, such as when a queued message is cancelled. - * - *

BlockingQueue implementations are thread-safe. All - * queuing methods achieve their effects atomically using internal - * locks or other forms of concurrency control. However, the - * bulk Collection operations addAll, - * containsAll, retainAll and removeAll are - * not necessarily performed atomically unless specified - * otherwise in an implementation. So it is possible, for example, for - * addAll(c) to fail (throwing an exception) after adding - * only some of the elements in c. - * - *

A BlockingQueue does not intrinsically support - * any kind of "close" or "shutdown" operation to - * indicate that no more items will be added. The needs and usage of - * such features tend to be implementation-dependent. For example, a - * common tactic is for producers to insert special - * end-of-stream or poison objects, that are - * interpreted accordingly when taken by consumers. - * - *

- * Usage example, based on a typical producer-consumer scenario. - * Note that a BlockingQueue can safely be used with multiple - * producers and multiple consumers. - *

- * class Producer implements Runnable {
- *   private final BlockingQueue queue;
- *   Producer(BlockingQueue q) { queue = q; }
- *   public void run() {
- *     try {
- *       while (true) { queue.put(produce()); }
- *     } catch (InterruptedException ex) { ... handle ...}
- *   }
- *   Object produce() { ... }
- * }
- *
- * class Consumer implements Runnable {
- *   private final BlockingQueue queue;
- *   Consumer(BlockingQueue q) { queue = q; }
- *   public void run() {
- *     try {
- *       while (true) { consume(queue.take()); }
- *     } catch (InterruptedException ex) { ... handle ...}
- *   }
- *   void consume(Object x) { ... }
- * }
- *
- * class Setup {
- *   void main() {
- *     BlockingQueue q = new SomeQueueImplementation();
- *     Producer p = new Producer(q);
- *     Consumer c1 = new Consumer(q);
- *     Consumer c2 = new Consumer(q);
- *     new Thread(p).start();
- *     new Thread(c1).start();
- *     new Thread(c2).start();
- *   }
- * }
- * 
- * - *

Memory consistency effects: As with other concurrent - * collections, actions in a thread prior to placing an object into a - * {@code BlockingQueue} - * happen-before - * actions subsequent to the access or removal of that element from - * the {@code BlockingQueue} in another thread. - * - *

This interface is a member of the - * - * Java Collections Framework. - * - * @since 1.5 - * @author Doug Lea - * @param the type of elements held in this collection - */ -public interface BlockingQueue extends java.util.Queue { - /** - * Inserts the specified element into this queue if it is possible to do - * so immediately without violating capacity restrictions, returning - * true upon success and throwing an - * IllegalStateException if no space is currently available. - * When using a capacity-restricted queue, it is generally preferable to - * use {@link #offer(Object) offer}. - * - * @param e the element to add - * @return true (as specified by {@link Collection#add}) - * @throws IllegalStateException if the element cannot be added at this - * time due to capacity restrictions - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this queue - * @throws NullPointerException if the specified element is null - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this queue - */ - boolean add(E e); - - /** - * Inserts the specified element into this queue if it is possible to do - * so immediately without violating capacity restrictions, returning - * true upon success and false if no space is currently - * available. When using a capacity-restricted queue, this method is - * generally preferable to {@link #add}, which can fail to insert an - * element only by throwing an exception. - * - * @param e the element to add - * @return true if the element was added to this queue, else - * false - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this queue - * @throws NullPointerException if the specified element is null - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this queue - */ - boolean offer(E e); - - /** - * Inserts the specified element into this queue, waiting if necessary - * for space to become available. - * - * @param e the element to add - * @throws InterruptedException if interrupted while waiting - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this queue - * @throws NullPointerException if the specified element is null - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this queue - */ - void put(E e) throws InterruptedException; - - /** - * Inserts the specified element into this queue, waiting up to the - * specified wait time if necessary for space to become available. - * - * @param e the element to add - * @param timeout how long to wait before giving up, in units of - * unit - * @param unit a TimeUnit determining how to interpret the - * timeout parameter - * @return true if successful, or false if - * the specified waiting time elapses before space is available - * @throws InterruptedException if interrupted while waiting - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this queue - * @throws NullPointerException if the specified element is null - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this queue - */ - boolean offer(E e, long timeout, TimeUnit unit) - throws InterruptedException; - - /** - * Retrieves and removes the head of this queue, waiting if necessary - * until an element becomes available. - * - * @return the head of this queue - * @throws InterruptedException if interrupted while waiting - */ - E take() throws InterruptedException; - - /** - * Retrieves and removes the head of this queue, waiting up to the - * specified wait time if necessary for an element to become available. - * - * @param timeout how long to wait before giving up, in units of - * unit - * @param unit a TimeUnit determining how to interpret the - * timeout parameter - * @return the head of this queue, or null if the - * specified waiting time elapses before an element is available - * @throws InterruptedException if interrupted while waiting - */ - E poll(long timeout, TimeUnit unit) - throws InterruptedException; - - /** - * Returns the number of additional elements that this queue can ideally - * (in the absence of memory or resource constraints) accept without - * blocking, or Integer.MAX_VALUE if there is no intrinsic - * limit. - * - *

Note that you cannot always tell if an attempt to insert - * an element will succeed by inspecting remainingCapacity - * because it may be the case that another thread is about to - * insert or remove an element. - * - * @return the remaining capacity - */ - int remainingCapacity(); - - /** - * Removes a single instance of the specified element from this queue, - * if it is present. More formally, removes an element e such - * that o.equals(e), if this queue contains one or more such - * elements. - * Returns true if this queue contained the specified element - * (or equivalently, if this queue changed as a result of the call). - * - * @param o element to be removed from this queue, if present - * @return true if this queue changed as a result of the call - * @throws ClassCastException if the class of the specified element - * is incompatible with this queue (optional) - * @throws NullPointerException if the specified element is null (optional) - */ - boolean remove(Object o); - - /** - * Returns true if this queue contains the specified element. - * More formally, returns true if and only if this queue contains - * at least one element e such that o.equals(e). - * - * @param o object to be checked for containment in this queue - * @return true if this queue contains the specified element - * @throws ClassCastException if the class of the specified element - * is incompatible with this queue (optional) - * @throws NullPointerException if the specified element is null (optional) - */ - public boolean contains(Object o); - - /** - * Removes all available elements from this queue and adds them - * to the given collection. This operation may be more - * efficient than repeatedly polling this queue. A failure - * encountered while attempting to add elements to - * collection c may result in elements being in neither, - * either or both collections when the associated exception is - * thrown. Attempts to drain a queue to itself result in - * IllegalArgumentException. Further, the behavior of - * this operation is undefined if the specified collection is - * modified while the operation is in progress. - * - * @param c the collection to transfer elements into - * @return the number of elements transferred - * @throws UnsupportedOperationException if addition of elements - * is not supported by the specified collection - * @throws ClassCastException if the class of an element of this queue - * prevents it from being added to the specified collection - * @throws NullPointerException if the specified collection is null - * @throws IllegalArgumentException if the specified collection is this - * queue, or some property of an element of this queue prevents - * it from being added to the specified collection - */ - int drainTo(Collection c); - - /** - * Removes at most the given number of available elements from - * this queue and adds them to the given collection. A failure - * encountered while attempting to add elements to - * collection c may result in elements being in neither, - * either or both collections when the associated exception is - * thrown. Attempts to drain a queue to itself result in - * IllegalArgumentException. Further, the behavior of - * this operation is undefined if the specified collection is - * modified while the operation is in progress. - * - * @param c the collection to transfer elements into - * @param maxElements the maximum number of elements to transfer - * @return the number of elements transferred - * @throws UnsupportedOperationException if addition of elements - * is not supported by the specified collection - * @throws ClassCastException if the class of an element of this queue - * prevents it from being added to the specified collection - * @throws NullPointerException if the specified collection is null - * @throws IllegalArgumentException if the specified collection is this - * queue, or some property of an element of this queue prevents - * it from being added to the specified collection - */ - int drainTo(Collection c, int maxElements); -} diff --git a/src/actors/scala/actors/threadpool/Callable.java b/src/actors/scala/actors/threadpool/Callable.java deleted file mode 100644 index f1b200c022..0000000000 --- a/src/actors/scala/actors/threadpool/Callable.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -/** - * A task that returns a result and may throw an exception. - * Implementors define a single method with no arguments called - * call. - * - *

The Callable interface is similar to {@link - * java.lang.Runnable}, in that both are designed for classes whose - * instances are potentially executed by another thread. A - * Runnable, however, does not return a result and cannot - * throw a checked exception. - * - *

The {@link Executors} class contains utility methods to - * convert from other common forms to Callable classes. - * - * @see Executor - * @since 1.5 - * @author Doug Lea - */ -public interface Callable { - /** - * Computes a result, or throws an exception if unable to do so. - * - * @return computed result - * @throws Exception if unable to compute a result - */ - Object call() throws Exception; -} diff --git a/src/actors/scala/actors/threadpool/CancellationException.java b/src/actors/scala/actors/threadpool/CancellationException.java deleted file mode 100644 index c2163b83c7..0000000000 --- a/src/actors/scala/actors/threadpool/CancellationException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -/** - * Exception indicating that the result of a value-producing task, - * such as a {@link FutureTask}, cannot be retrieved because the task - * was cancelled. - * - * @since 1.5 - * @author Doug Lea - */ -public class CancellationException extends IllegalStateException { - private static final long serialVersionUID = -9202173006928992231L; - - /** - * Constructs a CancellationException with no detail message. - */ - public CancellationException() {} - - /** - * Constructs a CancellationException with the specified detail - * message. - * - * @param message the detail message - */ - public CancellationException(String message) { - super(message); - } -} diff --git a/src/actors/scala/actors/threadpool/CompletionService.java b/src/actors/scala/actors/threadpool/CompletionService.java deleted file mode 100644 index 219ab7affa..0000000000 --- a/src/actors/scala/actors/threadpool/CompletionService.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -/** - * A service that decouples the production of new asynchronous tasks - * from the consumption of the results of completed tasks. Producers - * submit tasks for execution. Consumers take - * completed tasks and process their results in the order they - * complete. A CompletionService can for example be used to - * manage asynchronous IO, in which tasks that perform reads are - * submitted in one part of a program or system, and then acted upon - * in a different part of the program when the reads complete, - * possibly in a different order than they were requested. - * - *

Typically, a CompletionService relies on a separate - * {@link Executor} to actually execute the tasks, in which case the - * CompletionService only manages an internal completion - * queue. The {@link ExecutorCompletionService} class provides an - * implementation of this approach. - * - *

Memory consistency effects: Actions in a thread prior to - * submitting a task to a {@code CompletionService} - * happen-before - * actions taken by that task, which in turn happen-before - * actions following a successful return from the corresponding {@code take()}. - * - */ -public interface CompletionService { - /** - * Submits a value-returning task for execution and returns a Future - * representing the pending results of the task. Upon completion, - * this task may be taken or polled. - * - * @param task the task to submit - * @return a Future representing pending completion of the task - * @throws RejectedExecutionException if the task cannot be - * scheduled for execution - * @throws NullPointerException if the task is null - */ - Future submit(Callable task); - - /** - * Submits a Runnable task for execution and returns a Future - * representing that task. Upon completion, this task may be - * taken or polled. - * - * @param task the task to submit - * @param result the result to return upon successful completion - * @return a Future representing pending completion of the task, - * and whose get() method will return the given - * result value upon completion - * @throws RejectedExecutionException if the task cannot be - * scheduled for execution - * @throws NullPointerException if the task is null - */ - Future submit(Runnable task, Object result); - - /** - * Retrieves and removes the Future representing the next - * completed task, waiting if none are yet present. - * - * @return the Future representing the next completed task - * @throws InterruptedException if interrupted while waiting - */ - Future take() throws InterruptedException; - - - /** - * Retrieves and removes the Future representing the next - * completed task or null if none are present. - * - * @return the Future representing the next completed task, or - * null if none are present - */ - Future poll(); - - /** - * Retrieves and removes the Future representing the next - * completed task, waiting if necessary up to the specified wait - * time if none are yet present. - * - * @param timeout how long to wait before giving up, in units of - * unit - * @param unit a TimeUnit determining how to interpret the - * timeout parameter - * @return the Future representing the next completed task or - * null if the specified waiting time elapses - * before one is present - * @throws InterruptedException if interrupted while waiting - */ - Future poll(long timeout, TimeUnit unit) throws InterruptedException; -} diff --git a/src/actors/scala/actors/threadpool/ExecutionException.java b/src/actors/scala/actors/threadpool/ExecutionException.java deleted file mode 100644 index 912f965acf..0000000000 --- a/src/actors/scala/actors/threadpool/ExecutionException.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -/** - * Exception thrown when attempting to retrieve the result of a task - * that aborted by throwing an exception. This exception can be - * inspected using the {@link #getCause()} method. - * - * @see Future - * @since 1.5 - * @author Doug Lea - */ -public class ExecutionException extends Exception { - private static final long serialVersionUID = 7830266012832686185L; - - /** - * Constructs an ExecutionException with no detail message. - * The cause is not initialized, and may subsequently be - * initialized by a call to {@link #initCause(Throwable) initCause}. - */ - protected ExecutionException() { } - - /** - * Constructs an ExecutionException with the specified detail - * message. The cause is not initialized, and may subsequently be - * initialized by a call to {@link #initCause(Throwable) initCause}. - * - * @param message the detail message - */ - protected ExecutionException(String message) { - super(message); - } - - /** - * Constructs an ExecutionException with the specified detail - * message and cause. - * - * @param message the detail message - * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method) - */ - public ExecutionException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Constructs an ExecutionException with the specified cause. - * The detail message is set to: - *

-     *  (cause == null ? null : cause.toString())
- * (which typically contains the class and detail message of - * cause). - * - * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method) - */ - public ExecutionException(Throwable cause) { - super(cause); - } -} diff --git a/src/actors/scala/actors/threadpool/Executor.java b/src/actors/scala/actors/threadpool/Executor.java deleted file mode 100644 index e444e64dff..0000000000 --- a/src/actors/scala/actors/threadpool/Executor.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -/** - * An object that executes submitted {@link Runnable} tasks. This - * interface provides a way of decoupling task submission from the - * mechanics of how each task will be run, including details of thread - * use, scheduling, etc. An Executor is normally used - * instead of explicitly creating threads. For example, rather than - * invoking new Thread(new(RunnableTask())).start() for each - * of a set of tasks, you might use: - * - *
- * Executor executor = anExecutor;
- * executor.execute(new RunnableTask1());
- * executor.execute(new RunnableTask2());
- * ...
- * 
- * - * However, the Executor interface does not strictly - * require that execution be asynchronous. In the simplest case, an - * executor can run the submitted task immediately in the caller's - * thread: - * - *
- * class DirectExecutor implements Executor {
- *     public void execute(Runnable r) {
- *         r.run();
- *     }
- * }
- * - * More typically, tasks are executed in some thread other - * than the caller's thread. The executor below spawns a new thread - * for each task. - * - *
- * class ThreadPerTaskExecutor implements Executor {
- *     public void execute(Runnable r) {
- *         new Thread(r).start();
- *     }
- * }
- * - * Many Executor implementations impose some sort of - * limitation on how and when tasks are scheduled. The executor below - * serializes the submission of tasks to a second executor, - * illustrating a composite executor. - * - *
- * class SerialExecutor implements Executor {
- *     final Queue<Runnable> tasks = new ArrayDeque<Runnable>();
- *     final Executor executor;
- *     Runnable active;
- *
- *     SerialExecutor(Executor executor) {
- *         this.executor = executor;
- *     }
- *
- *     public synchronized void execute(final Runnable r) {
- *         tasks.offer(new Runnable() {
- *             public void run() {
- *                 try {
- *                     r.run();
- *                 } finally {
- *                     scheduleNext();
- *                 }
- *             }
- *         });
- *         if (active == null) {
- *             scheduleNext();
- *         }
- *     }
- *
- *     protected synchronized void scheduleNext() {
- *         if ((active = tasks.poll()) != null) {
- *             executor.execute(active);
- *         }
- *     }
- * }
- * - * The Executor implementations provided in this package - * implement {@link ExecutorService}, which is a more extensive - * interface. The {@link ThreadPoolExecutor} class provides an - * extensible thread pool implementation. The {@link Executors} class - * provides convenient factory methods for these Executors. - * - *

Memory consistency effects: Actions in a thread prior to - * submitting a {@code Runnable} object to an {@code Executor} - * happen-before - * its execution begins, perhaps in another thread. - * - * @since 1.5 - * @author Doug Lea - */ -public interface Executor { - - /** - * Executes the given command at some time in the future. The command - * may execute in a new thread, in a pooled thread, or in the calling - * thread, at the discretion of the Executor implementation. - * - * @param command the runnable task - * @throws RejectedExecutionException if this task cannot be - * accepted for execution. - * @throws NullPointerException if command is null - */ - void execute(Runnable command); -} diff --git a/src/actors/scala/actors/threadpool/ExecutorCompletionService.java b/src/actors/scala/actors/threadpool/ExecutorCompletionService.java deleted file mode 100644 index 02e9bbe297..0000000000 --- a/src/actors/scala/actors/threadpool/ExecutorCompletionService.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; -import scala.actors.threadpool.*; // for javadoc (till 6280605 is fixed) - -/** - * A {@link CompletionService} that uses a supplied {@link Executor} - * to execute tasks. This class arranges that submitted tasks are, - * upon completion, placed on a queue accessible using take. - * The class is lightweight enough to be suitable for transient use - * when processing groups of tasks. - * - *

- * - * Usage Examples. - * - * Suppose you have a set of solvers for a certain problem, each - * returning a value of some type Result, and would like to - * run them concurrently, processing the results of each of them that - * return a non-null value, in some method use(Result r). You - * could write this as: - * - *

- *   void solve(Executor e,
- *              Collection<Callable<Result>> solvers)
- *     throws InterruptedException, ExecutionException {
- *       CompletionService<Result> ecs
- *           = new ExecutorCompletionService<Result>(e);
- *       for (Callable<Result> s : solvers)
- *           ecs.submit(s);
- *       int n = solvers.size();
- *       for (int i = 0; i < n; ++i) {
- *           Result r = ecs.take().get();
- *           if (r != null)
- *               use(r);
- *       }
- *   }
- * 
- * - * Suppose instead that you would like to use the first non-null result - * of the set of tasks, ignoring any that encounter exceptions, - * and cancelling all other tasks when the first one is ready: - * - *
- *   void solve(Executor e,
- *              Collection<Callable<Result>> solvers)
- *     throws InterruptedException {
- *       CompletionService<Result> ecs
- *           = new ExecutorCompletionService<Result>(e);
- *       int n = solvers.size();
- *       List<Future<Result>> futures
- *           = new ArrayList<Future<Result>>(n);
- *       Result result = null;
- *       try {
- *           for (Callable<Result> s : solvers)
- *               futures.add(ecs.submit(s));
- *           for (int i = 0; i < n; ++i) {
- *               try {
- *                   Result r = ecs.take().get();
- *                   if (r != null) {
- *                       result = r;
- *                       break;
- *                   }
- *               } catch (ExecutionException ignore) {}
- *           }
- *       }
- *       finally {
- *           for (Future<Result> f : futures)
- *               f.cancel(true);
- *       }
- *
- *       if (result != null)
- *           use(result);
- *   }
- * 
- */ -public class ExecutorCompletionService implements CompletionService { - private final Executor executor; - private final AbstractExecutorService aes; - private final BlockingQueue completionQueue; - - /** - * FutureTask extension to enqueue upon completion - */ - private class QueueingFuture extends FutureTask { - QueueingFuture(RunnableFuture task) { - super(task, null); - this.task = task; - } - protected void done() { completionQueue.add(task); } - private final Future task; - } - - private RunnableFuture newTaskFor(Callable task) { - if (aes == null) - return new FutureTask(task); - else - return aes.newTaskFor(task); - } - - private RunnableFuture newTaskFor(Runnable task, Object result) { - if (aes == null) - return new FutureTask(task, result); - else - return aes.newTaskFor(task, result); - } - - /** - * Creates an ExecutorCompletionService using the supplied - * executor for base task execution and a - * {@link LinkedBlockingQueue} as a completion queue. - * - * @param executor the executor to use - * @throws NullPointerException if executor is null - */ - public ExecutorCompletionService(Executor executor) { - if (executor == null) - throw new NullPointerException(); - this.executor = executor; - this.aes = (executor instanceof AbstractExecutorService) ? - (AbstractExecutorService) executor : null; - this.completionQueue = new LinkedBlockingQueue(); - } - - /** - * Creates an ExecutorCompletionService using the supplied - * executor for base task execution and the supplied queue as its - * completion queue. - * - * @param executor the executor to use - * @param completionQueue the queue to use as the completion queue - * normally one dedicated for use by this service. This queue is - * treated as unbounded -- failed attempted Queue.add - * operations for completed tasks cause them not to be - * retrievable. - * @throws NullPointerException if executor or completionQueue are null - */ - public ExecutorCompletionService(Executor executor, - BlockingQueue completionQueue) { - if (executor == null || completionQueue == null) - throw new NullPointerException(); - this.executor = executor; - this.aes = (executor instanceof AbstractExecutorService) ? - (AbstractExecutorService) executor : null; - this.completionQueue = completionQueue; - } - - public Future submit(Callable task) { - if (task == null) throw new NullPointerException(); - RunnableFuture f = newTaskFor(task); - executor.execute(new QueueingFuture(f)); - return f; - } - - public Future submit(Runnable task, Object result) { - if (task == null) throw new NullPointerException(); - RunnableFuture f = newTaskFor(task, result); - executor.execute(new QueueingFuture(f)); - return f; - } - - public Future take() throws InterruptedException { - return (Future)completionQueue.take(); - } - - public Future poll() { - return (Future)completionQueue.poll(); - } - - public Future poll(long timeout, TimeUnit unit) throws InterruptedException { - return (Future)completionQueue.poll(timeout, unit); - } - -} diff --git a/src/actors/scala/actors/threadpool/ExecutorService.java b/src/actors/scala/actors/threadpool/ExecutorService.java deleted file mode 100644 index d3a9a3b8a8..0000000000 --- a/src/actors/scala/actors/threadpool/ExecutorService.java +++ /dev/null @@ -1,331 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -import scala.actors.threadpool.*; // for javadoc (till 6280605 is fixed) -import java.util.List; -import java.util.Collection; - -/** - * An {@link Executor} that provides methods to manage termination and - * methods that can produce a {@link Future} for tracking progress of - * one or more asynchronous tasks. - * - *

An ExecutorService can be shut down, which will cause - * it to reject new tasks. Two different methods are provided for - * shutting down an ExecutorService. The {@link #shutdown} - * method will allow previously submitted tasks to execute before - * terminating, while the {@link #shutdownNow} method prevents waiting - * tasks from starting and attempts to stop currently executing tasks. - * Upon termination, an executor has no tasks actively executing, no - * tasks awaiting execution, and no new tasks can be submitted. An - * unused ExecutorService should be shut down to allow - * reclamation of its resources. - * - *

Method submit extends base method {@link - * Executor#execute} by creating and returning a {@link Future} that - * can be used to cancel execution and/or wait for completion. - * Methods invokeAny and invokeAll perform the most - * commonly useful forms of bulk execution, executing a collection of - * tasks and then waiting for at least one, or all, to - * complete. (Class {@link ExecutorCompletionService} can be used to - * write customized variants of these methods.) - * - *

The {@link Executors} class provides factory methods for the - * executor services provided in this package. - * - *

Usage Example

- * - * Here is a sketch of a network service in which threads in a thread - * pool service incoming requests. It uses the preconfigured {@link - * Executors#newFixedThreadPool} factory method: - * - *
- * class NetworkService implements Runnable {
- *   private final ServerSocket serverSocket;
- *   private final ExecutorService pool;
- *
- *   public NetworkService(int port, int poolSize)
- *       throws IOException {
- *     serverSocket = new ServerSocket(port);
- *     pool = Executors.newFixedThreadPool(poolSize);
- *   }
- *
- *   public void run() { // run the service
- *     try {
- *       for (;;) {
- *         pool.execute(new Handler(serverSocket.accept()));
- *       }
- *     } catch (IOException ex) {
- *       pool.shutdown();
- *     }
- *   }
- * }
- *
- * class Handler implements Runnable {
- *   private final Socket socket;
- *   Handler(Socket socket) { this.socket = socket; }
- *   public void run() {
- *     // read and service request on socket
- *   }
- * }
- * 
- * - * The following method shuts down an ExecutorService in two phases, - * first by calling shutdown to reject incoming tasks, and then - * calling shutdownNow, if necessary, to cancel any lingering tasks: - * - *
- * void shutdownAndAwaitTermination(ExecutorService pool) {
- *   pool.shutdown(); // Disable new tasks from being submitted
- *   try {
- *     // Wait a while for existing tasks to terminate
- *     if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
- *       pool.shutdownNow(); // Cancel currently executing tasks
- *       // Wait a while for tasks to respond to being cancelled
- *       if (!pool.awaitTermination(60, TimeUnit.SECONDS))
- *           System.err.println("Pool did not terminate");
- *     }
- *   } catch (InterruptedException ie) {
- *     // (Re-)Cancel if current thread also interrupted
- *     pool.shutdownNow();
- *     // Preserve interrupt status
- *     Thread.currentThread().interrupt();
- *   }
- * }
- * 
- * - *

Memory consistency effects: Actions in a thread prior to the - * submission of a {@code Runnable} or {@code Callable} task to an - * {@code ExecutorService} - * happen-before - * any actions taken by that task, which in turn happen-before the - * result is retrieved via {@code Future.get()}. - * - * @since 1.5 - * @author Doug Lea - */ -public interface ExecutorService extends Executor { - - /** - * Initiates an orderly shutdown in which previously submitted - * tasks are executed, but no new tasks will be accepted. - * Invocation has no additional effect if already shut down. - * - * @throws SecurityException if a security manager exists and - * shutting down this ExecutorService may manipulate - * threads that the caller is not permitted to modify - * because it does not hold {@link - * java.lang.RuntimePermission}("modifyThread"), - * or the security manager's checkAccess method - * denies access. - */ - void shutdown(); - - /** - * Attempts to stop all actively executing tasks, halts the - * processing of waiting tasks, and returns a list of the tasks that were - * awaiting execution. - * - *

There are no guarantees beyond best-effort attempts to stop - * processing actively executing tasks. For example, typical - * implementations will cancel via {@link Thread#interrupt}, so any - * task that fails to respond to interrupts may never terminate. - * - * @return list of tasks that never commenced execution - * @throws SecurityException if a security manager exists and - * shutting down this ExecutorService may manipulate - * threads that the caller is not permitted to modify - * because it does not hold {@link - * java.lang.RuntimePermission}("modifyThread"), - * or the security manager's checkAccess method - * denies access. - */ - List shutdownNow(); - - /** - * Returns true if this executor has been shut down. - * - * @return true if this executor has been shut down - */ - boolean isShutdown(); - - /** - * Returns true if all tasks have completed following shut down. - * Note that isTerminated is never true unless - * either shutdown or shutdownNow was called first. - * - * @return true if all tasks have completed following shut down - */ - boolean isTerminated(); - - /** - * Blocks until all tasks have completed execution after a shutdown - * request, or the timeout occurs, or the current thread is - * interrupted, whichever happens first. - * - * @param timeout the maximum time to wait - * @param unit the time unit of the timeout argument - * @return true if this executor terminated and - * false if the timeout elapsed before termination - * @throws InterruptedException if interrupted while waiting - */ - boolean awaitTermination(long timeout, TimeUnit unit) - throws InterruptedException; - - - /** - * Submits a value-returning task for execution and returns a - * Future representing the pending results of the task. The - * Future's get method will return the task's result upon - * successful completion. - * - *

- * If you would like to immediately block waiting - * for a task, you can use constructions of the form - * result = exec.submit(aCallable).get(); - * - *

Note: The {@link Executors} class includes a set of methods - * that can convert some other common closure-like objects, - * for example, {@link java.security.PrivilegedAction} to - * {@link Callable} form so they can be submitted. - * - * @param task the task to submit - * @return a Future representing pending completion of the task - * @throws RejectedExecutionException if the task cannot be - * scheduled for execution - * @throws NullPointerException if the task is null - */ - Future submit(Callable task); - - /** - * Submits a Runnable task for execution and returns a Future - * representing that task. The Future's get method will - * return the given result upon successful completion. - * - * @param task the task to submit - * @param result the result to return - * @return a Future representing pending completion of the task - * @throws RejectedExecutionException if the task cannot be - * scheduled for execution - * @throws NullPointerException if the task is null - */ - Future submit(Runnable task, Object result); - - /** - * Submits a Runnable task for execution and returns a Future - * representing that task. The Future's get method will - * return null upon successful completion. - * - * @param task the task to submit - * @return a Future representing pending completion of the task - * @throws RejectedExecutionException if the task cannot be - * scheduled for execution - * @throws NullPointerException if the task is null - */ - Future submit(Runnable task); - - /** - * Executes the given tasks, returning a list of Futures holding - * their status and results when all complete. - * {@link Future#isDone} is true for each - * element of the returned list. - * Note that a completed task could have - * terminated either normally or by throwing an exception. - * The results of this method are undefined if the given - * collection is modified while this operation is in progress. - * - * @param tasks the collection of tasks - * @return A list of Futures representing the tasks, in the same - * sequential order as produced by the iterator for the - * given task list, each of which has completed. - * @throws InterruptedException if interrupted while waiting, in - * which case unfinished tasks are cancelled. - * @throws NullPointerException if tasks or any of its elements are null - * @throws RejectedExecutionException if any task cannot be - * scheduled for execution - */ - - List invokeAll(Collection tasks) - throws InterruptedException; - - /** - * Executes the given tasks, returning a list of Futures holding - * their status and results - * when all complete or the timeout expires, whichever happens first. - * {@link Future#isDone} is true for each - * element of the returned list. - * Upon return, tasks that have not completed are cancelled. - * Note that a completed task could have - * terminated either normally or by throwing an exception. - * The results of this method are undefined if the given - * collection is modified while this operation is in progress. - * - * @param tasks the collection of tasks - * @param timeout the maximum time to wait - * @param unit the time unit of the timeout argument - * @return a list of Futures representing the tasks, in the same - * sequential order as produced by the iterator for the - * given task list. If the operation did not time out, - * each task will have completed. If it did time out, some - * of these tasks will not have completed. - * @throws InterruptedException if interrupted while waiting, in - * which case unfinished tasks are cancelled - * @throws NullPointerException if tasks, any of its elements, or - * unit are null - * @throws RejectedExecutionException if any task cannot be scheduled - * for execution - */ - List invokeAll(Collection tasks, long timeout, TimeUnit unit) - throws InterruptedException; - - /** - * Executes the given tasks, returning the result - * of one that has completed successfully (i.e., without throwing - * an exception), if any do. Upon normal or exceptional return, - * tasks that have not completed are cancelled. - * The results of this method are undefined if the given - * collection is modified while this operation is in progress. - * - * @param tasks the collection of tasks - * @return the result returned by one of the tasks - * @throws InterruptedException if interrupted while waiting - * @throws NullPointerException if tasks or any of its elements - * are null - * @throws IllegalArgumentException if tasks is empty - * @throws ExecutionException if no task successfully completes - * @throws RejectedExecutionException if tasks cannot be scheduled - * for execution - */ - Object invokeAny(Collection tasks) - throws InterruptedException, ExecutionException; - - /** - * Executes the given tasks, returning the result - * of one that has completed successfully (i.e., without throwing - * an exception), if any do before the given timeout elapses. - * Upon normal or exceptional return, tasks that have not - * completed are cancelled. - * The results of this method are undefined if the given - * collection is modified while this operation is in progress. - * - * @param tasks the collection of tasks - * @param timeout the maximum time to wait - * @param unit the time unit of the timeout argument - * @return the result returned by one of the tasks. - * @throws InterruptedException if interrupted while waiting - * @throws NullPointerException if tasks, any of its elements, or - * unit are null - * @throws TimeoutException if the given timeout elapses before - * any task successfully completes - * @throws ExecutionException if no task successfully completes - * @throws RejectedExecutionException if tasks cannot be scheduled - * for execution - */ - Object invokeAny(Collection tasks, long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException; -} diff --git a/src/actors/scala/actors/threadpool/Executors.java b/src/actors/scala/actors/threadpool/Executors.java deleted file mode 100644 index 49a127a8db..0000000000 --- a/src/actors/scala/actors/threadpool/Executors.java +++ /dev/null @@ -1,667 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; -//import edu.emory.mathcs.backport.java.util.*; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedExceptionAction; -import java.security.AccessControlException; -import java.util.List; -import java.util.Collection; - -/** - * Factory and utility methods for {@link Executor}, {@link - * ExecutorService}, {@link ScheduledExecutorService}, {@link - * ThreadFactory}, and {@link Callable} classes defined in this - * package. This class supports the following kinds of methods: - * - *

    - *
  • Methods that create and return an {@link ExecutorService} - * set up with commonly useful configuration settings. - *
  • Methods that create and return a {@link ScheduledExecutorService} - * set up with commonly useful configuration settings. - *
  • Methods that create and return a "wrapped" ExecutorService, that - * disables reconfiguration by making implementation-specific methods - * inaccessible. - *
  • Methods that create and return a {@link ThreadFactory} - * that sets newly created threads to a known state. - *
  • Methods that create and return a {@link Callable} - * out of other closure-like forms, so they can be used - * in execution methods requiring Callable. - *
- * - * @since 1.5 - * @author Doug Lea - */ -public class Executors { - - /** - * Creates a thread pool that reuses a fixed number of threads - * operating off a shared unbounded queue. At any point, at most - * nThreads threads will be active processing tasks. - * If additional tasks are submitted when all threads are active, - * they will wait in the queue until a thread is available. - * If any thread terminates due to a failure during execution - * prior to shutdown, a new one will take its place if needed to - * execute subsequent tasks. The threads in the pool will exist - * until it is explicitly {@link ExecutorService#shutdown shutdown}. - * - * @param nThreads the number of threads in the pool - * @return the newly created thread pool - * @throws IllegalArgumentException if nThreads <= 0 - */ - public static ExecutorService newFixedThreadPool(int nThreads) { - return new ThreadPoolExecutor(nThreads, nThreads, - 0L, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue()); - } - - /** - * Creates a thread pool that reuses a fixed number of threads - * operating off a shared unbounded queue, using the provided - * ThreadFactory to create new threads when needed. At any point, - * at most nThreads threads will be active processing - * tasks. If additional tasks are submitted when all threads are - * active, they will wait in the queue until a thread is - * available. If any thread terminates due to a failure during - * execution prior to shutdown, a new one will take its place if - * needed to execute subsequent tasks. The threads in the pool will - * exist until it is explicitly {@link ExecutorService#shutdown - * shutdown}. - * - * @param nThreads the number of threads in the pool - * @param threadFactory the factory to use when creating new threads - * @return the newly created thread pool - * @throws NullPointerException if threadFactory is null - * @throws IllegalArgumentException if nThreads <= 0 - */ - public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { - return new ThreadPoolExecutor(nThreads, nThreads, - 0L, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue(), - threadFactory); - } - - /** - * Creates an Executor that uses a single worker thread operating - * off an unbounded queue. (Note however that if this single - * thread terminates due to a failure during execution prior to - * shutdown, a new one will take its place if needed to execute - * subsequent tasks.) Tasks are guaranteed to execute - * sequentially, and no more than one task will be active at any - * given time. Unlike the otherwise equivalent - * newFixedThreadPool(1) the returned executor is - * guaranteed not to be reconfigurable to use additional threads. - * - * @return the newly created single-threaded Executor - */ - public static ExecutorService newSingleThreadExecutor() { - return new FinalizableDelegatedExecutorService - (new ThreadPoolExecutor(1, 1, - 0L, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue())); - } - - /** - * Creates an Executor that uses a single worker thread operating - * off an unbounded queue, and uses the provided ThreadFactory to - * create a new thread when needed. Unlike the otherwise - * equivalent newFixedThreadPool(1, threadFactory) the - * returned executor is guaranteed not to be reconfigurable to use - * additional threads. - * - * @param threadFactory the factory to use when creating new - * threads - * - * @return the newly created single-threaded Executor - * @throws NullPointerException if threadFactory is null - */ - public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) { - return new FinalizableDelegatedExecutorService - (new ThreadPoolExecutor(1, 1, - 0L, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue(), - threadFactory)); - } - - /** - * Creates a thread pool that creates new threads as needed, but - * will reuse previously constructed threads when they are - * available. These pools will typically improve the performance - * of programs that execute many short-lived asynchronous tasks. - * Calls to execute will reuse previously constructed - * threads if available. If no existing thread is available, a new - * thread will be created and added to the pool. Threads that have - * not been used for sixty seconds are terminated and removed from - * the cache. Thus, a pool that remains idle for long enough will - * not consume any resources. Note that pools with similar - * properties but different details (for example, timeout parameters) - * may be created using {@link ThreadPoolExecutor} constructors. - * - * @return the newly created thread pool - */ - public static ExecutorService newCachedThreadPool() { - return new ThreadPoolExecutor(0, Integer.MAX_VALUE, - 60L, TimeUnit.SECONDS, - new SynchronousQueue()); - } - - /** - * Creates a thread pool that creates new threads as needed, but - * will reuse previously constructed threads when they are - * available, and uses the provided - * ThreadFactory to create new threads when needed. - * @param threadFactory the factory to use when creating new threads - * @return the newly created thread pool - * @throws NullPointerException if threadFactory is null - */ - public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { - return new ThreadPoolExecutor(0, Integer.MAX_VALUE, - 60L, TimeUnit.SECONDS, - new SynchronousQueue(), - threadFactory); - } - - /** - * Creates a single-threaded executor that can schedule commands - * to run after a given delay, or to execute periodically. - * (Note however that if this single - * thread terminates due to a failure during execution prior to - * shutdown, a new one will take its place if needed to execute - * subsequent tasks.) Tasks are guaranteed to execute - * sequentially, and no more than one task will be active at any - * given time. Unlike the otherwise equivalent - * newScheduledThreadPool(1) the returned executor is - * guaranteed not to be reconfigurable to use additional threads. - * @return the newly created scheduled executor - */ - /* public static ScheduledExecutorService newSingleThreadScheduledExecutor() { - return new DelegatedScheduledExecutorService - (new ScheduledThreadPoolExecutor(1)); - } - */ - /** - * Creates a single-threaded executor that can schedule commands - * to run after a given delay, or to execute periodically. (Note - * however that if this single thread terminates due to a failure - * during execution prior to shutdown, a new one will take its - * place if needed to execute subsequent tasks.) Tasks are - * guaranteed to execute sequentially, and no more than one task - * will be active at any given time. Unlike the otherwise - * equivalent newScheduledThreadPool(1, threadFactory) - * the returned executor is guaranteed not to be reconfigurable to - * use additional threads. - * @param threadFactory the factory to use when creating new - * threads - * @return a newly created scheduled executor - * @throws NullPointerException if threadFactory is null - */ - /* public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) { - return new DelegatedScheduledExecutorService - (new ScheduledThreadPoolExecutor(1, threadFactory)); - } - */ - /** - * Creates a thread pool that can schedule commands to run after a - * given delay, or to execute periodically. - * @param corePoolSize the number of threads to keep in the pool, - * even if they are idle. - * @return a newly created scheduled thread pool - * @throws IllegalArgumentException if corePoolSize < 0 - */ - /* public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { - return new ScheduledThreadPoolExecutor(corePoolSize); - } - */ - /** - * Creates a thread pool that can schedule commands to run after a - * given delay, or to execute periodically. - * @param corePoolSize the number of threads to keep in the pool, - * even if they are idle. - * @param threadFactory the factory to use when the executor - * creates a new thread. - * @return a newly created scheduled thread pool - * @throws IllegalArgumentException if corePoolSize < 0 - * @throws NullPointerException if threadFactory is null - */ - /* public static ScheduledExecutorService newScheduledThreadPool( - int corePoolSize, ThreadFactory threadFactory) { - return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory); - } - */ - - /** - * Returns an object that delegates all defined {@link - * ExecutorService} methods to the given executor, but not any - * other methods that might otherwise be accessible using - * casts. This provides a way to safely "freeze" configuration and - * disallow tuning of a given concrete implementation. - * @param executor the underlying implementation - * @return an ExecutorService instance - * @throws NullPointerException if executor null - */ - public static ExecutorService unconfigurableExecutorService(ExecutorService executor) { - if (executor == null) - throw new NullPointerException(); - return new DelegatedExecutorService(executor); - } - - /** - * Returns an object that delegates all defined {@link - * ScheduledExecutorService} methods to the given executor, but - * not any other methods that might otherwise be accessible using - * casts. This provides a way to safely "freeze" configuration and - * disallow tuning of a given concrete implementation. - * @param executor the underlying implementation - * @return a ScheduledExecutorService instance - * @throws NullPointerException if executor null - */ - /* public static ScheduledExecutorService unconfigurableScheduledExecutorService(ScheduledExecutorService executor) { - if (executor == null) - throw new NullPointerException(); - return new DelegatedScheduledExecutorService(executor); - } - */ - /** - * Returns a default thread factory used to create new threads. - * This factory creates all new threads used by an Executor in the - * same {@link ThreadGroup}. If there is a {@link - * java.lang.SecurityManager}, it uses the group of {@link - * System#getSecurityManager}, else the group of the thread - * invoking this defaultThreadFactory method. Each new - * thread is created as a non-daemon thread with priority set to - * the smaller of Thread.NORM_PRIORITY and the maximum - * priority permitted in the thread group. New threads have names - * accessible via {@link Thread#getName} of - * pool-N-thread-M, where N is the sequence - * number of this factory, and M is the sequence number - * of the thread created by this factory. - * @return a thread factory - */ - public static ThreadFactory defaultThreadFactory() { - return new DefaultThreadFactory(); - } - - /** - * Returns a thread factory used to create new threads that - * have the same permissions as the current thread. - * This factory creates threads with the same settings as {@link - * Executors#defaultThreadFactory}, additionally setting the - * AccessControlContext and contextClassLoader of new threads to - * be the same as the thread invoking this - * privilegedThreadFactory method. A new - * privilegedThreadFactory can be created within an - * {@link AccessController#doPrivileged} action setting the - * current thread's access control context to create threads with - * the selected permission settings holding within that action. - * - *

Note that while tasks running within such threads will have - * the same access control and class loader settings as the - * current thread, they need not have the same {@link - * java.lang.ThreadLocal} or {@link - * java.lang.InheritableThreadLocal} values. If necessary, - * particular values of thread locals can be set or reset before - * any task runs in {@link ThreadPoolExecutor} subclasses using - * {@link ThreadPoolExecutor#beforeExecute}. Also, if it is - * necessary to initialize worker threads to have the same - * InheritableThreadLocal settings as some other designated - * thread, you can create a custom ThreadFactory in which that - * thread waits for and services requests to create others that - * will inherit its values. - * - * @return a thread factory - * @throws AccessControlException if the current access control - * context does not have permission to both get and set context - * class loader. - */ - public static ThreadFactory privilegedThreadFactory() { - return new PrivilegedThreadFactory(); - } - - /** - * Returns a {@link Callable} object that, when - * called, runs the given task and returns the given result. This - * can be useful when applying methods requiring a - * Callable to an otherwise resultless action. - * @param task the task to run - * @param result the result to return - * @return a callable object - * @throws NullPointerException if task null - */ - public static Callable callable(Runnable task, Object result) { - if (task == null) - throw new NullPointerException(); - return new RunnableAdapter(task, result); - } - - /** - * Returns a {@link Callable} object that, when - * called, runs the given task and returns null. - * @param task the task to run - * @return a callable object - * @throws NullPointerException if task null - */ - public static Callable callable(Runnable task) { - if (task == null) - throw new NullPointerException(); - return new RunnableAdapter(task, null); - } - - /** - * Returns a {@link Callable} object that, when - * called, runs the given privileged action and returns its result. - * @param action the privileged action to run - * @return a callable object - * @throws NullPointerException if action null - */ - public static Callable callable(final PrivilegedAction action) { - if (action == null) - throw new NullPointerException(); - return new Callable() { - public Object call() { return action.run(); }}; - } - - /** - * Returns a {@link Callable} object that, when - * called, runs the given privileged exception action and returns - * its result. - * @param action the privileged exception action to run - * @return a callable object - * @throws NullPointerException if action null - */ - public static Callable callable(final PrivilegedExceptionAction action) { - if (action == null) - throw new NullPointerException(); - return new Callable() { - public Object call() throws Exception { return action.run(); }}; - } - - /** - * Returns a {@link Callable} object that will, when - * called, execute the given callable under the current - * access control context. This method should normally be - * invoked within an {@link AccessController#doPrivileged} action - * to create callables that will, if possible, execute under the - * selected permission settings holding within that action; or if - * not possible, throw an associated {@link - * AccessControlException}. - * @param callable the underlying task - * @return a callable object - * @throws NullPointerException if callable null - * - */ - public static Callable privilegedCallable(Callable callable) { - if (callable == null) - throw new NullPointerException(); - return new PrivilegedCallable(callable); - } - - /** - * Returns a {@link Callable} object that will, when - * called, execute the given callable under the current - * access control context, with the current context class loader - * as the context class loader. This method should normally be - * invoked within an {@link AccessController#doPrivileged} action - * to create callables that will, if possible, execute under the - * selected permission settings holding within that action; or if - * not possible, throw an associated {@link - * AccessControlException}. - * @param callable the underlying task - * - * @return a callable object - * @throws NullPointerException if callable null - * @throws AccessControlException if the current access control - * context does not have permission to both set and get context - * class loader. - */ - public static Callable privilegedCallableUsingCurrentClassLoader(Callable callable) { - if (callable == null) - throw new NullPointerException(); - return new PrivilegedCallableUsingCurrentClassLoader(callable); - } - - // Non-public classes supporting the public methods - - /** - * A callable that runs given task and returns given result - */ - static final class RunnableAdapter implements Callable { - final Runnable task; - final Object result; - RunnableAdapter(Runnable task, Object result) { - this.task = task; - this.result = result; - } - public Object call() { - task.run(); - return result; - } - } - - /** - * A callable that runs under established access control settings - */ - static final class PrivilegedCallable implements Callable { - private final AccessControlContext acc; - private final Callable task; - private Object result; - private Exception exception; - PrivilegedCallable(Callable task) { - this.task = task; - this.acc = AccessController.getContext(); - } - - public Object call() throws Exception { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - try { - result = task.call(); - } catch (Exception ex) { - exception = ex; - } - return null; - } - }, acc); - if (exception != null) - throw exception; - else - return result; - } - } - - /** - * A callable that runs under established access control settings and - * current ClassLoader - */ - static final class PrivilegedCallableUsingCurrentClassLoader implements Callable { - private final ClassLoader ccl; - private final AccessControlContext acc; - private final Callable task; - private Object result; - private Exception exception; - PrivilegedCallableUsingCurrentClassLoader(Callable task) { - this.task = task; - this.ccl = Thread.currentThread().getContextClassLoader(); - this.acc = AccessController.getContext(); - acc.checkPermission(new RuntimePermission("getContextClassLoader")); - acc.checkPermission(new RuntimePermission("setContextClassLoader")); - } - - public Object call() throws Exception { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - ClassLoader savedcl = null; - Thread t = Thread.currentThread(); - try { - ClassLoader cl = t.getContextClassLoader(); - if (ccl != cl) { - t.setContextClassLoader(ccl); - savedcl = cl; - } - result = task.call(); - } catch (Exception ex) { - exception = ex; - } finally { - if (savedcl != null) - t.setContextClassLoader(savedcl); - } - return null; - } - }, acc); - if (exception != null) - throw exception; - else - return result; - } - } - - /** - * The default thread factory - */ - static class DefaultThreadFactory implements ThreadFactory { - static final AtomicInteger poolNumber = new AtomicInteger(1); - final ThreadGroup group; - final AtomicInteger threadNumber = new AtomicInteger(1); - final String namePrefix; - - DefaultThreadFactory() { - SecurityManager s = System.getSecurityManager(); - group = (s != null)? s.getThreadGroup() : - Thread.currentThread().getThreadGroup(); - namePrefix = "pool-" + - poolNumber.getAndIncrement() + - "-thread-"; - } - - public Thread newThread(Runnable r) { - Thread t = new Thread(group, r, - namePrefix + threadNumber.getAndIncrement(), - 0); - if (t.isDaemon()) - t.setDaemon(false); - if (t.getPriority() != Thread.NORM_PRIORITY) - t.setPriority(Thread.NORM_PRIORITY); - return t; - } - } - - /** - * Thread factory capturing access control and class loader - */ - static class PrivilegedThreadFactory extends DefaultThreadFactory { - private final ClassLoader ccl; - private final AccessControlContext acc; - - PrivilegedThreadFactory() { - super(); - this.ccl = Thread.currentThread().getContextClassLoader(); - this.acc = AccessController.getContext(); - acc.checkPermission(new RuntimePermission("setContextClassLoader")); - } - - public Thread newThread(final Runnable r) { - return super.newThread(new Runnable() { - public void run() { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - Thread.currentThread().setContextClassLoader(ccl); - r.run(); - return null; - } - }, acc); - } - }); - } - - } - - /** - * A wrapper class that exposes only the ExecutorService methods - * of an ExecutorService implementation. - */ - static class DelegatedExecutorService extends AbstractExecutorService { - private final ExecutorService e; - DelegatedExecutorService(ExecutorService executor) { e = executor; } - public void execute(Runnable command) { e.execute(command); } - public void shutdown() { e.shutdown(); } - public List shutdownNow() { return e.shutdownNow(); } - public boolean isShutdown() { return e.isShutdown(); } - public boolean isTerminated() { return e.isTerminated(); } - public boolean awaitTermination(long timeout, TimeUnit unit) - throws InterruptedException { - return e.awaitTermination(timeout, unit); - } - public Future submit(Runnable task) { - return e.submit(task); - } - public Future submit(Callable task) { - return e.submit(task); - } - public Future submit(Runnable task, Object result) { - return e.submit(task, result); - } - public List invokeAll(Collection tasks) - throws InterruptedException { - return e.invokeAll(tasks); - } - public List invokeAll(Collection tasks, - long timeout, TimeUnit unit) - throws InterruptedException { - return e.invokeAll(tasks, timeout, unit); - } - public Object invokeAny(Collection tasks) - throws InterruptedException, ExecutionException { - return e.invokeAny(tasks); - } - public Object invokeAny(Collection tasks, - long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - return e.invokeAny(tasks, timeout, unit); - } - } - - static class FinalizableDelegatedExecutorService - extends DelegatedExecutorService { - FinalizableDelegatedExecutorService(ExecutorService executor) { - super(executor); - } - protected void finalize() { - super.shutdown(); - } - } - - /** - * A wrapper class that exposes only the ScheduledExecutorService - * methods of a ScheduledExecutorService implementation. - */ - /* static class DelegatedScheduledExecutorService - extends DelegatedExecutorService - implements ScheduledExecutorService { - private final ScheduledExecutorService e; - DelegatedScheduledExecutorService(ScheduledExecutorService executor) { - super(executor); - e = executor; - } - public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) { - return e.schedule(command, delay, unit); - } - public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { - return e.schedule(callable, delay, unit); - } - public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { - return e.scheduleAtFixedRate(command, initialDelay, period, unit); - } - public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { - return e.scheduleWithFixedDelay(command, initialDelay, delay, unit); - } - } -*/ - - /** Cannot instantiate. */ - private Executors() {} -} diff --git a/src/actors/scala/actors/threadpool/Future.java b/src/actors/scala/actors/threadpool/Future.java deleted file mode 100644 index 5e1b3d414a..0000000000 --- a/src/actors/scala/actors/threadpool/Future.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; -import scala.actors.threadpool.*; // for javadoc (till 6280605 is fixed) - -/** - * A Future represents the result of an asynchronous - * computation. Methods are provided to check if the computation is - * complete, to wait for its completion, and to retrieve the result of - * the computation. The result can only be retrieved using method - * get when the computation has completed, blocking if - * necessary until it is ready. Cancellation is performed by the - * cancel method. Additional methods are provided to - * determine if the task completed normally or was cancelled. Once a - * computation has completed, the computation cannot be cancelled. - * If you would like to use a Future for the sake - * of cancellability but not provide a usable result, you can - * declare types of the form Future<?> and - * return null as a result of the underlying task. - * - *

- * Sample Usage (Note that the following classes are all - * made-up.)

- *

- * interface ArchiveSearcher { String search(String target); }
- * class App {
- *   ExecutorService executor = ...
- *   ArchiveSearcher searcher = ...
- *   void showSearch(final String target)
- *       throws InterruptedException {
- *     Future<String> future
- *       = executor.submit(new Callable<String>() {
- *         public String call() {
- *             return searcher.search(target);
- *         }});
- *     displayOtherThings(); // do other things while searching
- *     try {
- *       displayText(future.get()); // use future
- *     } catch (ExecutionException ex) { cleanup(); return; }
- *   }
- * }
- * 
- * - * The {@link FutureTask} class is an implementation of Future that - * implements Runnable, and so may be executed by an Executor. - * For example, the above construction with submit could be replaced by: - *
- *     FutureTask<String> future =
- *       new FutureTask<String>(new Callable<String>() {
- *         public String call() {
- *           return searcher.search(target);
- *       }});
- *     executor.execute(future);
- * 
- * - *

Memory consistency effects: Actions taken by the asynchronous computation - * happen-before - * actions following the corresponding {@code Future.get()} in another thread. - * - * @see FutureTask - * @see Executor - * @since 1.5 - * @author Doug Lea - */ -public interface Future { - - /** - * Attempts to cancel execution of this task. This attempt will - * fail if the task has already completed, has already been cancelled, - * or could not be cancelled for some other reason. If successful, - * and this task has not started when cancel is called, - * this task should never run. If the task has already started, - * then the mayInterruptIfRunning parameter determines - * whether the thread executing this task should be interrupted in - * an attempt to stop the task. - * - *

After this method returns, subsequent calls to {@link #isDone} will - * always return true. Subsequent calls to {@link #isCancelled} - * will always return true if this method returned true. - * - * @param mayInterruptIfRunning true if the thread executing this - * task should be interrupted; otherwise, in-progress tasks are allowed - * to complete - * @return false if the task could not be cancelled, - * typically because it has already completed normally; - * true otherwise - */ - boolean cancel(boolean mayInterruptIfRunning); - - /** - * Returns true if this task was cancelled before it completed - * normally. - * - * @return true if this task was cancelled before it completed - */ - boolean isCancelled(); - - /** - * Returns true if this task completed. - * - * Completion may be due to normal termination, an exception, or - * cancellation -- in all of these cases, this method will return - * true. - * - * @return true if this task completed - */ - boolean isDone(); - - /** - * Waits if necessary for the computation to complete, and then - * retrieves its result. - * - * @return the computed result - * @throws CancellationException if the computation was cancelled - * @throws ExecutionException if the computation threw an - * exception - * @throws InterruptedException if the current thread was interrupted - * while waiting - */ - Object get() throws InterruptedException, ExecutionException; - - /** - * Waits if necessary for at most the given time for the computation - * to complete, and then retrieves its result, if available. - * - * @param timeout the maximum time to wait - * @param unit the time unit of the timeout argument - * @return the computed result - * @throws CancellationException if the computation was cancelled - * @throws ExecutionException if the computation threw an - * exception - * @throws InterruptedException if the current thread was interrupted - * while waiting - * @throws TimeoutException if the wait timed out - */ - Object get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException; -} diff --git a/src/actors/scala/actors/threadpool/FutureTask.java b/src/actors/scala/actors/threadpool/FutureTask.java deleted file mode 100644 index d4dcfe38b3..0000000000 --- a/src/actors/scala/actors/threadpool/FutureTask.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain. Use, modify, and - * redistribute this code in any way without acknowledgement. - */ - -package scala.actors.threadpool; - -import scala.actors.threadpool.*; // for javadoc -import scala.actors.threadpool.helpers.*; - -/** - * A cancellable asynchronous computation. This class provides a base - * implementation of {@link Future}, with methods to start and cancel - * a computation, query to see if the computation is complete, and - * retrieve the result of the computation. The result can only be - * retrieved when the computation has completed; the get - * method will block if the computation has not yet completed. Once - * the computation has completed, the computation cannot be restarted - * or cancelled. - * - *

A FutureTask can be used to wrap a {@link Callable} or - * {@link java.lang.Runnable} object. Because FutureTask - * implements Runnable, a FutureTask can be - * submitted to an {@link Executor} for execution. - * - *

In addition to serving as a standalone class, this class provides - * protected functionality that may be useful when creating - * customized task classes. - * - * @since 1.5 - * @author Doug Lea - */ -public class FutureTask implements RunnableFuture { - - /** State value representing that task is ready to run */ - private static final int READY = 0; - /** State value representing that task is running */ - private static final int RUNNING = 1; - /** State value representing that task ran */ - private static final int RAN = 2; - /** State value representing that task was cancelled */ - private static final int CANCELLED = 4; - - /** The underlying callable */ - private final Callable callable; - /** The result to return from get() */ - private Object result; - /** The exception to throw from get() */ - private Throwable exception; - - private int state; - - /** - * The thread running task. When nulled after set/cancel, this - * indicates that the results are accessible. Must be - * volatile, to ensure visibility upon completion. - */ - private volatile Thread runner; - - /** - * Creates a FutureTask that will, upon running, execute the - * given Callable. - * - * @param callable the callable task - * @throws NullPointerException if callable is null - */ - public FutureTask(Callable callable) { - if (callable == null) - throw new NullPointerException(); - this.callable = callable; - } - - /** - * Creates a FutureTask that will, upon running, execute the - * given Runnable, and arrange that get will return the - * given result on successful completion. - * - * @param runnable the runnable task - * @param result the result to return on successful completion. If - * you don't need a particular result, consider using - * constructions of the form: - * Future<?> f = new FutureTask<Object>(runnable, null) - * @throws NullPointerException if runnable is null - */ - public FutureTask(Runnable runnable, Object result) { - this(Executors.callable(runnable, result)); - } - - public synchronized boolean isCancelled() { - return state == CANCELLED; - } - - public synchronized boolean isDone() { - return ranOrCancelled() && runner == null; - } - - public boolean cancel(boolean mayInterruptIfRunning) { - synchronized (this) { - if (ranOrCancelled()) return false; - state = CANCELLED; - if (mayInterruptIfRunning) { - Thread r = runner; - if (r != null) r.interrupt(); - } - runner = null; - notifyAll(); - } - done(); - return true; - } - - /** - * @throws CancellationException {@inheritDoc} - */ - public synchronized Object get() - throws InterruptedException, ExecutionException - { - waitFor(); - return getResult(); - } - - /** - * @throws CancellationException {@inheritDoc} - */ - public synchronized Object get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException - { - waitFor(unit.toNanos(timeout)); - return getResult(); - } - - /** - * Protected method invoked when this task transitions to state - * isDone (whether normally or via cancellation). The - * default implementation does nothing. Subclasses may override - * this method to invoke completion callbacks or perform - * bookkeeping. Note that you can query status inside the - * implementation of this method to determine whether this task - * has been cancelled. - */ - protected void done() { } - - /** - * Sets the result of this Future to the given value unless - * this future has already been set or has been cancelled. - * This method is invoked internally by the run method - * upon successful completion of the computation. - * @param v the value - */ - protected void set(Object v) { - setCompleted(v); - } - - /** - * Causes this future to report an ExecutionException - * with the given throwable as its cause, unless this Future has - * already been set or has been cancelled. - * This method is invoked internally by the run method - * upon failure of the computation. - * @param t the cause of failure - */ - protected void setException(Throwable t) { - setFailed(t); - } - - /** - * Sets this Future to the result of its computation - * unless it has been cancelled. - */ - public void run() { - synchronized (this) { - if (state != READY) return; - state = RUNNING; - runner = Thread.currentThread(); - } - try { - set(callable.call()); - } - catch (Throwable ex) { - setException(ex); - } - } - - /** - * Executes the computation without setting its result, and then - * resets this Future to initial state, failing to do so if the - * computation encounters an exception or is cancelled. This is - * designed for use with tasks that intrinsically execute more - * than once. - * @return true if successfully run and reset - */ - protected boolean runAndReset() { - synchronized (this) { - if (state != READY) return false; - state = RUNNING; - runner = Thread.currentThread(); - } - try { - callable.call(); // don't set result - synchronized (this) { - runner = null; - if (state == RUNNING) { - state = READY; - return true; - } - else { - return false; - } - } - } - catch (Throwable ex) { - setException(ex); - return false; - } - } - - // PRE: lock owned - private boolean ranOrCancelled() { - return (state & (RAN | CANCELLED)) != 0; - } - - /** - * Marks the task as completed. - * @param result the result of a task. - */ - private void setCompleted(Object result) { - synchronized (this) { - if (ranOrCancelled()) return; - this.state = RAN; - this.result = result; - this.runner = null; - notifyAll(); - } - - // invoking callbacks *after* setting future as completed and - // outside the synchronization block makes it safe to call - // interrupt() from within callback code (in which case it will be - // ignored rather than cause deadlock / illegal state exception) - done(); - } - - /** - * Marks the task as failed. - * @param exception the cause of abrupt completion. - */ - private void setFailed(Throwable exception) { - synchronized (this) { - if (ranOrCancelled()) return; - this.state = RAN; - this.exception = exception; - this.runner = null; - notifyAll(); - } - - // invoking callbacks *after* setting future as completed and - // outside the synchronization block makes it safe to call - // interrupt() from within callback code (in which case it will be - // ignored rather than cause deadlock / illegal state exception) - done(); - } - - /** - * Waits for the task to complete. - * PRE: lock owned - */ - private void waitFor() throws InterruptedException { - while (!isDone()) { - wait(); - } - } - - /** - * Waits for the task to complete for timeout nanoseconds or throw - * TimeoutException if still not completed after that - * PRE: lock owned - */ - private void waitFor(long nanos) throws InterruptedException, TimeoutException { - if (nanos < 0) throw new IllegalArgumentException(); - if (isDone()) return; - long deadline = Utils.nanoTime() + nanos; - while (nanos > 0) { - TimeUnit.NANOSECONDS.timedWait(this, nanos); - if (isDone()) return; - nanos = deadline - Utils.nanoTime(); - } - throw new TimeoutException(); - } - - /** - * Gets the result of the task. - * - * PRE: task completed - * PRE: lock owned - */ - private Object getResult() throws ExecutionException { - if (state == CANCELLED) { - throw new CancellationException(); - } - if (exception != null) { - throw new ExecutionException(exception); - } - return result; - } - - // todo: consider - //public String toString() { - // return callable.toString(); - //} -} diff --git a/src/actors/scala/actors/threadpool/LinkedBlockingQueue.java b/src/actors/scala/actors/threadpool/LinkedBlockingQueue.java deleted file mode 100644 index 15f1085ec6..0000000000 --- a/src/actors/scala/actors/threadpool/LinkedBlockingQueue.java +++ /dev/null @@ -1,843 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.ReentrantLock; -import java.util.AbstractQueue; -import java.util.Collection; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * An optionally-bounded {@linkplain BlockingQueue blocking queue} based on - * linked nodes. - * This queue orders elements FIFO (first-in-first-out). - * The head of the queue is that element that has been on the - * queue the longest time. - * The tail of the queue is that element that has been on the - * queue the shortest time. New elements - * are inserted at the tail of the queue, and the queue retrieval - * operations obtain elements at the head of the queue. - * Linked queues typically have higher throughput than array-based queues but - * less predictable performance in most concurrent applications. - * - *

The optional capacity bound constructor argument serves as a - * way to prevent excessive queue expansion. The capacity, if unspecified, - * is equal to {@link Integer#MAX_VALUE}. Linked nodes are - * dynamically created upon each insertion unless this would bring the - * queue above capacity. - * - *

This class and its iterator implement all of the - * optional methods of the {@link Collection} and {@link - * Iterator} interfaces. - * - *

This class is a member of the - * - * Java Collections Framework. - * - * @since 1.5 - * @author Doug Lea - * @param the type of elements held in this collection - * - */ -public class LinkedBlockingQueue extends java.util.AbstractQueue - implements BlockingQueue, java.io.Serializable { - private static final long serialVersionUID = -6903933977591709194L; - - /* - * A variant of the "two lock queue" algorithm. The putLock gates - * entry to put (and offer), and has an associated condition for - * waiting puts. Similarly for the takeLock. The "count" field - * that they both rely on is maintained as an atomic to avoid - * needing to get both locks in most cases. Also, to minimize need - * for puts to get takeLock and vice-versa, cascading notifies are - * used. When a put notices that it has enabled at least one take, - * it signals taker. That taker in turn signals others if more - * items have been entered since the signal. And symmetrically for - * takes signalling puts. Operations such as remove(Object) and - * iterators acquire both locks. - * - * Visibility between writers and readers is provided as follows: - * - * Whenever an element is enqueued, the putLock is acquired and - * count updated. A subsequent reader guarantees visibility to the - * enqueued Node by either acquiring the putLock (via fullyLock) - * or by acquiring the takeLock, and then reading n = count.get(); - * this gives visibility to the first n items. - * - * To implement weakly consistent iterators, it appears we need to - * keep all Nodes GC-reachable from a predecessor dequeued Node. - * That would cause two problems: - * - allow a rogue Iterator to cause unbounded memory retention - * - cause cross-generational linking of old Nodes to new Nodes if - * a Node was tenured while live, which generational GCs have a - * hard time dealing with, causing repeated major collections. - * However, only non-deleted Nodes need to be reachable from - * dequeued Nodes, and reachability does not necessarily have to - * be of the kind understood by the GC. We use the trick of - * linking a Node that has just been dequeued to itself. Such a - * self-link implicitly means to advance to head.next. - */ - - /** - * Linked list node class - */ - static class Node { - E item; - - /** - * One of: - * - the real successor Node - * - this Node, meaning the successor is head.next - * - null, meaning there is no successor (this is the last node) - */ - Node next; - - Node(E x) { item = x; } - } - - /** The capacity bound, or Integer.MAX_VALUE if none */ - private final int capacity; - - /** Current number of elements */ - private final AtomicInteger count = new AtomicInteger(0); - - /** - * Head of linked list. - * Invariant: head.item == null - */ - private transient Node head; - - /** - * Tail of linked list. - * Invariant: last.next == null - */ - private transient Node last; - - /** Lock held by take, poll, etc */ - private final ReentrantLock takeLock = new ReentrantLock(); - - /** Wait queue for waiting takes */ - private final Condition notEmpty = takeLock.newCondition(); - - /** Lock held by put, offer, etc */ - private final ReentrantLock putLock = new ReentrantLock(); - - /** Wait queue for waiting puts */ - private final Condition notFull = putLock.newCondition(); - - /** - * Signals a waiting take. Called only from put/offer (which do not - * otherwise ordinarily lock takeLock.) - */ - private void signalNotEmpty() { - final ReentrantLock takeLock = this.takeLock; - takeLock.lock(); - try { - notEmpty.signal(); - } finally { - takeLock.unlock(); - } - } - - /** - * Signals a waiting put. Called only from take/poll. - */ - private void signalNotFull() { - final ReentrantLock putLock = this.putLock; - putLock.lock(); - try { - notFull.signal(); - } finally { - putLock.unlock(); - } - } - - /** - * Creates a node and links it at end of queue. - * - * @param x the item - */ - private void enqueue(E x) { - // assert putLock.isHeldByCurrentThread(); - // assert last.next == null; - last = last.next = new Node(x); - } - - /** - * Removes a node from head of queue. - * - * @return the node - */ - private E dequeue() { - // assert takeLock.isHeldByCurrentThread(); - // assert head.item == null; - Node h = head; - Node first = h.next; - h.next = h; // help GC - head = first; - E x = first.item; - first.item = null; - return x; - } - - /** - * Lock to prevent both puts and takes. - */ - void fullyLock() { - putLock.lock(); - takeLock.lock(); - } - - /** - * Unlock to allow both puts and takes. - */ - void fullyUnlock() { - takeLock.unlock(); - putLock.unlock(); - } - -// /** -// * Tells whether both locks are held by current thread. -// */ -// boolean isFullyLocked() { -// return (putLock.isHeldByCurrentThread() && -// takeLock.isHeldByCurrentThread()); -// } - - /** - * Creates a {@code LinkedBlockingQueue} with a capacity of - * {@link Integer#MAX_VALUE}. - */ - public LinkedBlockingQueue() { - this(Integer.MAX_VALUE); - } - - /** - * Creates a {@code LinkedBlockingQueue} with the given (fixed) capacity. - * - * @param capacity the capacity of this queue - * @throws IllegalArgumentException if {@code capacity} is not greater - * than zero - */ - public LinkedBlockingQueue(int capacity) { - if (capacity <= 0) throw new IllegalArgumentException(); - this.capacity = capacity; - last = head = new Node(null); - } - - /** - * Creates a {@code LinkedBlockingQueue} with a capacity of - * {@link Integer#MAX_VALUE}, initially containing the elements of the - * given collection, - * added in traversal order of the collection's iterator. - * - * @param c the collection of elements to initially contain - * @throws NullPointerException if the specified collection or any - * of its elements are null - */ - public LinkedBlockingQueue(Collection c) { - this(Integer.MAX_VALUE); - final ReentrantLock putLock = this.putLock; - putLock.lock(); // Never contended, but necessary for visibility - try { - int n = 0; - for (E e : c) { - if (e == null) - throw new NullPointerException(); - if (n == capacity) - throw new IllegalStateException("Queue full"); - enqueue(e); - ++n; - } - count.set(n); - } finally { - putLock.unlock(); - } - } - - - // this doc comment is overridden to remove the reference to collections - // greater in size than Integer.MAX_VALUE - /** - * Returns the number of elements in this queue. - * - * @return the number of elements in this queue - */ - public int size() { - return count.get(); - } - - // this doc comment is a modified copy of the inherited doc comment, - // without the reference to unlimited queues. - /** - * Returns the number of additional elements that this queue can ideally - * (in the absence of memory or resource constraints) accept without - * blocking. This is always equal to the initial capacity of this queue - * less the current {@code size} of this queue. - * - *

Note that you cannot always tell if an attempt to insert - * an element will succeed by inspecting {@code remainingCapacity} - * because it may be the case that another thread is about to - * insert or remove an element. - */ - public int remainingCapacity() { - return capacity - count.get(); - } - - /** - * Inserts the specified element at the tail of this queue, waiting if - * necessary for space to become available. - * - * @throws InterruptedException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - */ - public void put(E e) throws InterruptedException { - if (e == null) throw new NullPointerException(); - // Note: convention in all put/take/etc is to preset local var - // holding count negative to indicate failure unless set. - int c = -1; - final ReentrantLock putLock = this.putLock; - final AtomicInteger count = this.count; - putLock.lockInterruptibly(); - try { - /* - * Note that count is used in wait guard even though it is - * not protected by lock. This works because count can - * only decrease at this point (all other puts are shut - * out by lock), and we (or some other waiting put) are - * signalled if it ever changes from capacity. Similarly - * for all other uses of count in other wait guards. - */ - while (count.get() == capacity) { - notFull.await(); - } - enqueue(e); - c = count.getAndIncrement(); - if (c + 1 < capacity) - notFull.signal(); - } finally { - putLock.unlock(); - } - if (c == 0) - signalNotEmpty(); - } - - /** - * Inserts the specified element at the tail of this queue, waiting if - * necessary up to the specified wait time for space to become available. - * - * @return {@code true} if successful, or {@code false} if - * the specified waiting time elapses before space is available. - * @throws InterruptedException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - */ - public boolean offer(E e, long timeout, TimeUnit unit) - throws InterruptedException { - - if (e == null) throw new NullPointerException(); - long nanos = unit.toNanos(timeout); - int c = -1; - final ReentrantLock putLock = this.putLock; - final AtomicInteger count = this.count; - putLock.lockInterruptibly(); - try { - while (count.get() == capacity) { - if (nanos <= 0) - return false; - nanos = notFull.awaitNanos(nanos); - } - enqueue(e); - c = count.getAndIncrement(); - if (c + 1 < capacity) - notFull.signal(); - } finally { - putLock.unlock(); - } - if (c == 0) - signalNotEmpty(); - return true; - } - - /** - * Inserts the specified element at the tail of this queue if it is - * possible to do so immediately without exceeding the queue's capacity, - * returning {@code true} upon success and {@code false} if this queue - * is full. - * When using a capacity-restricted queue, this method is generally - * preferable to method {@link BlockingQueue#add add}, which can fail to - * insert an element only by throwing an exception. - * - * @throws NullPointerException if the specified element is null - */ - public boolean offer(E e) { - if (e == null) throw new NullPointerException(); - final AtomicInteger count = this.count; - if (count.get() == capacity) - return false; - int c = -1; - final ReentrantLock putLock = this.putLock; - putLock.lock(); - try { - if (count.get() < capacity) { - enqueue(e); - c = count.getAndIncrement(); - if (c + 1 < capacity) - notFull.signal(); - } - } finally { - putLock.unlock(); - } - if (c == 0) - signalNotEmpty(); - return c >= 0; - } - - - public E take() throws InterruptedException { - E x; - int c = -1; - final AtomicInteger count = this.count; - final ReentrantLock takeLock = this.takeLock; - takeLock.lockInterruptibly(); - try { - while (count.get() == 0) { - notEmpty.await(); - } - x = dequeue(); - c = count.getAndDecrement(); - if (c > 1) - notEmpty.signal(); - } finally { - takeLock.unlock(); - } - if (c == capacity) - signalNotFull(); - return x; - } - - public E poll(long timeout, TimeUnit unit) throws InterruptedException { - E x = null; - int c = -1; - long nanos = unit.toNanos(timeout); - final AtomicInteger count = this.count; - final ReentrantLock takeLock = this.takeLock; - takeLock.lockInterruptibly(); - try { - while (count.get() == 0) { - if (nanos <= 0) - return null; - nanos = notEmpty.awaitNanos(nanos); - } - x = dequeue(); - c = count.getAndDecrement(); - if (c > 1) - notEmpty.signal(); - } finally { - takeLock.unlock(); - } - if (c == capacity) - signalNotFull(); - return x; - } - - public E poll() { - final AtomicInteger count = this.count; - if (count.get() == 0) - return null; - E x = null; - int c = -1; - final ReentrantLock takeLock = this.takeLock; - takeLock.lock(); - try { - if (count.get() > 0) { - x = dequeue(); - c = count.getAndDecrement(); - if (c > 1) - notEmpty.signal(); - } - } finally { - takeLock.unlock(); - } - if (c == capacity) - signalNotFull(); - return x; - } - - public E peek() { - if (count.get() == 0) - return null; - final ReentrantLock takeLock = this.takeLock; - takeLock.lock(); - try { - Node first = head.next; - if (first == null) - return null; - else - return first.item; - } finally { - takeLock.unlock(); - } - } - - /** - * Unlinks interior Node p with predecessor trail. - */ - void unlink(Node p, Node trail) { - // assert isFullyLocked(); - // p.next is not changed, to allow iterators that are - // traversing p to maintain their weak-consistency guarantee. - p.item = null; - trail.next = p.next; - if (last == p) - last = trail; - if (count.getAndDecrement() == capacity) - notFull.signal(); - } - - /** - * Removes a single instance of the specified element from this queue, - * if it is present. More formally, removes an element {@code e} such - * that {@code o.equals(e)}, if this queue contains one or more such - * elements. - * Returns {@code true} if this queue contained the specified element - * (or equivalently, if this queue changed as a result of the call). - * - * @param o element to be removed from this queue, if present - * @return {@code true} if this queue changed as a result of the call - */ - public boolean remove(Object o) { - if (o == null) return false; - fullyLock(); - try { - for (Node trail = head, p = trail.next; - p != null; - trail = p, p = p.next) { - if (o.equals(p.item)) { - unlink(p, trail); - return true; - } - } - return false; - } finally { - fullyUnlock(); - } - } - - /** - * Returns an array containing all of the elements in this queue, in - * proper sequence. - * - *

The returned array will be "safe" in that no references to it are - * maintained by this queue. (In other words, this method must allocate - * a new array). The caller is thus free to modify the returned array. - * - *

This method acts as bridge between array-based and collection-based - * APIs. - * - * @return an array containing all of the elements in this queue - */ - public Object[] toArray() { - fullyLock(); - try { - int size = count.get(); - Object[] a = new Object[size]; - int k = 0; - for (Node p = head.next; p != null; p = p.next) - a[k++] = p.item; - return a; - } finally { - fullyUnlock(); - } - } - - /** - * Returns an array containing all of the elements in this queue, in - * proper sequence; the runtime type of the returned array is that of - * the specified array. If the queue fits in the specified array, it - * is returned therein. Otherwise, a new array is allocated with the - * runtime type of the specified array and the size of this queue. - * - *

If this queue fits in the specified array with room to spare - * (i.e., the array has more elements than this queue), the element in - * the array immediately following the end of the queue is set to - * {@code null}. - * - *

Like the {@link #toArray()} method, this method acts as bridge between - * array-based and collection-based APIs. Further, this method allows - * precise control over the runtime type of the output array, and may, - * under certain circumstances, be used to save allocation costs. - * - *

Suppose {@code x} is a queue known to contain only strings. - * The following code can be used to dump the queue into a newly - * allocated array of {@code String}: - * - *

-     *     String[] y = x.toArray(new String[0]);
- * - * Note that {@code toArray(new Object[0])} is identical in function to - * {@code toArray()}. - * - * @param a the array into which the elements of the queue are to - * be stored, if it is big enough; otherwise, a new array of the - * same runtime type is allocated for this purpose - * @return an array containing all of the elements in this queue - * @throws ArrayStoreException if the runtime type of the specified array - * is not a supertype of the runtime type of every element in - * this queue - * @throws NullPointerException if the specified array is null - */ - @SuppressWarnings("unchecked") - public T[] toArray(T[] a) { - fullyLock(); - try { - int size = count.get(); - if (a.length < size) - a = (T[])java.lang.reflect.Array.newInstance - (a.getClass().getComponentType(), size); - - int k = 0; - for (Node p = head.next; p != null; p = p.next) - a[k++] = (T)p.item; - if (a.length > k) - a[k] = null; - return a; - } finally { - fullyUnlock(); - } - } - - public String toString() { - fullyLock(); - try { - return super.toString(); - } finally { - fullyUnlock(); - } - } - - /** - * Atomically removes all of the elements from this queue. - * The queue will be empty after this call returns. - */ - public void clear() { - fullyLock(); - try { - for (Node p, h = head; (p = h.next) != null; h = p) { - h.next = h; - p.item = null; - } - head = last; - // assert head.item == null && head.next == null; - if (count.getAndSet(0) == capacity) - notFull.signal(); - } finally { - fullyUnlock(); - } - } - - /** - * @throws UnsupportedOperationException {@inheritDoc} - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - * @throws IllegalArgumentException {@inheritDoc} - */ - public int drainTo(Collection c) { - return drainTo(c, Integer.MAX_VALUE); - } - - /** - * @throws UnsupportedOperationException {@inheritDoc} - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - * @throws IllegalArgumentException {@inheritDoc} - */ - public int drainTo(Collection c, int maxElements) { - if (c == null) - throw new NullPointerException(); - if (c == this) - throw new IllegalArgumentException(); - boolean signalNotFull = false; - final ReentrantLock takeLock = this.takeLock; - takeLock.lock(); - try { - int n = Math.min(maxElements, count.get()); - // count.get provides visibility to first n Nodes - Node h = head; - int i = 0; - try { - while (i < n) { - Node p = h.next; - c.add(p.item); - p.item = null; - h.next = h; - h = p; - ++i; - } - return n; - } finally { - // Restore invariants even if c.add() threw - if (i > 0) { - // assert h.item == null; - head = h; - signalNotFull = (count.getAndAdd(-i) == capacity); - } - } - } finally { - takeLock.unlock(); - if (signalNotFull) - signalNotFull(); - } - } - - /** - * Returns an iterator over the elements in this queue in proper sequence. - * The returned {@code Iterator} is a "weakly consistent" iterator that - * will never throw {@link java.util.ConcurrentModificationException - * ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed to) - * reflect any modifications subsequent to construction. - * - * @return an iterator over the elements in this queue in proper sequence - */ - public Iterator iterator() { - return new Itr(); - } - - private class Itr implements Iterator { - /* - * Basic weakly-consistent iterator. At all times hold the next - * item to hand out so that if hasNext() reports true, we will - * still have it to return even if lost race with a take etc. - */ - private Node current; - private Node lastRet; - private E currentElement; - - Itr() { - fullyLock(); - try { - current = head.next; - if (current != null) - currentElement = current.item; - } finally { - fullyUnlock(); - } - } - - public boolean hasNext() { - return current != null; - } - - /** - * Returns the next live successor of p, or null if no such. - * - * Unlike other traversal methods, iterators need to handle both: - * - dequeued nodes (p.next == p) - * - (possibly multiple) interior removed nodes (p.item == null) - */ - private Node nextNode(Node p) { - for (;;) { - Node s = p.next; - if (s == p) - return head.next; - if (s == null || s.item != null) - return s; - p = s; - } - } - - public E next() { - fullyLock(); - try { - if (current == null) - throw new NoSuchElementException(); - E x = currentElement; - lastRet = current; - current = nextNode(current); - currentElement = (current == null) ? null : current.item; - return x; - } finally { - fullyUnlock(); - } - } - - public void remove() { - if (lastRet == null) - throw new IllegalStateException(); - fullyLock(); - try { - Node node = lastRet; - lastRet = null; - for (Node trail = head, p = trail.next; - p != null; - trail = p, p = p.next) { - if (p == node) { - unlink(p, trail); - break; - } - } - } finally { - fullyUnlock(); - } - } - } - - /** - * Save the state to a stream (that is, serialize it). - * - * @serialData The capacity is emitted (int), followed by all of - * its elements (each an {@code Object}) in the proper order, - * followed by a null - * @param s the stream - */ - private void writeObject(java.io.ObjectOutputStream s) - throws java.io.IOException { - - fullyLock(); - try { - // Write out any hidden stuff, plus capacity - s.defaultWriteObject(); - - // Write out all elements in the proper order. - for (Node p = head.next; p != null; p = p.next) - s.writeObject(p.item); - - // Use trailing null as sentinel - s.writeObject(null); - } finally { - fullyUnlock(); - } - } - - /** - * Reconstitute this queue instance from a stream (that is, - * deserialize it). - * - * @param s the stream - */ - private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException { - // Read in capacity, and any hidden stuff - s.defaultReadObject(); - - count.set(0); - last = head = new Node(null); - - // Read in all elements and place in queue - for (;;) { - @SuppressWarnings("unchecked") - E item = (E)s.readObject(); - if (item == null) - break; - add(item); - } - } -} diff --git a/src/actors/scala/actors/threadpool/Perf.java b/src/actors/scala/actors/threadpool/Perf.java deleted file mode 100644 index 0f262b444f..0000000000 --- a/src/actors/scala/actors/threadpool/Perf.java +++ /dev/null @@ -1,28 +0,0 @@ -package scala.actors.threadpool; - -/** - * Compilation stub for pre-1.4.2 JREs. Thanks to it, the whole backport - * package compiles and works with 1.4.2 as well as wih earlier JREs, and takes - * advantage of native Perf class when running on 1.4.2 while seamlessly - * falling back to System.currentTimeMillis() on previous JREs. This class - * should NOT be included in the binary distribution of backport. - * - * @author Dawid Kurzyniec - * @version 1.0 - */ -public final class Perf { - - private static final Perf perf = new Perf(); - - public static Perf getPerf() { return perf; } - - private Perf() {} - - public long highResCounter() { - return System.currentTimeMillis(); - } - - public long highResFrequency() { - return 1000L; - } -} diff --git a/src/actors/scala/actors/threadpool/Queue.java b/src/actors/scala/actors/threadpool/Queue.java deleted file mode 100644 index f952e9d94c..0000000000 --- a/src/actors/scala/actors/threadpool/Queue.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -import java.util.Collection; - -/** - * A collection designed for holding elements prior to processing. - * Besides basic {@link java.util.Collection Collection} operations, - * queues provide additional insertion, extraction, and inspection - * operations. Each of these methods exists in two forms: one throws - * an exception if the operation fails, the other returns a special - * value (either null or false, depending on the - * operation). The latter form of the insert operation is designed - * specifically for use with capacity-restricted Queue - * implementations; in most implementations, insert operations cannot - * fail. - * - *

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Throws exceptionReturns special value
Insert{@link #add add(e)}{@link #offer offer(e)}
Remove{@link #remove remove()}{@link #poll poll()}
Examine{@link #element element()}{@link #peek peek()}
- * - *

Queues typically, but do not necessarily, order elements in a - * FIFO (first-in-first-out) manner. Among the exceptions are - * priority queues, which order elements according to a supplied - * comparator, or the elements' natural ordering, and LIFO queues (or - * stacks) which order the elements LIFO (last-in-first-out). - * Whatever the ordering used, the head of the queue is that - * element which would be removed by a call to {@link #remove() } or - * {@link #poll()}. In a FIFO queue, all new elements are inserted at - * the tail of the queue. Other kinds of queues may use - * different placement rules. Every Queue implementation - * must specify its ordering properties. - * - *

The {@link #offer offer} method inserts an element if possible, - * otherwise returning false. This differs from the {@link - * java.util.Collection#add Collection.add} method, which can fail to - * add an element only by throwing an unchecked exception. The - * offer method is designed for use when failure is a normal, - * rather than exceptional occurrence, for example, in fixed-capacity - * (or "bounded") queues. - * - *

The {@link #remove()} and {@link #poll()} methods remove and - * return the head of the queue. - * Exactly which element is removed from the queue is a - * function of the queue's ordering policy, which differs from - * implementation to implementation. The remove() and - * poll() methods differ only in their behavior when the - * queue is empty: the remove() method throws an exception, - * while the poll() method returns null. - * - *

The {@link #element()} and {@link #peek()} methods return, but do - * not remove, the head of the queue. - * - *

The Queue interface does not define the blocking queue - * methods, which are common in concurrent programming. These methods, - * which wait for elements to appear or for space to become available, are - * defined in the {@link edu.emory.mathcs.backport.java.util.concurrent.BlockingQueue} interface, which - * extends this interface. - * - *

Queue implementations generally do not allow insertion - * of null elements, although some implementations, such as - * {@link LinkedList}, do not prohibit insertion of null. - * Even in the implementations that permit it, null should - * not be inserted into a Queue, as null is also - * used as a special return value by the poll method to - * indicate that the queue contains no elements. - * - *

Queue implementations generally do not define - * element-based versions of methods equals and - * hashCode but instead inherit the identity based versions - * from class Object, because element-based equality is not - * always well-defined for queues with the same elements but different - * ordering properties. - * - * - *

This interface is a member of the - * - * Java Collections Framework. - * - * @see java.util.Collection - * @see LinkedList - * @see PriorityQueue - * @see edu.emory.mathcs.backport.java.util.concurrent.LinkedBlockingQueue - * @see edu.emory.mathcs.backport.java.util.concurrent.BlockingQueue - * @see edu.emory.mathcs.backport.java.util.concurrent.ArrayBlockingQueue - * @see edu.emory.mathcs.backport.java.util.concurrent.LinkedBlockingQueue - * @see edu.emory.mathcs.backport.java.util.concurrent.PriorityBlockingQueue - * @since 1.5 - * @author Doug Lea - */ -public interface Queue extends Collection { - /** - * Inserts the specified element into this queue if it is possible to do so - * immediately without violating capacity restrictions, returning - * true upon success and throwing an IllegalStateException - * if no space is currently available. - * - * @param e the element to add - * @return true (as specified by {@link Collection#add}) - * @throws IllegalStateException if the element cannot be added at this - * time due to capacity restrictions - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this queue - * @throws NullPointerException if the specified element is null and - * this queue not permit null elements - * @throws IllegalArgumentException if some property of this element - * prevents it from being added to this queue - */ - boolean add(Object e); - - /** - * Inserts the specified element into this queue if it is possible to do - * so immediately without violating capacity restrictions. - * When using a capacity-restricted queue, this method is generally - * preferable to {@link #add}, which can fail to insert an element only - * by throwing an exception. - * - * @param e the element to add - * @return true if the element was added to this queue, else - * false - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this queue - * @throws NullPointerException if the specified element is null and - * this queue does not permit null elements - * @throws IllegalArgumentException if some property of this element - * prevents it from being added to this queue - */ - boolean offer(Object e); - - /** - * Retrieves and removes the head of this queue. This method differs - * from {@link #poll poll} only in that it throws an exception if this - * queue is empty. - * is empty. - * - * @return the head of this queue - * @throws NoSuchElementException if this queue is empty - */ - Object remove(); - - /** - * Retrieves and removes the head of this queue, - * or returns null if this queue is empty. - * - * @return the head of this queue, or null if this queue is empty - */ - Object poll(); - - /** - * Retrieves, but does not remove, the head of this queue. This method - * differs from {@link #peek peek} only in that it throws an exception - * if this queue is empty. - * - * @return the head of this queue - * @throws NoSuchElementException if this queue is empty - */ - Object element(); - - /** - * Retrieves, but does not remove, the head of this queue, - * or returns null if this queue is empty. - * - * @return the head of this queue, or null if this queue is empty - */ - Object peek(); -} diff --git a/src/actors/scala/actors/threadpool/RejectedExecutionException.java b/src/actors/scala/actors/threadpool/RejectedExecutionException.java deleted file mode 100644 index 1b61d35974..0000000000 --- a/src/actors/scala/actors/threadpool/RejectedExecutionException.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -/** - * Exception thrown by an {@link Executor} when a task cannot be - * accepted for execution. - * - * @since 1.5 - * @author Doug Lea - */ -public class RejectedExecutionException extends RuntimeException { - private static final long serialVersionUID = -375805702767069545L; - - /** - * Constructs a RejectedExecutionException with no detail message. - * The cause is not initialized, and may subsequently be - * initialized by a call to {@link #initCause(Throwable) initCause}. - */ - public RejectedExecutionException() { } - - /** - * Constructs a RejectedExecutionException with the - * specified detail message. The cause is not initialized, and may - * subsequently be initialized by a call to {@link - * #initCause(Throwable) initCause}. - * - * @param message the detail message - */ - public RejectedExecutionException(String message) { - super(message); - } - - /** - * Constructs a RejectedExecutionException with the - * specified detail message and cause. - * - * @param message the detail message - * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method) - */ - public RejectedExecutionException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Constructs a RejectedExecutionException with the - * specified cause. The detail message is set to:

 (cause ==
-     * null ? null : cause.toString())
(which typically contains - * the class and detail message of cause). - * - * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method) - */ - public RejectedExecutionException(Throwable cause) { - super(cause); - } -} diff --git a/src/actors/scala/actors/threadpool/RejectedExecutionHandler.java b/src/actors/scala/actors/threadpool/RejectedExecutionHandler.java deleted file mode 100644 index 86e6d18a40..0000000000 --- a/src/actors/scala/actors/threadpool/RejectedExecutionHandler.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -/** - * A handler for tasks that cannot be executed by a {@link ThreadPoolExecutor}. - * - * @since 1.5 - * @author Doug Lea - */ -public interface RejectedExecutionHandler { - - /** - * Method that may be invoked by a {@link ThreadPoolExecutor} when - * {@link ThreadPoolExecutor#execute execute} cannot accept a - * task. This may occur when no more threads or queue slots are - * available because their bounds would be exceeded, or upon - * shutdown of the Executor. - * - *

In the absence of other alternatives, the method may throw - * an unchecked {@link RejectedExecutionException}, which will be - * propagated to the caller of {@code execute}. - * - * @param r the runnable task requested to be executed - * @param executor the executor attempting to execute this task - * @throws RejectedExecutionException if there is no remedy - */ - - void rejectedExecution(Runnable r, ThreadPoolExecutor executor); -} diff --git a/src/actors/scala/actors/threadpool/RunnableFuture.java b/src/actors/scala/actors/threadpool/RunnableFuture.java deleted file mode 100644 index bbd63a2d92..0000000000 --- a/src/actors/scala/actors/threadpool/RunnableFuture.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -/** - * A {@link Future} that is {@link Runnable}. Successful execution of - * the run method causes completion of the Future - * and allows access to its results. - * @see FutureTask - * @see Executor - * @since 1.6 - * @author Doug Lea - */ -public interface RunnableFuture extends Runnable, Future { - /** - * Sets this Future to the result of its computation - * unless it has been cancelled. - */ - void run(); -} diff --git a/src/actors/scala/actors/threadpool/SynchronousQueue.java b/src/actors/scala/actors/threadpool/SynchronousQueue.java deleted file mode 100644 index 739b0043dd..0000000000 --- a/src/actors/scala/actors/threadpool/SynchronousQueue.java +++ /dev/null @@ -1,833 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; -import scala.actors.threadpool.locks.*; -//import edu.emory.mathcs.backport.java.util.*; -import java.util.Collection; -import java.util.Iterator; -import scala.actors.threadpool.helpers.Utils; -import java.util.NoSuchElementException; - -/** - * A {@linkplain BlockingQueue blocking queue} in which each insert - * operation must wait for a corresponding remove operation by another - * thread, and vice versa. A synchronous queue does not have any - * internal capacity, not even a capacity of one. You cannot - * peek at a synchronous queue because an element is only - * present when you try to remove it; you cannot insert an element - * (using any method) unless another thread is trying to remove it; - * you cannot iterate as there is nothing to iterate. The - * head of the queue is the element that the first queued - * inserting thread is trying to add to the queue; if there is no such - * queued thread then no element is available for removal and - * poll() will return null. For purposes of other - * Collection methods (for example contains), a - * SynchronousQueue acts as an empty collection. This queue - * does not permit null elements. - * - *

Synchronous queues are similar to rendezvous channels used in - * CSP and Ada. They are well suited for handoff designs, in which an - * object running in one thread must sync up with an object running - * in another thread in order to hand it some information, event, or - * task. - * - *

This class supports an optional fairness policy for ordering - * waiting producer and consumer threads. By default, this ordering - * is not guaranteed. However, a queue constructed with fairness set - * to true grants threads access in FIFO order. Fairness - * generally decreases throughput but reduces variability and avoids - * starvation. - * - *

This class and its iterator implement all of the - * optional methods of the {@link Collection} and {@link - * Iterator} interfaces. - * - *

This class is a member of the - * - * Java Collections Framework. - * - * @since 1.5 - * @author Doug Lea - */ -public class SynchronousQueue extends AbstractQueue - implements BlockingQueue, java.io.Serializable { - private static final long serialVersionUID = -3223113410248163686L; - - /* - This implementation divides actions into two cases for puts: - - * An arriving producer that does not already have a waiting consumer - creates a node holding item, and then waits for a consumer to take it. - * An arriving producer that does already have a waiting consumer fills - the slot node created by the consumer, and notifies it to continue. - - And symmetrically, two for takes: - - * An arriving consumer that does not already have a waiting producer - creates an empty slot node, and then waits for a producer to fill it. - * An arriving consumer that does already have a waiting producer takes - item from the node created by the producer, and notifies it to continue. - - When a put or take waiting for the actions of its counterpart - aborts due to interruption or timeout, it marks the node - it created as "CANCELLED", which causes its counterpart to retry - the entire put or take sequence. - - This requires keeping two simple queues, waitingProducers and - waitingConsumers. Each of these can be FIFO (preserves fairness) - or LIFO (improves throughput). - */ - - /** Lock protecting both wait queues */ - private final ReentrantLock qlock; - /** Queue holding waiting puts */ - private final WaitQueue waitingProducers; - /** Queue holding waiting takes */ - private final WaitQueue waitingConsumers; - - /** - * Creates a SynchronousQueue with nonfair access policy. - */ - public SynchronousQueue() { - this(false); - } - - /** - * Creates a SynchronousQueue with specified fairness policy. - * @param fair if true, threads contend in FIFO order for access; - * otherwise the order is unspecified. - */ - public SynchronousQueue(boolean fair) { - if (fair) { - qlock = new ReentrantLock(true); - waitingProducers = new FifoWaitQueue(); - waitingConsumers = new FifoWaitQueue(); - } - else { - qlock = new ReentrantLock(); - waitingProducers = new LifoWaitQueue(); - waitingConsumers = new LifoWaitQueue(); - } - } - - /** - * Queue to hold waiting puts/takes; specialized to Fifo/Lifo below. - * These queues have all transient fields, but are serializable - * in order to recover fairness settings when deserialized. - */ - static abstract class WaitQueue implements java.io.Serializable { - /** Creates, adds, and returns node for x. */ - abstract Node enq(Object x); - /** Removes and returns node, or null if empty. */ - abstract Node deq(); - /** Removes a cancelled node to avoid garbage retention. */ - abstract void unlink(Node node); - /** Returns true if a cancelled node might be on queue. */ - abstract boolean shouldUnlink(Node node); - } - - /** - * FIFO queue to hold waiting puts/takes. - */ - static final class FifoWaitQueue extends WaitQueue implements java.io.Serializable { - private static final long serialVersionUID = -3623113410248163686L; - private transient Node head; - private transient Node last; - - Node enq(Object x) { - Node p = new Node(x); - if (last == null) - last = head = p; - else - last = last.next = p; - return p; - } - - Node deq() { - Node p = head; - if (p != null) { - if ((head = p.next) == null) - last = null; - p.next = null; - } - return p; - } - - boolean shouldUnlink(Node node) { - return (node == last || node.next != null); - } - - void unlink(Node node) { - Node p = head; - Node trail = null; - while (p != null) { - if (p == node) { - Node next = p.next; - if (trail == null) - head = next; - else - trail.next = next; - if (last == node) - last = trail; - break; - } - trail = p; - p = p.next; - } - } - } - - /** - * LIFO queue to hold waiting puts/takes. - */ - static final class LifoWaitQueue extends WaitQueue implements java.io.Serializable { - private static final long serialVersionUID = -3633113410248163686L; - private transient Node head; - - Node enq(Object x) { - return head = new Node(x, head); - } - - Node deq() { - Node p = head; - if (p != null) { - head = p.next; - p.next = null; - } - return p; - } - - boolean shouldUnlink(Node node) { - // Return false if already dequeued or is bottom node (in which - // case we might retain at most one garbage node) - return (node == head || node.next != null); - } - - void unlink(Node node) { - Node p = head; - Node trail = null; - while (p != null) { - if (p == node) { - Node next = p.next; - if (trail == null) - head = next; - else - trail.next = next; - break; - } - trail = p; - p = p.next; - } - } - } - - /** - * Unlinks the given node from consumer queue. Called by cancelled - * (timeout, interrupt) waiters to avoid garbage retention in the - * absence of producers. - */ - private void unlinkCancelledConsumer(Node node) { - // Use a form of double-check to avoid unnecessary locking and - // traversal. The first check outside lock might - // conservatively report true. - if (waitingConsumers.shouldUnlink(node)) { - qlock.lock(); - try { - if (waitingConsumers.shouldUnlink(node)) - waitingConsumers.unlink(node); - } finally { - qlock.unlock(); - } - } - } - - /** - * Unlinks the given node from producer queue. Symmetric - * to unlinkCancelledConsumer. - */ - private void unlinkCancelledProducer(Node node) { - if (waitingProducers.shouldUnlink(node)) { - qlock.lock(); - try { - if (waitingProducers.shouldUnlink(node)) - waitingProducers.unlink(node); - } finally { - qlock.unlock(); - } - } - } - - /** - * Nodes each maintain an item and handle waits and signals for - * getting and setting it. The class extends - * AbstractQueuedSynchronizer to manage blocking, using AQS state - * 0 for waiting, 1 for ack, -1 for cancelled. - */ - static final class Node implements java.io.Serializable { - private static final long serialVersionUID = -3223113410248163686L; - - /** Synchronization state value representing that node acked */ - private static final int ACK = 1; - /** Synchronization state value representing that node cancelled */ - private static final int CANCEL = -1; - - int state = 0; - - /** The item being transferred */ - Object item; - /** Next node in wait queue */ - Node next; - - /** Creates a node with initial item */ - Node(Object x) { item = x; } - - /** Creates a node with initial item and next */ - Node(Object x, Node n) { item = x; next = n; } - - /** - * Takes item and nulls out field (for sake of GC) - * - * PRE: lock owned - */ - private Object extract() { - Object x = item; - item = null; - return x; - } - - /** - * Tries to cancel on interrupt; if so rethrowing, - * else setting interrupt state - * - * PRE: lock owned - */ - private void checkCancellationOnInterrupt(InterruptedException ie) - throws InterruptedException - { - if (state == 0) { - state = CANCEL; - notify(); - throw ie; - } - Thread.currentThread().interrupt(); - } - - /** - * Fills in the slot created by the consumer and signal consumer to - * continue. - */ - synchronized boolean setItem(Object x) { - if (state != 0) return false; - item = x; - state = ACK; - notify(); - return true; - } - - /** - * Removes item from slot created by producer and signal producer - * to continue. - */ - synchronized Object getItem() { - if (state != 0) return null; - state = ACK; - notify(); - return extract(); - } - - /** - * Waits for a consumer to take item placed by producer. - */ - synchronized void waitForTake() throws InterruptedException { - try { - while (state == 0) wait(); - } catch (InterruptedException ie) { - checkCancellationOnInterrupt(ie); - } - } - - /** - * Waits for a producer to put item placed by consumer. - */ - synchronized Object waitForPut() throws InterruptedException { - try { - while (state == 0) wait(); - } catch (InterruptedException ie) { - checkCancellationOnInterrupt(ie); - } - return extract(); - } - - private boolean attempt(long nanos) throws InterruptedException { - if (state != 0) return true; - if (nanos <= 0) { - state = CANCEL; - notify(); - return false; - } - long deadline = Utils.nanoTime() + nanos; - while (true) { - TimeUnit.NANOSECONDS.timedWait(this, nanos); - if (state != 0) return true; - nanos = deadline - Utils.nanoTime(); - if (nanos <= 0) { - state = CANCEL; - notify(); - return false; - } - } - } - - /** - * Waits for a consumer to take item placed by producer or time out. - */ - synchronized boolean waitForTake(long nanos) throws InterruptedException { - try { - if (!attempt(nanos)) return false; - } catch (InterruptedException ie) { - checkCancellationOnInterrupt(ie); - } - return true; - } - - /** - * Waits for a producer to put item placed by consumer, or time out. - */ - synchronized Object waitForPut(long nanos) throws InterruptedException { - try { - if (!attempt(nanos)) return null; - } catch (InterruptedException ie) { - checkCancellationOnInterrupt(ie); - } - return extract(); - } - } - - /** - * Adds the specified element to this queue, waiting if necessary for - * another thread to receive it. - * - * @throws InterruptedException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - */ - public void put(Object e) throws InterruptedException { - if (e == null) throw new NullPointerException(); - final ReentrantLock qlock = this.qlock; - - for (;;) { - Node node; - boolean mustWait; - if (Thread.interrupted()) throw new InterruptedException(); - qlock.lock(); - try { - node = waitingConsumers.deq(); - if ( (mustWait = (node == null)) ) - node = waitingProducers.enq(e); - } finally { - qlock.unlock(); - } - - if (mustWait) { - try { - node.waitForTake(); - return; - } catch (InterruptedException ex) { - unlinkCancelledProducer(node); - throw ex; - } - } - - else if (node.setItem(e)) - return; - - // else consumer cancelled, so retry - } - } - - /** - * Inserts the specified element into this queue, waiting if necessary - * up to the specified wait time for another thread to receive it. - * - * @return true if successful, or false if the - * specified waiting time elapses before a consumer appears. - * @throws InterruptedException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - */ - public boolean offer(Object e, long timeout, TimeUnit unit) throws InterruptedException { - if (e == null) throw new NullPointerException(); - long nanos = unit.toNanos(timeout); - final ReentrantLock qlock = this.qlock; - for (;;) { - Node node; - boolean mustWait; - if (Thread.interrupted()) throw new InterruptedException(); - qlock.lock(); - try { - node = waitingConsumers.deq(); - if ( (mustWait = (node == null)) ) - node = waitingProducers.enq(e); - } finally { - qlock.unlock(); - } - - if (mustWait) { - try { - boolean x = node.waitForTake(nanos); - if (!x) - unlinkCancelledProducer(node); - return x; - } catch (InterruptedException ex) { - unlinkCancelledProducer(node); - throw ex; - } - } - - else if (node.setItem(e)) - return true; - - // else consumer cancelled, so retry - } - } - - /** - * Retrieves and removes the head of this queue, waiting if necessary - * for another thread to insert it. - * - * @return the head of this queue - * @throws InterruptedException {@inheritDoc} - */ - public Object take() throws InterruptedException { - final ReentrantLock qlock = this.qlock; - for (;;) { - Node node; - boolean mustWait; - - if (Thread.interrupted()) throw new InterruptedException(); - qlock.lock(); - try { - node = waitingProducers.deq(); - if ( (mustWait = (node == null)) ) - node = waitingConsumers.enq(null); - } finally { - qlock.unlock(); - } - - if (mustWait) { - try { - Object x = node.waitForPut(); - return (Object)x; - } catch (InterruptedException ex) { - unlinkCancelledConsumer(node); - throw ex; - } - } - else { - Object x = node.getItem(); - if (x != null) - return (Object)x; - // else cancelled, so retry - } - } - } - - /** - * Retrieves and removes the head of this queue, waiting - * if necessary up to the specified wait time, for another thread - * to insert it. - * - * @return the head of this queue, or null if the - * specified waiting time elapses before an element is present. - * @throws InterruptedException {@inheritDoc} - */ - public Object poll(long timeout, TimeUnit unit) throws InterruptedException { - long nanos = unit.toNanos(timeout); - final ReentrantLock qlock = this.qlock; - - for (;;) { - Node node; - boolean mustWait; - - if (Thread.interrupted()) throw new InterruptedException(); - qlock.lock(); - try { - node = waitingProducers.deq(); - if ( (mustWait = (node == null)) ) - node = waitingConsumers.enq(null); - } finally { - qlock.unlock(); - } - - if (mustWait) { - try { - Object x = node.waitForPut(nanos); - if (x == null) - unlinkCancelledConsumer(node); - return (Object)x; - } catch (InterruptedException ex) { - unlinkCancelledConsumer(node); - throw ex; - } - } - else { - Object x = node.getItem(); - if (x != null) - return (Object)x; - // else cancelled, so retry - } - } - } - - // Untimed nonblocking versions - - /** - * Inserts the specified element into this queue, if another thread is - * waiting to receive it. - * - * @param e the element to add - * @return true if the element was added to this queue, else - * false - * @throws NullPointerException if the specified element is null - */ - public boolean offer(Object e) { - if (e == null) throw new NullPointerException(); - final ReentrantLock qlock = this.qlock; - - for (;;) { - Node node; - qlock.lock(); - try { - node = waitingConsumers.deq(); - } finally { - qlock.unlock(); - } - if (node == null) - return false; - - else if (node.setItem(e)) - return true; - // else retry - } - } - - /** - * Retrieves and removes the head of this queue, if another thread - * is currently making an element available. - * - * @return the head of this queue, or null if no - * element is available. - */ - public Object poll() { - final ReentrantLock qlock = this.qlock; - for (;;) { - Node node; - qlock.lock(); - try { - node = waitingProducers.deq(); - } finally { - qlock.unlock(); - } - if (node == null) - return null; - - else { - Object x = node.getItem(); - if (x != null) - return (Object)x; - // else retry - } - } - } - - /** - * Always returns true. - * A SynchronousQueue has no internal capacity. - * - * @return true - */ - public boolean isEmpty() { - return true; - } - - /** - * Always returns zero. - * A SynchronousQueue has no internal capacity. - * - * @return zero - */ - public int size() { - return 0; - } - - /** - * Always returns zero. - * A SynchronousQueue has no internal capacity. - * - * @return zero - */ - public int remainingCapacity() { - return 0; - } - - /** - * Does nothing. - * A SynchronousQueue has no internal capacity. - */ - public void clear() {} - - /** - * Always returns false. - * A SynchronousQueue has no internal capacity. - * - * @param o object to be checked for containment in this queue - * @return false - */ - public boolean contains(Object o) { - return false; - } - - /** - * Always returns false. - * A SynchronousQueue has no internal capacity. - * - * @param o the element to remove - * @return false - */ - public boolean remove(Object o) { - return false; - } - - /** - * Returns false unless the given collection is empty. - * A SynchronousQueue has no internal capacity. - * - * @param c the collection - * @return false unless the given collection is empty - * @throws NullPointerException if the specified collection is null - */ - public boolean containsAll(Collection c) { - return c.isEmpty(); - } - - /** - * Always returns false. - * A SynchronousQueue has no internal capacity. - * - * @param c the collection - * @return false - */ - public boolean removeAll(Collection c) { - return false; - } - - /** - * Always returns false. - * A SynchronousQueue has no internal capacity. - * - * @param c the collection - * @return false - */ - public boolean retainAll(Collection c) { - return false; - } - - /** - * Always returns null. - * A SynchronousQueue does not return elements - * unless actively waited on. - * - * @return null - */ - public Object peek() { - return null; - } - - - static class EmptyIterator implements Iterator { - public boolean hasNext() { - return false; - } - public Object next() { - throw new NoSuchElementException(); - } - public void remove() { - throw new IllegalStateException(); - } - } - - /** - * Returns an empty iterator in which hasNext always returns - * false. - * - * @return an empty iterator - */ - public Iterator iterator() { - return new EmptyIterator(); - } - - - /** - * Returns a zero-length array. - * @return a zero-length array - */ - public Object[] toArray() { - return new Object[0]; - } - - /** - * Sets the zeroeth element of the specified array to null - * (if the array has non-zero length) and returns it. - * - * @param a the array - * @return the specified array - * @throws NullPointerException if the specified array is null - */ - public Object[] toArray(Object[] a) { - if (a.length > 0) - a[0] = null; - return a; - } - - /** - * @throws UnsupportedOperationException {@inheritDoc} - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - * @throws IllegalArgumentException {@inheritDoc} - */ - public int drainTo(Collection c) { - if (c == null) - throw new NullPointerException(); - if (c == this) - throw new IllegalArgumentException(); - int n = 0; - Object e; - while ( (e = poll()) != null) { - c.add(e); - ++n; - } - return n; - } - - /** - * @throws UnsupportedOperationException {@inheritDoc} - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - * @throws IllegalArgumentException {@inheritDoc} - */ - public int drainTo(Collection c, int maxElements) { - if (c == null) - throw new NullPointerException(); - if (c == this) - throw new IllegalArgumentException(); - int n = 0; - Object e; - while (n < maxElements && (e = poll()) != null) { - c.add(e); - ++n; - } - return n; - } -} diff --git a/src/actors/scala/actors/threadpool/ThreadFactory.java b/src/actors/scala/actors/threadpool/ThreadFactory.java deleted file mode 100644 index ed6e90ccaa..0000000000 --- a/src/actors/scala/actors/threadpool/ThreadFactory.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -/** - * An object that creates new threads on demand. Using thread factories - * removes hardwiring of calls to {@link Thread#Thread(Runnable) new Thread}, - * enabling applications to use special thread subclasses, priorities, etc. - * - *

- * The simplest implementation of this interface is just: - *

- * class SimpleThreadFactory implements ThreadFactory {
- *   public Thread newThread(Runnable r) {
- *     return new Thread(r);
- *   }
- * }
- * 
- * - * The {@link Executors#defaultThreadFactory} method provides a more - * useful simple implementation, that sets the created thread context - * to known values before returning it. - * @since 1.5 - * @author Doug Lea - */ -public interface ThreadFactory { - - /** - * Constructs a new {@code Thread}. Implementations may also initialize - * priority, name, daemon status, {@code ThreadGroup}, etc. - * - * @param r a runnable to be executed by new thread instance - * @return constructed thread, or {@code null} if the request to - * create a thread is rejected - */ - Thread newThread(Runnable r); -} diff --git a/src/actors/scala/actors/threadpool/ThreadPoolExecutor.java b/src/actors/scala/actors/threadpool/ThreadPoolExecutor.java deleted file mode 100644 index 11e35b034c..0000000000 --- a/src/actors/scala/actors/threadpool/ThreadPoolExecutor.java +++ /dev/null @@ -1,1968 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; -import scala.actors.threadpool.locks.*; -import scala.actors.threadpool.helpers.Utils; -import java.util.HashSet; -import java.util.List; -import java.util.Iterator; -import java.util.ArrayList; -import java.util.ConcurrentModificationException; - -/** - * An {@link ExecutorService} that executes each submitted task using - * one of possibly several pooled threads, normally configured - * using {@link Executors} factory methods. - * - *

Thread pools address two different problems: they usually - * provide improved performance when executing large numbers of - * asynchronous tasks, due to reduced per-task invocation overhead, - * and they provide a means of bounding and managing the resources, - * including threads, consumed when executing a collection of tasks. - * Each {@code ThreadPoolExecutor} also maintains some basic - * statistics, such as the number of completed tasks. - * - *

To be useful across a wide range of contexts, this class - * provides many adjustable parameters and extensibility - * hooks. However, programmers are urged to use the more convenient - * {@link Executors} factory methods {@link - * Executors#newCachedThreadPool} (unbounded thread pool, with - * automatic thread reclamation), {@link Executors#newFixedThreadPool} - * (fixed size thread pool) and {@link - * Executors#newSingleThreadExecutor} (single background thread), that - * preconfigure settings for the most common usage - * scenarios. Otherwise, use the following guide when manually - * configuring and tuning this class: - * - *

- * - *
Core and maximum pool sizes
- * - *
A {@code ThreadPoolExecutor} will automatically adjust the - * pool size (see {@link #getPoolSize}) - * according to the bounds set by - * corePoolSize (see {@link #getCorePoolSize}) and - * maximumPoolSize (see {@link #getMaximumPoolSize}). - * - * When a new task is submitted in method {@link #execute}, and fewer - * than corePoolSize threads are running, a new thread is created to - * handle the request, even if other worker threads are idle. If - * there are more than corePoolSize but less than maximumPoolSize - * threads running, a new thread will be created only if the queue is - * full. By setting corePoolSize and maximumPoolSize the same, you - * create a fixed-size thread pool. By setting maximumPoolSize to an - * essentially unbounded value such as {@code Integer.MAX_VALUE}, you - * allow the pool to accommodate an arbitrary number of concurrent - * tasks. Most typically, core and maximum pool sizes are set only - * upon construction, but they may also be changed dynamically using - * {@link #setCorePoolSize} and {@link #setMaximumPoolSize}.
- * - *
On-demand construction
- * - *
By default, even core threads are initially created and - * started only when new tasks arrive, but this can be overridden - * dynamically using method {@link #prestartCoreThread} or {@link - * #prestartAllCoreThreads}. You probably want to prestart threads if - * you construct the pool with a non-empty queue.
- * - *
Creating new threads
- * - *
New threads are created using a {@link ThreadFactory}. If not - * otherwise specified, a {@link Executors#defaultThreadFactory} is - * used, that creates threads to all be in the same {@link - * ThreadGroup} and with the same {@code NORM_PRIORITY} priority and - * non-daemon status. By supplying a different ThreadFactory, you can - * alter the thread's name, thread group, priority, daemon status, - * etc. If a {@code ThreadFactory} fails to create a thread when asked - * by returning null from {@code newThread}, the executor will - * continue, but might not be able to execute any tasks. Threads - * should possess the "modifyThread" {@code RuntimePermission}. If - * worker threads or other threads using the pool do not possess this - * permission, service may be degraded: configuration changes may not - * take effect in a timely manner, and a shutdown pool may remain in a - * state in which termination is possible but not completed.
- * - *
Keep-alive times
- * - *
If the pool currently has more than corePoolSize threads, - * excess threads will be terminated if they have been idle for more - * than the keepAliveTime (see {@link #getKeepAliveTime}). This - * provides a means of reducing resource consumption when the pool is - * not being actively used. If the pool becomes more active later, new - * threads will be constructed. This parameter can also be changed - * dynamically using method {@link #setKeepAliveTime}. Using a value - * of {@code Long.MAX_VALUE} {@link TimeUnit#NANOSECONDS} effectively - * disables idle threads from ever terminating prior to shut down. By - * default, the keep-alive policy applies only when there are more - * than corePoolSizeThreads. But method {@link - * #allowCoreThreadTimeOut(boolean)} can be used to apply this - * time-out policy to core threads as well, so long as the - * keepAliveTime value is non-zero.
- * - *
Queuing
- * - *
Any {@link BlockingQueue} may be used to transfer and hold - * submitted tasks. The use of this queue interacts with pool sizing: - * - *
    - * - *
  • If fewer than corePoolSize threads are running, the Executor - * always prefers adding a new thread - * rather than queuing.
  • - * - *
  • If corePoolSize or more threads are running, the Executor - * always prefers queuing a request rather than adding a new - * thread.
  • - * - *
  • If a request cannot be queued, a new thread is created unless - * this would exceed maximumPoolSize, in which case, the task will be - * rejected.
  • - * - *
- * - * There are three general strategies for queuing: - *
    - * - *
  1. Direct handoffs. A good default choice for a work - * queue is a {@link SynchronousQueue} that hands off tasks to threads - * without otherwise holding them. Here, an attempt to queue a task - * will fail if no threads are immediately available to run it, so a - * new thread will be constructed. This policy avoids lockups when - * handling sets of requests that might have internal dependencies. - * Direct handoffs generally require unbounded maximumPoolSizes to - * avoid rejection of new submitted tasks. This in turn admits the - * possibility of unbounded thread growth when commands continue to - * arrive on average faster than they can be processed.
  2. - * - *
  3. Unbounded queues. Using an unbounded queue (for - * example a {@link LinkedBlockingQueue} without a predefined - * capacity) will cause new tasks to wait in the queue when all - * corePoolSize threads are busy. Thus, no more than corePoolSize - * threads will ever be created. (And the value of the maximumPoolSize - * therefore doesn't have any effect.) This may be appropriate when - * each task is completely independent of others, so tasks cannot - * affect each others execution; for example, in a web page server. - * While this style of queuing can be useful in smoothing out - * transient bursts of requests, it admits the possibility of - * unbounded work queue growth when commands continue to arrive on - * average faster than they can be processed.
  4. - * - *
  5. Bounded queues. A bounded queue (for example, an - * {@link ArrayBlockingQueue}) helps prevent resource exhaustion when - * used with finite maximumPoolSizes, but can be more difficult to - * tune and control. Queue sizes and maximum pool sizes may be traded - * off for each other: Using large queues and small pools minimizes - * CPU usage, OS resources, and context-switching overhead, but can - * lead to artificially low throughput. If tasks frequently block (for - * example if they are I/O bound), a system may be able to schedule - * time for more threads than you otherwise allow. Use of small queues - * generally requires larger pool sizes, which keeps CPUs busier but - * may encounter unacceptable scheduling overhead, which also - * decreases throughput.
  6. - * - *
- * - *
- * - *
Rejected tasks
- * - *
New tasks submitted in method {@link #execute} will be - * rejected when the Executor has been shut down, and also - * when the Executor uses finite bounds for both maximum threads and - * work queue capacity, and is saturated. In either case, the {@code - * execute} method invokes the {@link - * RejectedExecutionHandler#rejectedExecution} method of its {@link - * RejectedExecutionHandler}. Four predefined handler policies are - * provided: - * - *
    - * - *
  1. In the default {@link ThreadPoolExecutor.AbortPolicy}, the - * handler throws a runtime {@link RejectedExecutionException} upon - * rejection.
  2. - * - *
  3. In {@link ThreadPoolExecutor.CallerRunsPolicy}, the thread - * that invokes {@code execute} itself runs the task. This provides a - * simple feedback control mechanism that will slow down the rate that - * new tasks are submitted.
  4. - * - *
  5. In {@link ThreadPoolExecutor.DiscardPolicy}, a task that - * cannot be executed is simply dropped.
  6. - * - *
  7. In {@link ThreadPoolExecutor.DiscardOldestPolicy}, if the - * executor is not shut down, the task at the head of the work queue - * is dropped, and then execution is retried (which can fail again, - * causing this to be repeated.)
  8. - * - *
- * - * It is possible to define and use other kinds of {@link - * RejectedExecutionHandler} classes. Doing so requires some care - * especially when policies are designed to work only under particular - * capacity or queuing policies.
- * - *
Hook methods
- * - *
This class provides {@code protected} overridable {@link - * #beforeExecute} and {@link #afterExecute} methods that are called - * before and after execution of each task. These can be used to - * manipulate the execution environment; for example, reinitializing - * ThreadLocals, gathering statistics, or adding log - * entries. Additionally, method {@link #terminated} can be overridden - * to perform any special processing that needs to be done once the - * Executor has fully terminated. - * - *

If hook or callback methods throw exceptions, internal worker - * threads may in turn fail and abruptly terminate.

- * - *
Queue maintenance
- * - *
Method {@link #getQueue} allows access to the work queue for - * purposes of monitoring and debugging. Use of this method for any - * other purpose is strongly discouraged. Two supplied methods, - * {@link #remove} and {@link #purge} are available to assist in - * storage reclamation when large numbers of queued tasks become - * cancelled.
- * - *
Finalization
- * - *
A pool that is no longer referenced in a program AND - * has no remaining threads will be {@code shutdown} automatically. If - * you would like to ensure that unreferenced pools are reclaimed even - * if users forget to call {@link #shutdown}, then you must arrange - * that unused threads eventually die, by setting appropriate - * keep-alive times, using a lower bound of zero core threads and/or - * setting {@link #allowCoreThreadTimeOut(boolean)}.
- * - *
- * - *

Extension example. Most extensions of this class - * override one or more of the protected hook methods. For example, - * here is a subclass that adds a simple pause/resume feature: - * - *

 {@code
- * class PausableThreadPoolExecutor extends ThreadPoolExecutor {
- *   private boolean isPaused;
- *   private ReentrantLock pauseLock = new ReentrantLock();
- *   private Condition unpaused = pauseLock.newCondition();
- *
- *   public PausableThreadPoolExecutor(...) { super(...); }
- *
- *   protected void beforeExecute(Thread t, Runnable r) {
- *     super.beforeExecute(t, r);
- *     pauseLock.lock();
- *     try {
- *       while (isPaused) unpaused.await();
- *     } catch (InterruptedException ie) {
- *       t.interrupt();
- *     } finally {
- *       pauseLock.unlock();
- *     }
- *   }
- *
- *   public void pause() {
- *     pauseLock.lock();
- *     try {
- *       isPaused = true;
- *     } finally {
- *       pauseLock.unlock();
- *     }
- *   }
- *
- *   public void resume() {
- *     pauseLock.lock();
- *     try {
- *       isPaused = false;
- *       unpaused.signalAll();
- *     } finally {
- *       pauseLock.unlock();
- *     }
- *   }
- * }}
- * - * @since 1.5 - * @author Doug Lea - */ -public class ThreadPoolExecutor extends AbstractExecutorService { - /** - * The main pool control state, ctl, is an atomic integer packing - * two conceptual fields - * workerCount, indicating the effective number of threads - * runState, indicating whether running, shutting down etc - * - * In order to pack them into one int, we limit workerCount to - * (2^29)-1 (about 500 million) threads rather than (2^31)-1 (2 - * billion) otherwise representable. If this is ever an issue in - * the future, the variable can be changed to be an AtomicLong, - * and the shift/mask constants below adjusted. But until the need - * arises, this code is a bit faster and simpler using an int. - * - * The workerCount is the number of workers that have been - * permitted to start and not permitted to stop. The value may be - * transiently different from the actual number of live threads, - * for example when a ThreadFactory fails to create a thread when - * asked, and when exiting threads are still performing - * bookkeeping before terminating. The user-visible pool size is - * reported as the current size of the workers set. - * - * The runState provides the main lifecyle control, taking on values: - * - * RUNNING: Accept new tasks and process queued tasks - * SHUTDOWN: Don't accept new tasks, but process queued tasks - * STOP: Don't accept new tasks, don't process queued tasks, - * and interrupt in-progress tasks - * TIDYING: All tasks have terminated, workerCount is zero, - * the thread transitioning to state TIDYING - * will run the terminated() hook method - * TERMINATED: terminated() has completed - * - * The numerical order among these values matters, to allow - * ordered comparisons. The runState monotonically increases over - * time, but need not hit each state. The transitions are: - * - * RUNNING -> SHUTDOWN - * On invocation of shutdown(), perhaps implicitly in finalize() - * (RUNNING or SHUTDOWN) -> STOP - * On invocation of shutdownNow() - * SHUTDOWN -> TIDYING - * When both queue and pool are empty - * STOP -> TIDYING - * When pool is empty - * TIDYING -> TERMINATED - * When the terminated() hook method has completed - * - * Threads waiting in awaitTermination() will return when the - * state reaches TERMINATED. - * - * Detecting the transition from SHUTDOWN to TIDYING is less - * straightforward than you'd like because the queue may become - * empty after non-empty and vice versa during SHUTDOWN state, but - * we can only terminate if, after seeing that it is empty, we see - * that workerCount is 0 (which sometimes entails a recheck -- see - * below). - */ - private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); - private static final int COUNT_BITS = 29; // Integer.SIZE - 3; - private static final int CAPACITY = (1 << COUNT_BITS) - 1; - - // runState is stored in the high-order bits - private static final int RUNNING = -1 << COUNT_BITS; - private static final int SHUTDOWN = 0 << COUNT_BITS; - private static final int STOP = 1 << COUNT_BITS; - private static final int TIDYING = 2 << COUNT_BITS; - private static final int TERMINATED = 3 << COUNT_BITS; - - // Packing and unpacking ctl - private static int runStateOf(int c) { return c & ~CAPACITY; } - private static int workerCountOf(int c) { return c & CAPACITY; } - private static int ctlOf(int rs, int wc) { return rs | wc; } - - /* - * Bit field accessors that don't require unpacking ctl. - * These depend on the bit layout and on workerCount being never negative. - */ - - private static boolean runStateLessThan(int c, int s) { - return c < s; - } - - private static boolean runStateAtLeast(int c, int s) { - return c >= s; - } - - private static boolean isRunning(int c) { - return c < SHUTDOWN; - } - - /** - * Attempt to CAS-increment the workerCount field of ctl. - */ - private boolean compareAndIncrementWorkerCount(int expect) { - return ctl.compareAndSet(expect, expect + 1); - } - - /** - * Attempt to CAS-decrement the workerCount field of ctl. - */ - private boolean compareAndDecrementWorkerCount(int expect) { - return ctl.compareAndSet(expect, expect - 1); - } - - /** - * Decrements the workerCount field of ctl. This is called only on - * abrupt termination of a thread (see processWorkerExit). Other - * decrements are performed within getTask. - */ - private void decrementWorkerCount() { - do {} while (! compareAndDecrementWorkerCount(ctl.get())); - } - - /** - * The queue used for holding tasks and handing off to worker - * threads. We do not require that workQueue.poll() returning - * null necessarily means that workQueue.isEmpty(), so rely - * solely on isEmpty to see if the queue is empty (which we must - * do for example when deciding whether to transition from - * SHUTDOWN to TIDYING). This accommodates special-purpose - * queues such as DelayQueues for which poll() is allowed to - * return null even if it may later return non-null when delays - * expire. - */ - private final BlockingQueue workQueue; - - // TODO: DK: mainLock is used in lock(); try { ... } finally { unlock(); } - // Consider replacing with synchronized {} if performance reasons exist - /** - * Lock held on access to workers set and related bookkeeping. - * While we could use a concurrent set of some sort, it turns out - * to be generally preferable to use a lock. Among the reasons is - * that this serializes interruptIdleWorkers, which avoids - * unnecessary interrupt storms, especially during shutdown. - * Otherwise exiting threads would concurrently interrupt those - * that have not yet interrupted. It also simplifies some of the - * associated statistics bookkeeping of largestPoolSize etc. We - * also hold mainLock on shutdown and shutdownNow, for the sake of - * ensuring workers set is stable while separately checking - * permission to interrupt and actually interrupting. - */ - public final ReentrantLock mainLock = new ReentrantLock(); - - /** - * Set containing all worker threads in pool. Accessed only when - * holding mainLock. - */ - public final HashSet workers = new HashSet(); - - /** - * Wait condition to support awaitTermination - */ - private final Condition termination = mainLock.newCondition(); - - /** - * Tracks largest attained pool size. Accessed only under - * mainLock. - */ - private int largestPoolSize; - - /** - * Counter for completed tasks. Updated only on termination of - * worker threads. Accessed only under mainLock. - */ - private long completedTaskCount; - - /* - * All user control parameters are declared as volatiles so that - * ongoing actions are based on freshest values, but without need - * for locking, since no internal invariants depend on them - * changing synchronously with respect to other actions. - */ - - /** - * Factory for new threads. All threads are created using this - * factory (via method addWorker). All callers must be prepared - * for addWorker to fail, which may reflect a system or user's - * policy limiting the number of threads. Even though it is not - * treated as an error, failure to create threads may result in - * new tasks being rejected or existing ones remaining stuck in - * the queue. On the other hand, no special precautions exist to - * handle OutOfMemoryErrors that might be thrown while trying to - * create threads, since there is generally no recourse from - * within this class. - */ - private volatile ThreadFactory threadFactory; - - /** - * Handler called when saturated or shutdown in execute. - */ - private volatile RejectedExecutionHandler handler; - - /** - * Timeout in nanoseconds for idle threads waiting for work. - * Threads use this timeout when there are more than corePoolSize - * present or if allowCoreThreadTimeOut. Otherwise they wait - * forever for new work. - */ - private volatile long keepAliveTime; - - /** - * If false (default), core threads stay alive even when idle. - * If true, core threads use keepAliveTime to time out waiting - * for work. - */ - private volatile boolean allowCoreThreadTimeOut; - - /** - * Core pool size is the minimum number of workers to keep alive - * (and not allow to time out etc) unless allowCoreThreadTimeOut - * is set, in which case the minimum is zero. - */ - private volatile int corePoolSize; - - /** - * Maximum pool size. Note that the actual maximum is internally - * bounded by CAPACITY. - */ - private volatile int maximumPoolSize; - - /** - * The default rejected execution handler - */ - private static final RejectedExecutionHandler defaultHandler = - new AbortPolicy(); - - /** - * Permission required for callers of shutdown and shutdownNow. - * We additionally require (see checkShutdownAccess) that callers - * have permission to actually interrupt threads in the worker set - * (as governed by Thread.interrupt, which relies on - * ThreadGroup.checkAccess, which in turn relies on - * SecurityManager.checkAccess). Shutdowns are attempted only if - * these checks pass. - * - * All actual invocations of Thread.interrupt (see - * interruptIdleWorkers and interruptWorkers) ignore - * SecurityExceptions, meaning that the attempted interrupts - * silently fail. In the case of shutdown, they should not fail - * unless the SecurityManager has inconsistent policies, sometimes - * allowing access to a thread and sometimes not. In such cases, - * failure to actually interrupt threads may disable or delay full - * termination. Other uses of interruptIdleWorkers are advisory, - * and failure to actually interrupt will merely delay response to - * configuration changes so is not handled exceptionally. - */ - private static final RuntimePermission shutdownPerm = - new RuntimePermission("modifyThread"); - - /** - * Class Worker mainly maintains interrupt control state for - * threads running tasks, along with other minor bookkeeping. This - * class opportunistically extends ReentrantLock to simplify - * acquiring and releasing a lock surrounding each task execution. - * This protects against interrupts that are intended to wake up a - * worker thread waiting for a task from instead interrupting a - * task being run. - */ - public final class Worker extends ReentrantLock implements Runnable { - /** - * This class will never be serialized, but we provide a - * serialVersionUID to suppress a javac warning. - */ - private static final long serialVersionUID = 6138294804551838833L; - - /** Thread this worker is running in. Null if factory fails. */ - public final Thread thread; - /** Initial task to run. Possibly null. */ - Runnable firstTask; - /** Per-thread task counter */ - volatile long completedTasks; - - /** - * Creates with given first task and thread from ThreadFactory. - * @param firstTask the first task (null if none) - */ - Worker(Runnable firstTask) { - this.firstTask = firstTask; - this.thread = getThreadFactory().newThread(this); - } - - /** Delegates main run loop to outer runWorker */ - public void run() { - runWorker(this); - } - } - - /* - * Methods for setting control state - */ - - /** - * Transitions runState to given target, or leaves it alone if - * already at least the given target. - * - * @param targetState the desired state, either SHUTDOWN or STOP - * (but not TIDYING or TERMINATED -- use tryTerminate for that) - */ - private void advanceRunState(int targetState) { - for (;;) { - int c = ctl.get(); - if (runStateAtLeast(c, targetState) || - ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c)))) - break; - } - } - - /** - * Transitions to TERMINATED state if either (SHUTDOWN and pool - * and queue empty) or (STOP and pool empty). If otherwise - * eligible to terminate but workerCount is nonzero, interrupts an - * idle worker to ensure that shutdown signals propagate. This - * method must be called following any action that might make - * termination possible -- reducing worker count or removing tasks - * from the queue during shutdown. The method is non-private to - * allow access from ScheduledThreadPoolExecutor. - */ - final void tryTerminate() { - for (;;) { - int c = ctl.get(); - if (isRunning(c) || - runStateAtLeast(c, TIDYING) || - (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty())) - return; - if (workerCountOf(c) != 0) { // Eligible to terminate - interruptIdleWorkers(ONLY_ONE); - return; - } - - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) { - try { - terminated(); - } finally { - ctl.set(ctlOf(TERMINATED, 0)); - termination.signalAll(); - } - return; - } - } finally { - mainLock.unlock(); - } - // else retry on failed CAS - } - } - - /* - * Methods for controlling interrupts to worker threads. - */ - - /** - * If there is a security manager, makes sure caller has - * permission to shut down threads in general (see shutdownPerm). - * If this passes, additionally makes sure the caller is allowed - * to interrupt each worker thread. This might not be true even if - * first check passed, if the SecurityManager treats some threads - * specially. - */ - private void checkShutdownAccess() { - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkPermission(shutdownPerm); - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - for (Iterator itr = workers.iterator(); itr.hasNext();) { - Worker w = (Worker)itr.next(); - security.checkAccess(w.thread); - } - } finally { - mainLock.unlock(); - } - } - } - - /** - * Interrupts all threads, even if active. Ignores SecurityExceptions - * (in which case some threads may remain uninterrupted). - */ - private void interruptWorkers() { - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - for (Iterator itr = workers.iterator(); itr.hasNext();) { - Worker w = (Worker)itr.next(); - try { - w.thread.interrupt(); - } catch (SecurityException ignore) { - } - } - } finally { - mainLock.unlock(); - } - } - - /** - * Interrupts threads that might be waiting for tasks (as - * indicated by not being locked) so they can check for - * termination or configuration changes. Ignores - * SecurityExceptions (in which case some threads may remain - * uninterrupted). - * - * @param onlyOne If true, interrupt at most one worker. This is - * called only from tryTerminate when termination is otherwise - * enabled but there are still other workers. In this case, at - * most one waiting worker is interrupted to propagate shutdown - * signals in case all threads are currently waiting. - * Interrupting any arbitrary thread ensures that newly arriving - * workers since shutdown began will also eventually exit. - * To guarantee eventual termination, it suffices to always - * interrupt only one idle worker, but shutdown() interrupts all - * idle workers so that redundant workers exit promptly, not - * waiting for a straggler task to finish. - */ - private void interruptIdleWorkers(boolean onlyOne) { - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - Iterator it = workers.iterator(); - while (it.hasNext()) { - Worker w = (Worker)it.next(); - Thread t = w.thread; - if (!t.isInterrupted() && w.tryLock()) { - try { - t.interrupt(); - } catch (SecurityException ignore) { - } finally { - w.unlock(); - } - } - if (onlyOne) - break; - } - } finally { - mainLock.unlock(); - } - } - - /** - * Common form of interruptIdleWorkers, to avoid having to - * remember what the boolean argument means. - */ - private void interruptIdleWorkers() { - interruptIdleWorkers(false); - } - - private static final boolean ONLY_ONE = true; - - /** - * Ensures that unless the pool is stopping, the current thread - * does not have its interrupt set. This requires a double-check - * of state in case the interrupt was cleared concurrently with a - * shutdownNow -- if so, the interrupt is re-enabled. - */ - private void clearInterruptsForTaskRun() { - if (runStateLessThan(ctl.get(), STOP) && - Thread.interrupted() && - runStateAtLeast(ctl.get(), STOP)) - Thread.currentThread().interrupt(); - } - - /* - * Misc utilities, most of which are also exported to - * ScheduledThreadPoolExecutor - */ - - /** - * Invokes the rejected execution handler for the given command. - * Package-protected for use by ScheduledThreadPoolExecutor. - */ - final void reject(Runnable command) { - handler.rejectedExecution(command, this); - } - - /** - * Performs any further cleanup following run state transition on - * invocation of shutdown. A no-op here, but used by - * ScheduledThreadPoolExecutor to cancel delayed tasks. - */ - void onShutdown() { - } - - /** - * State check needed by ScheduledThreadPoolExecutor to - * enable running tasks during shutdown. - * - * @param shutdownOK true if should return true if SHUTDOWN - */ - final boolean isRunningOrShutdown(boolean shutdownOK) { - int rs = runStateOf(ctl.get()); - return rs == RUNNING || (rs == SHUTDOWN && shutdownOK); - } - - /** - * Drains the task queue into a new list, normally using - * drainTo. But if the queue is a DelayQueue or any other kind of - * queue for which poll or drainTo may fail to remove some - * elements, it deletes them one by one. - */ - private List drainQueue() { - BlockingQueue q = workQueue; - List taskList = new ArrayList(); - q.drainTo(taskList); - if (!q.isEmpty()) { - Runnable[] arr = (Runnable[])q.toArray(new Runnable[0]); - for (int i=0; i= SHUTDOWN && - ! (rs == SHUTDOWN && - firstTask == null && - ! workQueue.isEmpty())) - return false; - - for (;;) { - int wc = workerCountOf(c); - if (wc >= CAPACITY || - wc >= (core ? corePoolSize : maximumPoolSize)) - return false; - if (compareAndIncrementWorkerCount(c)) - break retry; - c = ctl.get(); // Re-read ctl - if (runStateOf(c) != rs) - continue retry; - // else CAS failed due to workerCount change; retry inner loop - } - } - - Worker w = new Worker(firstTask); - Thread t = w.thread; - - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - // Recheck while holding lock. - // Back out on ThreadFactory failure or if - // shut down before lock acquired. - int c = ctl.get(); - int rs = runStateOf(c); - - if (t == null || - (rs >= SHUTDOWN && - ! (rs == SHUTDOWN && - firstTask == null))) { - decrementWorkerCount(); - tryTerminate(); - return false; - } - - workers.add(w); - - int s = workers.size(); - if (s > largestPoolSize) - largestPoolSize = s; - } finally { - mainLock.unlock(); - } - - t.start(); - // It is possible (but unlikely) for a thread to have been - // added to workers, but not yet started, during transition to - // STOP, which could result in a rare missed interrupt, - // because Thread.interrupt is not guaranteed to have any effect - // on a non-yet-started Thread (see Thread#interrupt). - if (runStateOf(ctl.get()) == STOP && ! t.isInterrupted()) - t.interrupt(); - - return true; - } - - /** - * Performs cleanup and bookkeeping for a dying worker. Called - * only from worker threads. Unless completedAbruptly is set, - * assumes that workerCount has already been adjusted to account - * for exit. This method removes thread from worker set, and - * possibly terminates the pool or replaces the worker if either - * it exited due to user task exception or if fewer than - * corePoolSize workers are running or queue is non-empty but - * there are no workers. - * - * @param w the worker - * @param completedAbruptly if the worker died due to user exception - */ - private void processWorkerExit(Worker w, boolean completedAbruptly) { - if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted - decrementWorkerCount(); - - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - completedTaskCount += w.completedTasks; - workers.remove(w); - } finally { - mainLock.unlock(); - } - - tryTerminate(); - - int c = ctl.get(); - if (runStateLessThan(c, STOP)) { - if (!completedAbruptly) { - int min = allowCoreThreadTimeOut ? 0 : corePoolSize; - if (min == 0 && ! workQueue.isEmpty()) - min = 1; - if (workerCountOf(c) >= min) - return; // replacement not needed - } - addWorker(null, false); - } - } - - /** - * Performs blocking or timed wait for a task, depending on - * current configuration settings, or returns null if this worker - * must exit because of any of: - * 1. There are more than maximumPoolSize workers (due to - * a call to setMaximumPoolSize). - * 2. The pool is stopped. - * 3. The pool is shutdown and the queue is empty. - * 4. This worker timed out waiting for a task, and timed-out - * workers are subject to termination (that is, - * {@code allowCoreThreadTimeOut || workerCount > corePoolSize}) - * both before and after the timed wait. - * - * @return task, or null if the worker must exit, in which case - * workerCount is decremented - */ - private Runnable getTask() { - boolean timedOut = false; // Did the last poll() time out? - - retry: - for (;;) { - int c = ctl.get(); - int rs = runStateOf(c); - - // Check if queue empty only if necessary. - if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { - decrementWorkerCount(); - return null; - } - - boolean timed; // Are workers subject to culling? - - for (;;) { - int wc = workerCountOf(c); - timed = allowCoreThreadTimeOut || wc > corePoolSize; - - if (wc <= maximumPoolSize && ! (timedOut && timed)) - break; - if (compareAndDecrementWorkerCount(c)) - return null; - c = ctl.get(); // Re-read ctl - if (runStateOf(c) != rs) - continue retry; - // else CAS failed due to workerCount change; retry inner loop - } - - try { - Runnable r = timed ? - (Runnable)workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : - (Runnable)workQueue.take(); - if (r != null) - return r; - timedOut = true; - } catch (InterruptedException retry) { - timedOut = false; - } - } - } - - /** - * Main worker run loop. Repeatedly gets tasks from queue and - * executes them, while coping with a number of issues: - * - * 1. We may start out with an initial task, in which case we - * don't need to get the first one. Otherwise, as long as pool is - * running, we get tasks from getTask. If it returns null then the - * worker exits due to changed pool state or configuration - * parameters. Other exits result from exception throws in - * external code, in which case completedAbruptly holds, which - * usually leads processWorkerExit to replace this thread. - * - * 2. Before running any task, the lock is acquired to prevent - * other pool interrupts while the task is executing, and - * clearInterruptsForTaskRun called to ensure that unless pool is - * stopping, this thread does not have its interrupt set. - * - * 3. Each task run is preceded by a call to beforeExecute, which - * might throw an exception, in which case we cause thread to die - * (breaking loop with completedAbruptly true) without processing - * the task. - * - * 4. Assuming beforeExecute completes normally, we run the task, - * gathering any of its thrown exceptions to send to - * afterExecute. We separately handle RuntimeException, Error - * (both of which the specs guarantee that we trap) and arbitrary - * Throwables. Because we cannot rethrow Throwables within - * Runnable.run, we wrap them within Errors on the way out (to the - * thread's UncaughtExceptionHandler). Any thrown exception also - * conservatively causes thread to die. - * - * 5. After task.run completes, we call afterExecute, which may - * also throw an exception, which will also cause thread to - * die. According to JLS Sec 14.20, this exception is the one that - * will be in effect even if task.run throws. - * - * The net effect of the exception mechanics is that afterExecute - * and the thread's UncaughtExceptionHandler have as accurate - * information as we can provide about any problems encountered by - * user code. - * - * @param w the worker - */ - final void runWorker(Worker w) { - Runnable task = w.firstTask; - w.firstTask = null; - boolean completedAbruptly = true; - try { - while (task != null || (task = getTask()) != null) { - w.lock(); - clearInterruptsForTaskRun(); - try { - beforeExecute(w.thread, task); - Throwable thrown = null; - try { - task.run(); - } catch (RuntimeException x) { - thrown = x; throw x; - } catch (Error x) { - thrown = x; throw x; - } catch (Throwable x) { - thrown = x; throw new Error(x); - } finally { - afterExecute(task, thrown); - } - } finally { - task = null; - w.completedTasks++; - w.unlock(); - } - } - completedAbruptly = false; - } finally { - processWorkerExit(w, completedAbruptly); - } - } - - // Public constructors and methods - - /** - * Creates a new {@code ThreadPoolExecutor} with the given initial - * parameters and default thread factory and rejected execution handler. - * It may be more convenient to use one of the {@link Executors} factory - * methods instead of this general purpose constructor. - * - * @param corePoolSize the number of threads to keep in the pool, even - * if they are idle, unless {@code allowCoreThreadTimeOut} is set - * @param maximumPoolSize the maximum number of threads to allow in the - * pool - * @param keepAliveTime when the number of threads is greater than - * the core, this is the maximum time that excess idle threads - * will wait for new tasks before terminating. - * @param unit the time unit for the {@code keepAliveTime} argument - * @param workQueue the queue to use for holding tasks before they are - * executed. This queue will hold only the {@code Runnable} - * tasks submitted by the {@code execute} method. - * @throws IllegalArgumentException if one of the following holds:
- * {@code corePoolSize < 0}
- * {@code keepAliveTime < 0}
- * {@code maximumPoolSize <= 0}
- * {@code maximumPoolSize < corePoolSize} - * @throws NullPointerException if {@code workQueue} is null - */ - public ThreadPoolExecutor(int corePoolSize, - int maximumPoolSize, - long keepAliveTime, - TimeUnit unit, - BlockingQueue workQueue) { - this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, - Executors.defaultThreadFactory(), defaultHandler); - } - - /** - * Creates a new {@code ThreadPoolExecutor} with the given initial - * parameters and default rejected execution handler. - * - * @param corePoolSize the number of threads to keep in the pool, even - * if they are idle, unless {@code allowCoreThreadTimeOut} is set - * @param maximumPoolSize the maximum number of threads to allow in the - * pool - * @param keepAliveTime when the number of threads is greater than - * the core, this is the maximum time that excess idle threads - * will wait for new tasks before terminating. - * @param unit the time unit for the {@code keepAliveTime} argument - * @param workQueue the queue to use for holding tasks before they are - * executed. This queue will hold only the {@code Runnable} - * tasks submitted by the {@code execute} method. - * @param threadFactory the factory to use when the executor - * creates a new thread - * @throws IllegalArgumentException if one of the following holds:
- * {@code corePoolSize < 0}
- * {@code keepAliveTime < 0}
- * {@code maximumPoolSize <= 0}
- * {@code maximumPoolSize < corePoolSize} - * @throws NullPointerException if {@code workQueue} - * or {@code threadFactory} is null - */ - public ThreadPoolExecutor(int corePoolSize, - int maximumPoolSize, - long keepAliveTime, - TimeUnit unit, - BlockingQueue workQueue, - ThreadFactory threadFactory) { - this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, - threadFactory, defaultHandler); - } - - /** - * Creates a new {@code ThreadPoolExecutor} with the given initial - * parameters and default thread factory. - * - * @param corePoolSize the number of threads to keep in the pool, even - * if they are idle, unless {@code allowCoreThreadTimeOut} is set - * @param maximumPoolSize the maximum number of threads to allow in the - * pool - * @param keepAliveTime when the number of threads is greater than - * the core, this is the maximum time that excess idle threads - * will wait for new tasks before terminating. - * @param unit the time unit for the {@code keepAliveTime} argument - * @param workQueue the queue to use for holding tasks before they are - * executed. This queue will hold only the {@code Runnable} - * tasks submitted by the {@code execute} method. - * @param handler the handler to use when execution is blocked - * because the thread bounds and queue capacities are reached - * @throws IllegalArgumentException if one of the following holds:
- * {@code corePoolSize < 0}
- * {@code keepAliveTime < 0}
- * {@code maximumPoolSize <= 0}
- * {@code maximumPoolSize < corePoolSize} - * @throws NullPointerException if {@code workQueue} - * or {@code handler} is null - */ - public ThreadPoolExecutor(int corePoolSize, - int maximumPoolSize, - long keepAliveTime, - TimeUnit unit, - BlockingQueue workQueue, - RejectedExecutionHandler handler) { - this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, - Executors.defaultThreadFactory(), handler); - } - - /** - * Creates a new {@code ThreadPoolExecutor} with the given initial - * parameters. - * - * @param corePoolSize the number of threads to keep in the pool, even - * if they are idle, unless {@code allowCoreThreadTimeOut} is set - * @param maximumPoolSize the maximum number of threads to allow in the - * pool - * @param keepAliveTime when the number of threads is greater than - * the core, this is the maximum time that excess idle threads - * will wait for new tasks before terminating. - * @param unit the time unit for the {@code keepAliveTime} argument - * @param workQueue the queue to use for holding tasks before they are - * executed. This queue will hold only the {@code Runnable} - * tasks submitted by the {@code execute} method. - * @param threadFactory the factory to use when the executor - * creates a new thread - * @param handler the handler to use when execution is blocked - * because the thread bounds and queue capacities are reached - * @throws IllegalArgumentException if one of the following holds:
- * {@code corePoolSize < 0}
- * {@code keepAliveTime < 0}
- * {@code maximumPoolSize <= 0}
- * {@code maximumPoolSize < corePoolSize} - * @throws NullPointerException if {@code workQueue} - * or {@code threadFactory} or {@code handler} is null - */ - public ThreadPoolExecutor(int corePoolSize, - int maximumPoolSize, - long keepAliveTime, - TimeUnit unit, - BlockingQueue workQueue, - ThreadFactory threadFactory, - RejectedExecutionHandler handler) { - if (corePoolSize < 0 || - maximumPoolSize <= 0 || - maximumPoolSize < corePoolSize || - keepAliveTime < 0) - throw new IllegalArgumentException(); - if (workQueue == null || threadFactory == null || handler == null) - throw new NullPointerException(); - this.corePoolSize = corePoolSize; - this.maximumPoolSize = maximumPoolSize; - this.workQueue = workQueue; - this.keepAliveTime = unit.toNanos(keepAliveTime); - this.threadFactory = threadFactory; - this.handler = handler; - } - - /** - * Executes the given task sometime in the future. The task - * may execute in a new thread or in an existing pooled thread. - * - * If the task cannot be submitted for execution, either because this - * executor has been shutdown or because its capacity has been reached, - * the task is handled by the current {@code RejectedExecutionHandler}. - * - * @param command the task to execute - * @throws RejectedExecutionException at discretion of - * {@code RejectedExecutionHandler}, if the task - * cannot be accepted for execution - * @throws NullPointerException if {@code command} is null - */ - public void execute(Runnable command) { - if (command == null) - throw new NullPointerException(); - /* - * Proceed in 3 steps: - * - * 1. If fewer than corePoolSize threads are running, try to - * start a new thread with the given command as its first - * task. The call to addWorker atomically checks runState and - * workerCount, and so prevents false alarms that would add - * threads when it shouldn't, by returning false. - * - * 2. If a task can be successfully queued, then we still need - * to double-check whether we should have added a thread - * (because existing ones died since last checking) or that - * the pool shut down since entry into this method. So we - * recheck state and if necessary roll back the enqueuing if - * stopped, or start a new thread if there are none. - * - * 3. If we cannot queue task, then we try to add a new - * thread. If it fails, we know we are shut down or saturated - * and so reject the task. - */ - int c = ctl.get(); - if (workerCountOf(c) < corePoolSize) { - if (addWorker(command, true)) - return; - c = ctl.get(); - } - if (isRunning(c) && workQueue.offer(command)) { - int recheck = ctl.get(); - if (! isRunning(recheck) && remove(command)) - reject(command); - else if (workerCountOf(recheck) == 0) - addWorker(null, false); - } - else if (!addWorker(command, false)) - reject(command); - } - - /** - * Initiates an orderly shutdown in which previously submitted - * tasks are executed, but no new tasks will be accepted. - * Invocation has no additional effect if already shut down. - * - * @throws SecurityException {@inheritDoc} - */ - public void shutdown() { - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - checkShutdownAccess(); - advanceRunState(SHUTDOWN); - interruptIdleWorkers(); - onShutdown(); // hook for ScheduledThreadPoolExecutor - } finally { - mainLock.unlock(); - } - tryTerminate(); - } - - /** - * Attempts to stop all actively executing tasks, halts the - * processing of waiting tasks, and returns a list of the tasks - * that were awaiting execution. These tasks are drained (removed) - * from the task queue upon return from this method. - * - *

There are no guarantees beyond best-effort attempts to stop - * processing actively executing tasks. This implementation - * cancels tasks via {@link Thread#interrupt}, so any task that - * fails to respond to interrupts may never terminate. - * - * @throws SecurityException {@inheritDoc} - */ - public List shutdownNow() { - List tasks; - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - checkShutdownAccess(); - advanceRunState(STOP); - interruptWorkers(); - tasks = drainQueue(); - } finally { - mainLock.unlock(); - } - tryTerminate(); - return tasks; - } - - public boolean isShutdown() { - return ! isRunning(ctl.get()); - } - - /** - * Returns true if this executor is in the process of terminating - * after {@link #shutdown} or {@link #shutdownNow} but has not - * completely terminated. This method may be useful for - * debugging. A return of {@code true} reported a sufficient - * period after shutdown may indicate that submitted tasks have - * ignored or suppressed interruption, causing this executor not - * to properly terminate. - * - * @return true if terminating but not yet terminated - */ - public boolean isTerminating() { - int c = ctl.get(); - return ! isRunning(c) && runStateLessThan(c, TERMINATED); - } - - public boolean isTerminated() { - return runStateAtLeast(ctl.get(), TERMINATED); - } - - public boolean awaitTermination(long timeout, TimeUnit unit) - throws InterruptedException { - long nanos = unit.toNanos(timeout); - long deadline = Utils.nanoTime() + nanos; - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - if (runStateAtLeast(ctl.get(), TERMINATED)) - return true; - while (nanos > 0) { - termination.await(nanos, TimeUnit.NANOSECONDS); - if (runStateAtLeast(ctl.get(), TERMINATED)) - return true; - nanos = deadline - Utils.nanoTime(); - } - return false; - } finally { - mainLock.unlock(); - } - } - - /** - * Invokes {@code shutdown} when this executor is no longer - * referenced and it has no threads. - */ - protected void finalize() { - shutdown(); - } - - /** - * Sets the thread factory used to create new threads. - * - * @param threadFactory the new thread factory - * @throws NullPointerException if threadFactory is null - * @see #getThreadFactory - */ - public void setThreadFactory(ThreadFactory threadFactory) { - if (threadFactory == null) - throw new NullPointerException(); - this.threadFactory = threadFactory; - } - - /** - * Returns the thread factory used to create new threads. - * - * @return the current thread factory - * @see #setThreadFactory - */ - public ThreadFactory getThreadFactory() { - return threadFactory; - } - - /** - * Sets a new handler for unexecutable tasks. - * - * @param handler the new handler - * @throws NullPointerException if handler is null - * @see #getRejectedExecutionHandler - */ - public void setRejectedExecutionHandler(RejectedExecutionHandler handler) { - if (handler == null) - throw new NullPointerException(); - this.handler = handler; - } - - /** - * Returns the current handler for unexecutable tasks. - * - * @return the current handler - * @see #setRejectedExecutionHandler - */ - public RejectedExecutionHandler getRejectedExecutionHandler() { - return handler; - } - - /** - * Sets the core number of threads. This overrides any value set - * in the constructor. If the new value is smaller than the - * current value, excess existing threads will be terminated when - * they next become idle. If larger, new threads will, if needed, - * be started to execute any queued tasks. - * - * @param corePoolSize the new core size - * @throws IllegalArgumentException if {@code corePoolSize < 0} - * @see #getCorePoolSize - */ - public void setCorePoolSize(int corePoolSize) { - if (corePoolSize < 0) - throw new IllegalArgumentException(); - int delta = corePoolSize - this.corePoolSize; - this.corePoolSize = corePoolSize; - if (workerCountOf(ctl.get()) > corePoolSize) - interruptIdleWorkers(); - else if (delta > 0) { - // We don't really know how many new threads are "needed". - // As a heuristic, prestart enough new workers (up to new - // core size) to handle the current number of tasks in - // queue, but stop if queue becomes empty while doing so. - int k = Math.min(delta, workQueue.size()); - while (k-- > 0 && addWorker(null, true)) { - if (workQueue.isEmpty()) - break; - } - } - } - - /** - * Returns the core number of threads. - * - * @return the core number of threads - * @see #setCorePoolSize - */ - public int getCorePoolSize() { - return corePoolSize; - } - - /** - * Starts a core thread, causing it to idly wait for work. This - * overrides the default policy of starting core threads only when - * new tasks are executed. This method will return {@code false} - * if all core threads have already been started. - * - * @return {@code true} if a thread was started - */ - public boolean prestartCoreThread() { - return workerCountOf(ctl.get()) < corePoolSize && - addWorker(null, true); - } - - /** - * Starts all core threads, causing them to idly wait for work. This - * overrides the default policy of starting core threads only when - * new tasks are executed. - * - * @return the number of threads started - */ - public int prestartAllCoreThreads() { - int n = 0; - while (addWorker(null, true)) - ++n; - return n; - } - - /** - * Returns true if this pool allows core threads to time out and - * terminate if no tasks arrive within the keepAlive time, being - * replaced if needed when new tasks arrive. When true, the same - * keep-alive policy applying to non-core threads applies also to - * core threads. When false (the default), core threads are never - * terminated due to lack of incoming tasks. - * - * @return {@code true} if core threads are allowed to time out, - * else {@code false} - * - * @since 1.6 - */ - public boolean allowsCoreThreadTimeOut() { - return allowCoreThreadTimeOut; - } - - /** - * Sets the policy governing whether core threads may time out and - * terminate if no tasks arrive within the keep-alive time, being - * replaced if needed when new tasks arrive. When false, core - * threads are never terminated due to lack of incoming - * tasks. When true, the same keep-alive policy applying to - * non-core threads applies also to core threads. To avoid - * continual thread replacement, the keep-alive time must be - * greater than zero when setting {@code true}. This method - * should in general be called before the pool is actively used. - * - * @param value {@code true} if should time out, else {@code false} - * @throws IllegalArgumentException if value is {@code true} - * and the current keep-alive time is not greater than zero - * - * @since 1.6 - */ - public void allowCoreThreadTimeOut(boolean value) { - if (value && keepAliveTime <= 0) - throw new IllegalArgumentException("Core threads must have nonzero keep alive times"); - if (value != allowCoreThreadTimeOut) { - allowCoreThreadTimeOut = value; - if (value) - interruptIdleWorkers(); - } - } - - /** - * Sets the maximum allowed number of threads. This overrides any - * value set in the constructor. If the new value is smaller than - * the current value, excess existing threads will be - * terminated when they next become idle. - * - * @param maximumPoolSize the new maximum - * @throws IllegalArgumentException if the new maximum is - * less than or equal to zero, or - * less than the {@linkplain #getCorePoolSize core pool size} - * @see #getMaximumPoolSize - */ - public void setMaximumPoolSize(int maximumPoolSize) { - if (maximumPoolSize <= 0 || maximumPoolSize < corePoolSize) - throw new IllegalArgumentException(); - this.maximumPoolSize = maximumPoolSize; - if (workerCountOf(ctl.get()) > maximumPoolSize) - interruptIdleWorkers(); - } - - /** - * Returns the maximum allowed number of threads. - * - * @return the maximum allowed number of threads - * @see #setMaximumPoolSize - */ - public int getMaximumPoolSize() { - return maximumPoolSize; - } - - /** - * Sets the time limit for which threads may remain idle before - * being terminated. If there are more than the core number of - * threads currently in the pool, after waiting this amount of - * time without processing a task, excess threads will be - * terminated. This overrides any value set in the constructor. - * - * @param time the time to wait. A time value of zero will cause - * excess threads to terminate immediately after executing tasks. - * @param unit the time unit of the {@code time} argument - * @throws IllegalArgumentException if {@code time} less than zero or - * if {@code time} is zero and {@code allowsCoreThreadTimeOut} - * @see #getKeepAliveTime - */ - public void setKeepAliveTime(long time, TimeUnit unit) { - if (time < 0) - throw new IllegalArgumentException(); - if (time == 0 && allowsCoreThreadTimeOut()) - throw new IllegalArgumentException("Core threads must have nonzero keep alive times"); - long keepAliveTime = unit.toNanos(time); - long delta = keepAliveTime - this.keepAliveTime; - this.keepAliveTime = keepAliveTime; - if (delta < 0) - interruptIdleWorkers(); - } - - /** - * Returns the thread keep-alive time, which is the amount of time - * that threads in excess of the core pool size may remain - * idle before being terminated. - * - * @param unit the desired time unit of the result - * @return the time limit - * @see #setKeepAliveTime - */ - public long getKeepAliveTime(TimeUnit unit) { - return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS); - } - - /* User-level queue utilities */ - - /** - * Returns the task queue used by this executor. Access to the - * task queue is intended primarily for debugging and monitoring. - * This queue may be in active use. Retrieving the task queue - * does not prevent queued tasks from executing. - * - * @return the task queue - */ - public BlockingQueue getQueue() { - return workQueue; - } - - /** - * Removes this task from the executor's internal queue if it is - * present, thus causing it not to be run if it has not already - * started. - * - *

This method may be useful as one part of a cancellation - * scheme. It may fail to remove tasks that have been converted - * into other forms before being placed on the internal queue. For - * example, a task entered using {@code submit} might be - * converted into a form that maintains {@code Future} status. - * However, in such cases, method {@link #purge} may be used to - * remove those Futures that have been cancelled. - * - * @param task the task to remove - * @return true if the task was removed - */ - public boolean remove(Runnable task) { - boolean removed = workQueue.remove(task); - tryTerminate(); // In case SHUTDOWN and now empty - return removed; - } - - /** - * Tries to remove from the work queue all {@link Future} - * tasks that have been cancelled. This method can be useful as a - * storage reclamation operation, that has no other impact on - * functionality. Cancelled tasks are never executed, but may - * accumulate in work queues until worker threads can actively - * remove them. Invoking this method instead tries to remove them now. - * However, this method may fail to remove tasks in - * the presence of interference by other threads. - */ - public void purge() { - final BlockingQueue q = workQueue; - try { - Iterator it = q.iterator(); - while (it.hasNext()) { - Runnable r = (Runnable)it.next(); - if (r instanceof Future && ((Future)r).isCancelled()) - it.remove(); - } - } catch (ConcurrentModificationException fallThrough) { - // Take slow path if we encounter interference during traversal. - // Make copy for traversal and call remove for cancelled entries. - // The slow path is more likely to be O(N*N). - Object[] arr = q.toArray(); - for (int i=0; i 0 - return runStateAtLeast(ctl.get(), TIDYING) ? 0 - : workers.size(); - } finally { - mainLock.unlock(); - } - } - - /** - * Returns the approximate number of threads that are actively - * executing tasks. - * - * @return the number of threads - */ - public int getActiveCount() { - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - int n = 0; - for (Iterator itr = workers.iterator(); itr.hasNext();) { - Worker w = (Worker)itr.next(); - if (w.isLocked()) - ++n; - } - return n; - } finally { - mainLock.unlock(); - } - } - - /** - * Returns the largest number of threads that have ever - * simultaneously been in the pool. - * - * @return the number of threads - */ - public int getLargestPoolSize() { - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - return largestPoolSize; - } finally { - mainLock.unlock(); - } - } - - /** - * Returns the approximate total number of tasks that have ever been - * scheduled for execution. Because the states of tasks and - * threads may change dynamically during computation, the returned - * value is only an approximation. - * - * @return the number of tasks - */ - public long getTaskCount() { - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - long n = completedTaskCount; - for (Iterator itr = workers.iterator(); itr.hasNext();) { - Worker w = (Worker)itr.next(); - n += w.completedTasks; - if (w.isLocked()) - ++n; - } - return n + workQueue.size(); - } finally { - mainLock.unlock(); - } - } - - /** - * Returns the approximate total number of tasks that have - * completed execution. Because the states of tasks and threads - * may change dynamically during computation, the returned value - * is only an approximation, but one that does not ever decrease - * across successive calls. - * - * @return the number of tasks - */ - public long getCompletedTaskCount() { - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - long n = completedTaskCount; - for (Iterator itr = workers.iterator(); itr.hasNext();) { - Worker w = (Worker)itr.next(); - n += w.completedTasks; - } - return n; - } finally { - mainLock.unlock(); - } - } - - /* Extension hooks */ - - /** - * Method invoked prior to executing the given Runnable in the - * given thread. This method is invoked by thread {@code t} that - * will execute task {@code r}, and may be used to re-initialize - * ThreadLocals, or to perform logging. - * - *

This implementation does nothing, but may be customized in - * subclasses. Note: To properly nest multiple overridings, subclasses - * should generally invoke {@code super.beforeExecute} at the end of - * this method. - * - * @param t the thread that will run task {@code r} - * @param r the task that will be executed - */ - protected void beforeExecute(Thread t, Runnable r) { } - - /** - * Method invoked upon completion of execution of the given Runnable. - * This method is invoked by the thread that executed the task. If - * non-null, the Throwable is the uncaught {@code RuntimeException} - * or {@code Error} that caused execution to terminate abruptly. - * - *

This implementation does nothing, but may be customized in - * subclasses. Note: To properly nest multiple overridings, subclasses - * should generally invoke {@code super.afterExecute} at the - * beginning of this method. - * - *

Note: When actions are enclosed in tasks (such as - * {@link FutureTask}) either explicitly or via methods such as - * {@code submit}, these task objects catch and maintain - * computational exceptions, and so they do not cause abrupt - * termination, and the internal exceptions are not - * passed to this method. If you would like to trap both kinds of - * failures in this method, you can further probe for such cases, - * as in this sample subclass that prints either the direct cause - * or the underlying exception if a task has been aborted: - * - *

 {@code
-     * class ExtendedExecutor extends ThreadPoolExecutor {
-     *   // ...
-     *   protected void afterExecute(Runnable r, Throwable t) {
-     *     super.afterExecute(r, t);
-     *     if (t == null && r instanceof Future) {
-     *       try {
-     *         Object result = ((Future) r).get();
-     *       } catch (CancellationException ce) {
-     *           t = ce;
-     *       } catch (ExecutionException ee) {
-     *           t = ee.getCause();
-     *       } catch (InterruptedException ie) {
-     *           Thread.currentThread().interrupt(); // ignore/reset
-     *       }
-     *     }
-     *     if (t != null)
-     *       System.out.println(t);
-     *   }
-     * }}
- * - * @param r the runnable that has completed - * @param t the exception that caused termination, or null if - * execution completed normally - */ - protected void afterExecute(Runnable r, Throwable t) { } - - /** - * Method invoked when the Executor has terminated. Default - * implementation does nothing. Note: To properly nest multiple - * overridings, subclasses should generally invoke - * {@code super.terminated} within this method. - */ - protected void terminated() { } - - /* Predefined RejectedExecutionHandlers */ - - /** - * A handler for rejected tasks that runs the rejected task - * directly in the calling thread of the {@code execute} method, - * unless the executor has been shut down, in which case the task - * is discarded. - */ - public static class CallerRunsPolicy implements RejectedExecutionHandler { - /** - * Creates a {@code CallerRunsPolicy}. - */ - public CallerRunsPolicy() { } - - /** - * Executes task r in the caller's thread, unless the executor - * has been shut down, in which case the task is discarded. - * - * @param r the runnable task requested to be executed - * @param e the executor attempting to execute this task - */ - public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { - if (!e.isShutdown()) { - r.run(); - } - } - } - - /** - * A handler for rejected tasks that throws a - * {@code RejectedExecutionException}. - */ - public static class AbortPolicy implements RejectedExecutionHandler { - /** - * Creates an {@code AbortPolicy}. - */ - public AbortPolicy() { } - - /** - * Always throws RejectedExecutionException. - * - * @param r the runnable task requested to be executed - * @param e the executor attempting to execute this task - * @throws RejectedExecutionException always. - */ - public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { - throw new RejectedExecutionException(); - } - } - - /** - * A handler for rejected tasks that silently discards the - * rejected task. - */ - public static class DiscardPolicy implements RejectedExecutionHandler { - /** - * Creates a {@code DiscardPolicy}. - */ - public DiscardPolicy() { } - - /** - * Does nothing, which has the effect of discarding task r. - * - * @param r the runnable task requested to be executed - * @param e the executor attempting to execute this task - */ - public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { - } - } - - /** - * A handler for rejected tasks that discards the oldest unhandled - * request and then retries {@code execute}, unless the executor - * is shut down, in which case the task is discarded. - */ - public static class DiscardOldestPolicy implements RejectedExecutionHandler { - /** - * Creates a {@code DiscardOldestPolicy} for the given executor. - */ - public DiscardOldestPolicy() { } - - /** - * Obtains and ignores the next task that the executor - * would otherwise execute, if one is immediately available, - * and then retries execution of task r, unless the executor - * is shut down, in which case task r is instead discarded. - * - * @param r the runnable task requested to be executed - * @param e the executor attempting to execute this task - */ - public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { - if (!e.isShutdown()) { - e.getQueue().poll(); - e.execute(r); - } - } - } -} diff --git a/src/actors/scala/actors/threadpool/TimeUnit.java b/src/actors/scala/actors/threadpool/TimeUnit.java deleted file mode 100644 index c443750e33..0000000000 --- a/src/actors/scala/actors/threadpool/TimeUnit.java +++ /dev/null @@ -1,407 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -import java.io.InvalidObjectException; -import java.io.ObjectStreamException; - -/** - * A TimeUnit represents time durations at a given unit of - * granularity and provides utility methods to convert across units, - * and to perform timing and delay operations in these units. A - * TimeUnit does not maintain time information, but only - * helps organize and use time representations that may be maintained - * separately across various contexts. A nanosecond is defined as one - * thousandth of a microsecond, a microsecond as one thousandth of a - * millisecond, a millisecond as one thousandth of a second, a minute - * as sixty seconds, an hour as sixty minutes, and a day as twenty four - * hours. - * - *

A TimeUnit is mainly used to inform time-based methods - * how a given timing parameter should be interpreted. For example, - * the following code will timeout in 50 milliseconds if the {@link - * edu.emory.mathcs.backport.java.util.concurrent.locks.Lock lock} is not available: - * - *

  Lock lock = ...;
-  *  if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
-  * 
- * while this code will timeout in 50 seconds: - *
-  *  Lock lock = ...;
-  *  if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
-  * 
- * - * Note however, that there is no guarantee that a particular timeout - * implementation will be able to notice the passage of time at the - * same granularity as the given TimeUnit. - * - * @since 1.5 - * @author Doug Lea - */ -public abstract class TimeUnit implements java.io.Serializable { - - public static final TimeUnit NANOSECONDS = new TimeUnit(0, "NANOSECONDS") { - private final static long serialVersionUID = 535148490883208361L; - public long toNanos(long d) { return d; } - public long toMicros(long d) { return d/(C1/C0); } - public long toMillis(long d) { return d/(C2/C0); } - public long toSeconds(long d) { return d/(C3/C0); } - public long toMinutes(long d) { return d/(C4/C0); } - public long toHours(long d) { return d/(C5/C0); } - public long toDays(long d) { return d/(C6/C0); } - public long convert(long d, TimeUnit u) { return u.toNanos(d); } - int excessNanos(long d, long m) { return (int)(d - (m*C2)); } - }; - public static final TimeUnit MICROSECONDS = new TimeUnit(1, "MICROSECONDS") { - private final static long serialVersionUID = 2185906575929579108L; - public long toNanos(long d) { return x(d, C1/C0, MAX/(C1/C0)); } - public long toMicros(long d) { return d; } - public long toMillis(long d) { return d/(C2/C1); } - public long toSeconds(long d) { return d/(C3/C1); } - public long toMinutes(long d) { return d/(C4/C1); } - public long toHours(long d) { return d/(C5/C1); } - public long toDays(long d) { return d/(C6/C1); } - public long convert(long d, TimeUnit u) { return u.toMicros(d); } - int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); } - }; - public static final TimeUnit MILLISECONDS = new TimeUnit(2, "MILLISECONDS") { - private final static long serialVersionUID = 9032047794123325184L; - public long toNanos(long d) { return x(d, C2/C0, MAX/(C2/C0)); } - public long toMicros(long d) { return x(d, C2/C1, MAX/(C2/C1)); } - public long toMillis(long d) { return d; } - public long toSeconds(long d) { return d/(C3/C2); } - public long toMinutes(long d) { return d/(C4/C2); } - public long toHours(long d) { return d/(C5/C2); } - public long toDays(long d) { return d/(C6/C2); } - public long convert(long d, TimeUnit u) { return u.toMillis(d); } - int excessNanos(long d, long m) { return 0; } - }; - public static final TimeUnit SECONDS = new TimeUnit(3, "SECONDS") { - private final static long serialVersionUID = 227755028449378390L; - public long toNanos(long d) { return x(d, C3/C0, MAX/(C3/C0)); } - public long toMicros(long d) { return x(d, C3/C1, MAX/(C3/C1)); } - public long toMillis(long d) { return x(d, C3/C2, MAX/(C3/C2)); } - public long toSeconds(long d) { return d; } - public long toMinutes(long d) { return d/(C4/C3); } - public long toHours(long d) { return d/(C5/C3); } - public long toDays(long d) { return d/(C6/C3); } - public long convert(long d, TimeUnit u) { return u.toSeconds(d); } - int excessNanos(long d, long m) { return 0; } - }; - public static final TimeUnit MINUTES = new TimeUnit(4, "MINUTES") { - private final static long serialVersionUID = 1827351566402609187L; - public long toNanos(long d) { return x(d, C4/C0, MAX/(C4/C0)); } - public long toMicros(long d) { return x(d, C4/C1, MAX/(C4/C1)); } - public long toMillis(long d) { return x(d, C4/C2, MAX/(C4/C2)); } - public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); } - public long toMinutes(long d) { return d; } - public long toHours(long d) { return d/(C5/C4); } - public long toDays(long d) { return d/(C6/C4); } - public long convert(long d, TimeUnit u) { return u.toMinutes(d); } - int excessNanos(long d, long m) { return 0; } - }; - public static final TimeUnit HOURS = new TimeUnit(5, "HOURS") { - private final static long serialVersionUID = -6438436134732089810L; - public long toNanos(long d) { return x(d, C5/C0, MAX/(C5/C0)); } - public long toMicros(long d) { return x(d, C5/C1, MAX/(C5/C1)); } - public long toMillis(long d) { return x(d, C5/C2, MAX/(C5/C2)); } - public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); } - public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); } - public long toHours(long d) { return d; } - public long toDays(long d) { return d/(C6/C5); } - public long convert(long d, TimeUnit u) { return u.toHours(d); } - int excessNanos(long d, long m) { return 0; } - }; - public static final TimeUnit DAYS = new TimeUnit(6, "DAYS") { - private final static long serialVersionUID = 567463171959674600L; - public long toNanos(long d) { return x(d, C6/C0, MAX/(C6/C0)); } - public long toMicros(long d) { return x(d, C6/C1, MAX/(C6/C1)); } - public long toMillis(long d) { return x(d, C6/C2, MAX/(C6/C2)); } - public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); } - public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); } - public long toHours(long d) { return x(d, C6/C5, MAX/(C6/C5)); } - public long toDays(long d) { return d; } - public long convert(long d, TimeUnit u) { return u.toDays(d); } - int excessNanos(long d, long m) { return 0; } - }; - - private static final TimeUnit[] values = new TimeUnit[] - { NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS }; - - public static TimeUnit[] values() { - return (TimeUnit[])values.clone(); - } - - /** - * Returns the enum constant of this type with the specified name. The - * string must match exactly an identifier used to declare an - * enum constant in this type. (Extraneous whitespace characters are not - * permitted.) - * - * @param name the name of the enum constant to be returned - * @return the enum constant with the specified name - * @throws IllegalArgumentException - * if this enum type has no constant with the specified name - */ - public static TimeUnit valueOf(String name) { - for (int i = 0; i < values.length; i++) { - if (values[i].name.equals(name)) { - return values[i]; - } - } - throw new IllegalArgumentException("No enum const TimeUnit." + name); - } - - /** - * The ordinal of this unit. This is useful both for {@link #ordinal()} - * and to maintain serialization consistence with earlier versions. - */ - private final int index; - - /** name of this unit */ - private final String name; - - /** Internal constructor */ - TimeUnit(int index, String name) { - this.index = index; - this.name = name; - } - - // Handy constants for conversion methods - static final long C0 = 1; - static final long C1 = C0 * 1000; - static final long C2 = C1 * 1000; - static final long C3 = C2 * 1000; - static final long C4 = C3 * 60; - static final long C5 = C4 * 60; - static final long C6 = C5 * 24; - - static final long MAX = Long.MAX_VALUE; - - /** - * Scale d by m, checking for overflow. - * This has a short name to make above code more readable. - */ - static long x(long d, long m, long over) { - if (d > over) return Long.MAX_VALUE; - if (d < -over) return Long.MIN_VALUE; - return d * m; - } - - /** - * Convert the given time duration in the given unit to this - * unit. Conversions from finer to coarser granularities - * truncate, so lose precision. For example converting - * 999 milliseconds to seconds results in - * 0. Conversions from coarser to finer granularities - * with arguments that would numerically overflow saturate to - * Long.MIN_VALUE if negative or Long.MAX_VALUE - * if positive. - * - *

For example, to convert 10 minutes to milliseconds, use: - * TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES) - * - * @param sourceDuration the time duration in the given sourceUnit - * @param sourceUnit the unit of the sourceDuration argument - * @return the converted duration in this unit, - * or Long.MIN_VALUE if conversion would negatively - * overflow, or Long.MAX_VALUE if it would positively overflow. - */ - public abstract long convert(long sourceDuration, TimeUnit sourceUnit); - - /** - * Equivalent to NANOSECONDS.convert(duration, this). - * @param duration the duration - * @return the converted duration, - * or Long.MIN_VALUE if conversion would negatively - * overflow, or Long.MAX_VALUE if it would positively overflow. - * @see #convert - */ - public abstract long toNanos(long duration); - - /** - * Equivalent to MICROSECONDS.convert(duration, this). - * @param duration the duration - * @return the converted duration, - * or Long.MIN_VALUE if conversion would negatively - * overflow, or Long.MAX_VALUE if it would positively overflow. - * @see #convert - */ - public abstract long toMicros(long duration); - - /** - * Equivalent to MILLISECONDS.convert(duration, this). - * @param duration the duration - * @return the converted duration, - * or Long.MIN_VALUE if conversion would negatively - * overflow, or Long.MAX_VALUE if it would positively overflow. - * @see #convert - */ - public abstract long toMillis(long duration); - - /** - * Equivalent to SECONDS.convert(duration, this). - * @param duration the duration - * @return the converted duration, - * or Long.MIN_VALUE if conversion would negatively - * overflow, or Long.MAX_VALUE if it would positively overflow. - * @see #convert - */ - public abstract long toSeconds(long duration); - - /** - * Equivalent to MINUTES.convert(duration, this). - * @param duration the duration - * @return the converted duration, - * or Long.MIN_VALUE if conversion would negatively - * overflow, or Long.MAX_VALUE if it would positively overflow. - * @see #convert - * @since 1.6 - */ - public abstract long toMinutes(long duration); - - /** - * Equivalent to HOURS.convert(duration, this). - * @param duration the duration - * @return the converted duration, - * or Long.MIN_VALUE if conversion would negatively - * overflow, or Long.MAX_VALUE if it would positively overflow. - * @see #convert - * @since 1.6 - */ - public abstract long toHours(long duration); - - /** - * Equivalent to DAYS.convert(duration, this). - * @param duration the duration - * @return the converted duration - * @see #convert - * @since 1.6 - */ - public abstract long toDays(long duration); - - /** - * Utility to compute the excess-nanosecond argument to wait, - * sleep, join. - * @param d the duration - * @param m the number of milliseconds - * @return the number of nanoseconds - */ - abstract int excessNanos(long d, long m); - - /** - * Returns the name of this enum constant, exactly as declared in its enum - * declaration. Most programmers should use the - * {@link #toString()} method in preference to this one, as the toString - * method may return a more user-friendly name. This method is - * designed primarily for use in specialized situations where correctness - * depends on getting the exact name, which will not vary from release to - * release. - * - * @return the name of this enum constant - */ - public String name() { - return name; - } - - /** - * Returns the ordinal of this enumeration constant (its position in its - * enum declaration, where the initial constant is assigned an ordinal of - * zero). Most programmers will have no use for this method. It is - * designed for use by sophisticated enum-based data structures, such as - * EnumSet and EnumMap. - * - * @return the ordinal of this enumeration constant - */ - public int ordinal() { - return index; - } - - /* - * Guarantees that deserialized objects will be referentially equal to the - * standard enumeration objects. - */ - protected Object readResolve() throws ObjectStreamException { - try { - return valueOf(name); - } catch (IllegalArgumentException e) { - throw new InvalidObjectException(name - + " is not a valid enum for TimeUnit"); - } - } - - /** - * Performs a timed Object.wait using this time unit. - * This is a convenience method that converts timeout arguments - * into the form required by the Object.wait method. - * - *

For example, you could implement a blocking poll - * method (see {@link BlockingQueue#poll BlockingQueue.poll}) - * using: - * - *

  public synchronized  Object poll(long timeout, TimeUnit unit) throws InterruptedException {
-     *    while (empty) {
-     *      unit.timedWait(this, timeout);
-     *      ...
-     *    }
-     *  }
- * - * @param obj the object to wait on - * @param timeout the maximum time to wait. If less than - * or equal to zero, do not wait at all. - * @throws InterruptedException if interrupted while waiting. - * @see java.lang.Object#wait(long, int) - */ - public void timedWait(Object obj, long timeout) - throws InterruptedException { - if (timeout > 0) { - long ms = toMillis(timeout); - int ns = excessNanos(timeout, ms); - obj.wait(ms, ns); - } - } - - /** - * Performs a timed Thread.join using this time unit. - * This is a convenience method that converts time arguments into the - * form required by the Thread.join method. - * @param thread the thread to wait for - * @param timeout the maximum time to wait. If less than - * or equal to zero, do not wait at all. - * @throws InterruptedException if interrupted while waiting. - * @see java.lang.Thread#join(long, int) - */ - public void timedJoin(Thread thread, long timeout) - throws InterruptedException { - if (timeout > 0) { - long ms = toMillis(timeout); - int ns = excessNanos(timeout, ms); - thread.join(ms, ns); - } - } - - /** - * Performs a Thread.sleep using this unit. - * This is a convenience method that converts time arguments into the - * form required by the Thread.sleep method. - * @param timeout the maximum time to sleep. If less than - * or equal to zero, do not sleep at all. - * @throws InterruptedException if interrupted while sleeping. - * @see java.lang.Thread#sleep - */ - public void sleep(long timeout) throws InterruptedException { - if (timeout > 0) { - long ms = toMillis(timeout); - int ns = excessNanos(timeout, ms); - Thread.sleep(ms, ns); - } - } - - public String toString() { - return name; - } -} diff --git a/src/actors/scala/actors/threadpool/TimeoutException.java b/src/actors/scala/actors/threadpool/TimeoutException.java deleted file mode 100644 index c6fdbe5dc4..0000000000 --- a/src/actors/scala/actors/threadpool/TimeoutException.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool; - -/** - * Exception thrown when a blocking operation times out. Blocking - * operations for which a timeout is specified need a means to - * indicate that the timeout has occurred. For many such operations it - * is possible to return a value that indicates timeout; when that is - * not possible or desirable then TimeoutException should be - * declared and thrown. - * - * @since 1.5 - * @author Doug Lea - */ -public class TimeoutException extends Exception { - private static final long serialVersionUID = 1900926677490660714L; - - /** - * Constructs a TimeoutException with no specified detail - * message. - */ - public TimeoutException() {} - - /** - * Constructs a TimeoutException with the specified detail - * message. - * - * @param message the detail message - */ - public TimeoutException(String message) { - super(message); - } -} diff --git a/src/actors/scala/actors/threadpool/helpers/FIFOWaitQueue.java b/src/actors/scala/actors/threadpool/helpers/FIFOWaitQueue.java deleted file mode 100644 index 432b851f3e..0000000000 --- a/src/actors/scala/actors/threadpool/helpers/FIFOWaitQueue.java +++ /dev/null @@ -1,85 +0,0 @@ -package scala.actors.threadpool.helpers; - -import java.util.Collection; -import java.util.ArrayList; -import java.util.List; - -/** - * Simple linked list queue used in FIFOSemaphore. - * Methods are not synchronized; they depend on synch of callers. - * Must be public, since it is used by Semaphore (outside this package). - * NOTE: this class is NOT present in java.util.concurrent. - **/ - -public class FIFOWaitQueue extends WaitQueue implements java.io.Serializable { - - private final static long serialVersionUID = 2416444691925378811L; - - protected transient WaitNode head_ = null; - protected transient WaitNode tail_ = null; - - public FIFOWaitQueue() {} - - public void insert(WaitNode w) { - if (tail_ == null) - head_ = tail_ = w; - else { - tail_.next = w; - tail_ = w; - } - } - - public WaitNode extract() { - if (head_ == null) - return null; - else { - WaitNode w = head_; - head_ = w.next; - if (head_ == null) - tail_ = null; - w.next = null; - return w; - } - } - - public void putBack(WaitNode w) { - w.next = head_; - head_ = w; - if (tail_ == null) - tail_ = w; - } - - public boolean hasNodes() { - return head_ != null; - } - - public int getLength() { - int count = 0; - WaitNode node = head_; - while (node != null) { - if (node.waiting) count++; - node = node.next; - } - return count; - } - - public Collection getWaitingThreads() { - List list = new ArrayList(); - int count = 0; - WaitNode node = head_; - while (node != null) { - if (node.waiting) list.add(node.owner); - node = node.next; - } - return list; - } - - public boolean isWaiting(Thread thread) { - if (thread == null) throw new NullPointerException(); - for (WaitNode node = head_; node != null; node = node.next) { - if (node.waiting && node.owner == thread) return true; - } - return false; - } - -} diff --git a/src/actors/scala/actors/threadpool/helpers/NanoTimer.java b/src/actors/scala/actors/threadpool/helpers/NanoTimer.java deleted file mode 100644 index f3edf13565..0000000000 --- a/src/actors/scala/actors/threadpool/helpers/NanoTimer.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Written by Dawid Kurzyniec and released to the public domain, as explained - * at http://creativecommons.org/licenses/publicdomain - */ -package scala.actors.threadpool.helpers; - -/** - * Interface to specify custom implementation of precise timer. - * - * @author Dawid Kurzyniec - * @version 1.0 - */ -public interface NanoTimer { - /** - * Returns the current value of the most precise available system timer, - * in nanoseconds. This method can only be used to measure elapsed time and - * is not related to any other notion of system or wall-clock time. The - * value returned represents nanoseconds since some fixed but arbitrary - * time (perhaps in the future, so values may be negative). This method - * provides nanosecond precision, but not necessarily nanosecond accuracy. - * No guarantees are made about how frequently values change. Differences - * in successive calls that span greater than approximately 292 years - * (263 nanoseconds) will not accurately compute elapsed time due to - * numerical overflow. - * - * @return The current value of the system timer, in nanoseconds. - */ - long nanoTime(); -} diff --git a/src/actors/scala/actors/threadpool/helpers/ThreadHelpers.java b/src/actors/scala/actors/threadpool/helpers/ThreadHelpers.java deleted file mode 100644 index 13da20c4d6..0000000000 --- a/src/actors/scala/actors/threadpool/helpers/ThreadHelpers.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Written by Dawid Kurzyniec and released to the public domain, as explained - * at http://creativecommons.org/licenses/publicdomain - */ -package scala.actors.threadpool.helpers; - -/** - * Emulation of some new functionality present in java.lang.Thread in J2SE 5.0. - * - * @author Dawid Kurzyniec - * @version 1.0 - */ -public class ThreadHelpers { - - private ThreadHelpers() {} - - /** - * Returns wrapped runnable that ensures that if an exception occurs - * during the execution, the specified exception handler is invoked. - * @param runnable runnable for which exceptions are to be intercepted - * @param handler the exception handler to call when exception occurs - * during execution of the given runnable - * @return wrapped runnable - */ - public static Runnable assignExceptionHandler(final Runnable runnable, - final UncaughtExceptionHandler handler) - { - if (runnable == null || handler == null) { - throw new NullPointerException(); - } - return new Runnable() { - public void run() { - try { - runnable.run(); - } - catch (Throwable error) { - try { - handler.uncaughtException(Thread.currentThread(), error); - } - catch (Throwable ignore) {} - } - } - }; - } - - /** - * Abstraction of the exception handler which receives notifications of - * exceptions occurred possibly in various parts of the system. Exception - * handlers present attractive approach to exception handling in multi-threaded - * systems, as they can handle exceptions that occurred in different threads. - *

- * This class is analogous to Thread.UncaughtExceptionHandler in J2SE 5.0. - * Obviously you cannot use it the same way, e.g. you cannot assign the - * handler to the thread so that it is invoked when thread terminates. - * However, it can be {@link ThreadHelpers#assignExceptionHandler emulated}. - */ - public static interface UncaughtExceptionHandler { - /** - * Notification of the uncaught exception that occurred within specified - * thread. - * @param thread the thread where the exception occurred - * @param error the exception - */ - void uncaughtException(Thread thread, Throwable error); - } -} diff --git a/src/actors/scala/actors/threadpool/helpers/Utils.java b/src/actors/scala/actors/threadpool/helpers/Utils.java deleted file mode 100644 index d12389215d..0000000000 --- a/src/actors/scala/actors/threadpool/helpers/Utils.java +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Written by Dawid Kurzyniec, based on code written by Doug Lea with assistance - * from members of JCP JSR-166 Expert Group. Released to the public domain, - * as explained at http://creativecommons.org/licenses/publicdomain. - * - * Thanks to Craig Mattocks for suggesting to use sun.misc.Perf. - */ - -package scala.actors.threadpool.helpers; - -//import edu.emory.mathcs.backport.java.util.*; -import scala.actors.threadpool.*; -import scala.actors.threadpool.locks.*; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.lang.reflect.Array; -import java.util.Iterator; -import java.util.Collection; - -/** - *

- * This class groups together the functionality of java.util.concurrent that - * cannot be fully and reliably implemented in backport, but for which some - * form of emulation is possible. - *

- * Currently, this class contains methods related to nanosecond-precision - * timing, particularly via the {@link #nanoTime} method. To measure time - * accurately, this method by default uses java.sun.Perf on - * JDK1.4.2 and it falls back to System.currentTimeMillis - * on earlier JDKs. - * - * @author Dawid Kurzyniec - * @version 1.0 - */ -public final class Utils { - - private final static NanoTimer nanoTimer; - private final static String providerProp = - "edu.emory.mathcs.backport.java.util.concurrent.NanoTimerProvider"; - - static { - NanoTimer timer = null; - try { - String nanoTimerClassName = - AccessController.doPrivileged(new PrivilegedAction() { - public String run() { - return System.getProperty(providerProp); - } - }); - if (nanoTimerClassName != null) { - Class cls = Class.forName(nanoTimerClassName); - timer = (NanoTimer) cls.newInstance(); - } - } - catch (Exception e) { - System.err.println("WARNING: unable to load the system-property-defined " + - "nanotime provider; switching to the default"); - e.printStackTrace(); - } - - if (timer == null) { - try { - timer = new SunPerfProvider(); - } - catch (Throwable e) {} - } - - if (timer == null) { - timer = new MillisProvider(); - } - - nanoTimer = timer; - } - - private Utils() {} - - /** - * Returns the current value of the most precise available system timer, - * in nanoseconds. This method can only be used to measure elapsed time and - * is not related to any other notion of system or wall-clock time. The - * value returned represents nanoseconds since some fixed but arbitrary - * time (perhaps in the future, so values may be negative). This method - * provides nanosecond precision, but not necessarily nanosecond accuracy. - * No guarantees are made about how frequently values change. Differences - * in successive calls that span greater than approximately 292 years - * (2^63 nanoseconds) will not accurately compute elapsed time due to - * numerical overflow. - *

- * Implementation note:By default, this method uses - * sun.misc.Perf on Java 1.4.2, and falls back to - * System.currentTimeMillis() emulation on earlier JDKs. Custom - * timer can be provided via the system property - * edu.emory.mathcs.backport.java.util.concurrent.NanoTimerProvider. - * The value of the property should name a class implementing - * {@link NanoTimer} interface. - *

- * Note: on JDK 1.4.2, sun.misc.Perf timer seems to have - * resolution of the order of 1 microsecond, measured on Linux. - * - * @return The current value of the system timer, in nanoseconds. - */ - public static long nanoTime() { - return nanoTimer.nanoTime(); - } - - /** - * Causes the current thread to wait until it is signalled or interrupted, - * or the specified waiting time elapses. This method originally appears - * in the {@link Condition} interface, but it was moved to here since it - * can only be emulated, with very little accuracy guarantees: the - * efficient implementation requires accurate nanosecond timer and native - * support for nanosecond-precision wait queues, which are not usually - * present in JVMs prior to 1.5. Loss of precision may cause total waiting - * times to be systematically shorter than specified when re-waits occur. - * - *

The lock associated with this condition is atomically - * released and the current thread becomes disabled for thread scheduling - * purposes and lies dormant until one of five things happens: - *

    - *
  • Some other thread invokes the {@link - * edu.emory.mathcs.backport.java.util.concurrent.locks.Condition#signal} - * method for this - * Condition and the current thread happens to be chosen as the - * thread to be awakened; or - *
  • Some other thread invokes the {@link - * edu.emory.mathcs.backport.java.util.concurrent.locks.Condition#signalAll} - * method for this - * Condition; or - *
  • Some other thread {@link Thread#interrupt interrupts} the current - * thread, and interruption of thread suspension is supported; or - *
  • The specified waiting time elapses; or - *
  • A "spurious wakeup" occurs. - *
- * - *

In all cases, before this method can return the current thread must - * re-acquire the lock associated with this condition. When the - * thread returns it is guaranteed to hold this lock. - * - *

If the current thread: - *

    - *
  • has its interrupted status set on entry to this method; or - *
  • is {@link Thread#interrupt interrupted} while waiting - * and interruption of thread suspension is supported, - *
- * then {@link InterruptedException} is thrown and the current thread's - * interrupted status is cleared. It is not specified, in the first - * case, whether or not the test for interruption occurs before the lock - * is released. - * - *

The method returns an estimate of the number of nanoseconds - * remaining to wait given the supplied nanosTimeout - * value upon return, or a value less than or equal to zero if it - * timed out. Accuracy of this estimate is directly dependent on the - * accuracy of {@link #nanoTime}. This value can be used to determine - * whether and how long to re-wait in cases where the wait returns but an - * awaited condition still does not hold. Typical uses of this method take - * the following form: - * - *

-     * synchronized boolean aMethod(long timeout, TimeUnit unit) {
-     *   long nanosTimeout = unit.toNanos(timeout);
-     *   while (!conditionBeingWaitedFor) {
-     *     if (nanosTimeout > 0)
-     *         nanosTimeout = theCondition.awaitNanos(nanosTimeout);
-     *      else
-     *        return false;
-     *   }
-     *   // ...
-     * }
-     * 
- * - *

Implementation Considerations - *

The current thread is assumed to hold the lock associated with this - * Condition when this method is called. - * It is up to the implementation to determine if this is - * the case and if not, how to respond. Typically, an exception will be - * thrown (such as {@link IllegalMonitorStateException}) and the - * implementation must document that fact. - * - *

A condition implementation can favor responding to an interrupt over - * normal method return in response to a signal, or over indicating the - * elapse of the specified waiting time. In either case the implementation - * must ensure that the signal is redirected to another waiting thread, if - * there is one. - * - * @param cond the condition to wait for - * @param nanosTimeout the maximum time to wait, in nanoseconds - * @return A value less than or equal to zero if the wait has - * timed out; otherwise an estimate, that - * is strictly less than the nanosTimeout argument, - * of the time still remaining when this method returned. - * - * @throws InterruptedException if the current thread is interrupted (and - * interruption of thread suspension is supported). - */ - public static long awaitNanos(Condition cond, long nanosTimeout) - throws InterruptedException - { - if (nanosTimeout <= 0) return nanosTimeout; - long now = nanoTime(); - cond.await(nanosTimeout, TimeUnit.NANOSECONDS); - return nanosTimeout - (nanoTime() - now); - } - - private static final class SunPerfProvider implements NanoTimer { - final Perf perf; - final long multiplier, divisor; - SunPerfProvider() { - perf = - AccessController.doPrivileged(new PrivilegedAction() { - public Perf run() { - return Perf.getPerf(); - } - }); - // trying to avoid BOTH overflow and rounding errors - long numerator = 1000000000; - long denominator = perf.highResFrequency(); - long gcd = gcd(numerator, denominator); - this.multiplier = numerator / gcd; - this.divisor = denominator / gcd; - } - public long nanoTime() { - long ctr = perf.highResCounter(); - - // anything less sophisticated suffers either from rounding errors - // (FP arithmetics, backport v1.0) or overflow, when gcd is small - // (a bug in backport v1.0_01 reported by Ramesh Nethi) - - return ((ctr / divisor) * multiplier) + - (ctr % divisor) * multiplier / divisor; - - // even the above can theoretically cause problems if your JVM is - // running for sufficiently long time, but "sufficiently" means 292 - // years (worst case), or 30,000 years (common case). - - // Details: when the ticks ctr overflows, there is no way to avoid - // discontinuity in computed nanos, even in infinite arithmetics, - // unless we count number of overflows that the ctr went through - // since the JVM started. This follows from the fact that - // (2^64*multiplier/divisor) mod (2^64) > 0 in general case. - // Theoretically we could find out the number of overflows by - // checking System.currentTimeMillis(), but this is unreliable - // since the system time can unpredictably change during the JVM - // lifetime. - // The time to overflow is 2^63 / ticks frequency. With current - // ticks frequencies of several MHz, it gives about 30,000 years - // before the problem happens. If ticks frequency reaches 1 GHz, the - // time to overflow is 292 years. It is unlikely that the frequency - // ever exceeds 1 GHz. We could double the time to overflow - // (to 2^64 / frequency) by using unsigned arithmetics, e.g. by - // adding the following correction whenever the ticks is negative: - // -2*((Long.MIN_VALUE / divisor) * multiplier + - // (Long.MIN_VALUE % divisor) * multiplier / divisor) - // But, with the worst case of as much as 292 years, it does not - // seem justified. - } - } - - private static final class MillisProvider implements NanoTimer { - MillisProvider() {} - public long nanoTime() { - return System.currentTimeMillis() * 1000000; - } - } - - private static long gcd(long a, long b) { - long r; - while (b>0) { r = a % b; a = b; b = r; } - return a; - } - - - public static Object[] collectionToArray(Collection c) { - // guess the array size; expect to possibly be different - int len = c.size(); - Object[] arr = new Object[len]; - Iterator itr = c.iterator(); - int idx = 0; - while (true) { - while (idx < len && itr.hasNext()) { - arr[idx++] = itr.next(); - } - if (!itr.hasNext()) { - if (idx == len) return arr; - // otherwise have to trim - return Arrays.copyOf(arr, idx, Object[].class); - } - // otherwise, have to grow - int newcap = ((arr.length/2)+1)*3; - if (newcap < arr.length) { - // overflow - if (arr.length < Integer.MAX_VALUE) { - newcap = Integer.MAX_VALUE; - } - else { - throw new OutOfMemoryError("required array size too large"); - } - } - arr = Arrays.copyOf(arr, newcap, Object[].class); - len = newcap; - } - } - - public static Object[] collectionToArray(Collection c, Object[] a) { - Class aType = a.getClass(); - // guess the array size; expect to possibly be different - int len = c.size(); - Object[] arr = (a.length >= len ? a : - (Object[])Array.newInstance(aType.getComponentType(), len)); - Iterator itr = c.iterator(); - int idx = 0; - while (true) { - while (idx < len && itr.hasNext()) { - arr[idx++] = itr.next(); - } - if (!itr.hasNext()) { - if (idx == len) return arr; - if (arr == a) { - // orig array -> null terminate - a[idx] = null; - return a; - } - else { - // have to trim - return Arrays.copyOf(arr, idx, aType); - } - } - // otherwise, have to grow - int newcap = ((arr.length/2)+1)*3; - if (newcap < arr.length) { - // overflow - if (arr.length < Integer.MAX_VALUE) { - newcap = Integer.MAX_VALUE; - } - else { - throw new OutOfMemoryError("required array size too large"); - } - } - arr = Arrays.copyOf(arr, newcap, aType); - len = newcap; - } - } -} diff --git a/src/actors/scala/actors/threadpool/helpers/WaitQueue.java b/src/actors/scala/actors/threadpool/helpers/WaitQueue.java deleted file mode 100644 index bcbf29e5c2..0000000000 --- a/src/actors/scala/actors/threadpool/helpers/WaitQueue.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - based on file: QueuedSemaphore.java - Originally written by Doug Lea and released into the public domain. - This may be used for any purposes whatsoever without acknowledgment. - Thanks for the assistance and support of Sun Microsystems Labs, - and everyone contributing, testing, and using this code. - History: - Date Who What - 11Jun1998 dl Create public version - 5Aug1998 dl replaced int counters with longs - 24Aug1999 dl release(n): screen arguments - */ - -package scala.actors.threadpool.helpers; - -import java.util.Collection; -import scala.actors.threadpool.*; - -/** - * Base class for internal queue classes for semaphores, etc. - * Relies on subclasses to actually implement queue mechanics. - * NOTE: this class is NOT present in java.util.concurrent. - **/ - -public abstract class WaitQueue { - - public abstract void insert(WaitNode w); // assumed not to block - public abstract WaitNode extract(); // should return null if empty - public abstract void putBack(WaitNode w); - - public abstract boolean hasNodes(); - public abstract int getLength(); - public abstract Collection getWaitingThreads(); - public abstract boolean isWaiting(Thread thread); - - public static interface QueuedSync { - // invoked with sync on wait node, (atomically) just before enqueuing - boolean recheck(WaitNode node); - // invoked with sync on wait node, (atomically) just before signalling - void takeOver(WaitNode node); - } - - public static class WaitNode { - boolean waiting = true; - WaitNode next = null; - final Thread owner; - - public WaitNode() { - this.owner = Thread.currentThread(); - } - - public Thread getOwner() { - return owner; - } - - public synchronized boolean signal(QueuedSync sync) { - boolean signalled = waiting; - if (signalled) { - waiting = false; - notify(); - sync.takeOver(this); - } - return signalled; - } - - public synchronized boolean doTimedWait(QueuedSync sync, long nanos) - throws InterruptedException - { - if (sync.recheck(this) || !waiting) - return true; - else if (nanos <= 0) { - waiting = false; - return false; - } - else { - long deadline = Utils.nanoTime() + nanos; - try { - for (; ; ) { - TimeUnit.NANOSECONDS.timedWait(this, nanos); - if (!waiting) // definitely signalled - return true; - else { - nanos = deadline - Utils.nanoTime(); - if (nanos <= 0) { // timed out - waiting = false; - return false; - } - } - } - } - catch (InterruptedException ex) { - if (waiting) { // no notification - waiting = false; // invalidate for the signaller - throw ex; - } - else { // thread was interrupted after it was notified - Thread.currentThread().interrupt(); - return true; - } - } - } - } - - public synchronized void doWait(QueuedSync sync) - throws InterruptedException - { - if (!sync.recheck(this)) { - try { - while (waiting) wait(); - } - catch (InterruptedException ex) { - if (waiting) { // no notification - waiting = false; // invalidate for the signaller - throw ex; - } - else { // thread was interrupted after it was notified - Thread.currentThread().interrupt(); - return; - } - } - } - } - - public synchronized void doWaitUninterruptibly(QueuedSync sync) { - if (!sync.recheck(this)) { - boolean wasInterrupted = Thread.interrupted(); - try { - while (waiting) { - try { - wait(); - } - catch (InterruptedException ex) { - wasInterrupted = true; - // no need to notify; if we were signalled, we - // must be not waiting, and we'll act like signalled - } - } - } - finally { - if (wasInterrupted) Thread.currentThread().interrupt(); - } - } - } - } -} - diff --git a/src/actors/scala/actors/threadpool/locks/CondVar.java b/src/actors/scala/actors/threadpool/locks/CondVar.java deleted file mode 100644 index 44df1c0b97..0000000000 --- a/src/actors/scala/actors/threadpool/locks/CondVar.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - File: ConditionVariable.java - Originally written by Doug Lea and released into the public domain. - This may be used for any purposes whatsoever without acknowledgment. - Thanks for the assistance and support of Sun Microsystems Labs, - and everyone contributing, testing, and using this code. - History: - Date Who What - 11Jun1998 dl Create public version - */ - -package scala.actors.threadpool.locks; - -import java.util.Collection; -import java.util.Date; -import scala.actors.threadpool.*; -import scala.actors.threadpool.helpers.*; - -class CondVar implements Condition, java.io.Serializable { - private static final long serialVersionUID = -5009898475638427940L; - - /** The lock **/ - protected final ExclusiveLock lock; - - /** - * Create a new CondVar that relies on the given mutual - * exclusion lock. - * @param lock A non-reentrant mutual exclusion lock. - **/ - - CondVar(ExclusiveLock lock) { - this.lock = lock; - } - - public void awaitUninterruptibly() { - int holdCount = lock.getHoldCount(); - if (holdCount == 0) { - throw new IllegalMonitorStateException(); - } - // avoid instant spurious wakeup if thread already interrupted - boolean wasInterrupted = Thread.interrupted(); - try { - synchronized (this) { - for (int i=holdCount; i>0; i--) lock.unlock(); - try { - wait(); - } - catch (InterruptedException ex) { - wasInterrupted = true; - // may have masked the signal and there is no way - // to tell; we must wake up spuriously - } - } - } - finally { - for (int i=holdCount; i>0; i--) lock.lock(); - if (wasInterrupted) { - Thread.currentThread().interrupt(); - } - } - } - - public void await() throws InterruptedException { - int holdCount = lock.getHoldCount(); - if (holdCount == 0) { - throw new IllegalMonitorStateException(); - } - if (Thread.interrupted()) throw new InterruptedException(); - try { - synchronized (this) { - for (int i=holdCount; i>0; i--) lock.unlock(); - try { - wait(); - } - catch (InterruptedException ex) { - notify(); - throw ex; - } - } - } - finally { - for (int i=holdCount; i>0; i--) lock.lock(); - } - } - - public boolean await(long timeout, TimeUnit unit) throws InterruptedException { - int holdCount = lock.getHoldCount(); - if (holdCount == 0) { - throw new IllegalMonitorStateException(); - } - if (Thread.interrupted()) throw new InterruptedException(); - long nanos = unit.toNanos(timeout); - boolean success = false; - try { - synchronized (this) { - for (int i=holdCount; i>0; i--) lock.unlock(); - try { - if (nanos > 0) { - long start = Utils.nanoTime(); - TimeUnit.NANOSECONDS.timedWait(this, nanos); - // DK: due to coarse-grained (millis) clock, it seems - // preferable to acknowledge timeout (success == false) - // when the equality holds (timing is exact) - success = Utils.nanoTime() - start < nanos; - } - } - catch (InterruptedException ex) { - notify(); - throw ex; - } - } - } - finally { - for (int i=holdCount; i>0; i--) lock.lock(); - } - return success; - } - -// public long awaitNanos(long timeout) throws InterruptedException { -// throw new UnsupportedOperationException(); -// } -// - public boolean awaitUntil(Date deadline) throws InterruptedException { - if (deadline == null) throw new NullPointerException(); - int holdCount = lock.getHoldCount(); - if (holdCount == 0) { - throw new IllegalMonitorStateException(); - } - long abstime = deadline.getTime(); - if (Thread.interrupted()) throw new InterruptedException(); - - boolean success = false; - try { - synchronized (this) { - for (int i=holdCount; i>0; i--) lock.unlock(); - try { - long start = System.currentTimeMillis(); - long msecs = abstime - start; - if (msecs > 0) { - wait(msecs); - // DK: due to coarse-grained (millis) clock, it seems - // preferable to acknowledge timeout (success == false) - // when the equality holds (timing is exact) - success = System.currentTimeMillis() - start < msecs; - } - } - catch (InterruptedException ex) { - notify(); - throw ex; - } - } - } - finally { - for (int i=holdCount; i>0; i--) lock.lock(); - } - return success; - } - - public synchronized void signal() { - if (!lock.isHeldByCurrentThread()) { - throw new IllegalMonitorStateException(); - } - notify(); - } - - public synchronized void signalAll() { - if (!lock.isHeldByCurrentThread()) { - throw new IllegalMonitorStateException(); - } - notifyAll(); - } - - protected ExclusiveLock getLock() { return lock; } - - protected boolean hasWaiters() { - throw new UnsupportedOperationException("Use FAIR version"); - } - - protected int getWaitQueueLength() { - throw new UnsupportedOperationException("Use FAIR version"); - } - - protected Collection getWaitingThreads() { - throw new UnsupportedOperationException("Use FAIR version"); - } - - static interface ExclusiveLock extends Lock { - boolean isHeldByCurrentThread(); - int getHoldCount(); - } -} diff --git a/src/actors/scala/actors/threadpool/locks/Condition.java b/src/actors/scala/actors/threadpool/locks/Condition.java deleted file mode 100644 index 0553684321..0000000000 --- a/src/actors/scala/actors/threadpool/locks/Condition.java +++ /dev/null @@ -1,434 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool.locks; - -import scala.actors.threadpool.*; -import java.util.Date; - -/** - * {@code Condition} factors out the {@code Object} monitor - * methods ({@link Object#wait() wait}, {@link Object#notify notify} - * and {@link Object#notifyAll notifyAll}) into distinct objects to - * give the effect of having multiple wait-sets per object, by - * combining them with the use of arbitrary {@link Lock} implementations. - * Where a {@code Lock} replaces the use of {@code synchronized} methods - * and statements, a {@code Condition} replaces the use of the Object - * monitor methods. - * - *

Conditions (also known as condition queues or - * condition variables) provide a means for one thread to - * suspend execution (to "wait") until notified by another - * thread that some state condition may now be true. Because access - * to this shared state information occurs in different threads, it - * must be protected, so a lock of some form is associated with the - * condition. The key property that waiting for a condition provides - * is that it atomically releases the associated lock and - * suspends the current thread, just like {@code Object.wait}. - * - *

A {@code Condition} instance is intrinsically bound to a lock. - * To obtain a {@code Condition} instance for a particular {@link Lock} - * instance use its {@link Lock#newCondition newCondition()} method. - * - *

As an example, suppose we have a bounded buffer which supports - * {@code put} and {@code take} methods. If a - * {@code take} is attempted on an empty buffer, then the thread will block - * until an item becomes available; if a {@code put} is attempted on a - * full buffer, then the thread will block until a space becomes available. - * We would like to keep waiting {@code put} threads and {@code take} - * threads in separate wait-sets so that we can use the optimization of - * only notifying a single thread at a time when items or spaces become - * available in the buffer. This can be achieved using two - * {@link Condition} instances. - *

- * class BoundedBuffer {
- *   final Lock lock = new ReentrantLock();
- *   final Condition notFull  = lock.newCondition(); 
- *   final Condition notEmpty = lock.newCondition(); 
- *
- *   final Object[] items = new Object[100];
- *   int putptr, takeptr, count;
- *
- *   public void put(Object x) throws InterruptedException {
- *     lock.lock();
- *     try {
- *       while (count == items.length)
- *         notFull.await();
- *       items[putptr] = x;
- *       if (++putptr == items.length) putptr = 0;
- *       ++count;
- *       notEmpty.signal();
- *     } finally {
- *       lock.unlock();
- *     }
- *   }
- *
- *   public Object take() throws InterruptedException {
- *     lock.lock();
- *     try {
- *       while (count == 0)
- *         notEmpty.await();
- *       Object x = items[takeptr];
- *       if (++takeptr == items.length) takeptr = 0;
- *       --count;
- *       notFull.signal();
- *       return x;
- *     } finally {
- *       lock.unlock();
- *     }
- *   }
- * }
- * 
- * - * (The {@link edu.emory.mathcs.backport.java.util.concurrent.ArrayBlockingQueue} class provides - * this functionality, so there is no reason to implement this - * sample usage class.) - * - *

A {@code Condition} implementation can provide behavior and semantics - * that is - * different from that of the {@code Object} monitor methods, such as - * guaranteed ordering for notifications, or not requiring a lock to be held - * when performing notifications. - * If an implementation provides such specialized semantics then the - * implementation must document those semantics. - * - *

Note that {@code Condition} instances are just normal objects and can - * themselves be used as the target in a {@code synchronized} statement, - * and can have their own monitor {@link Object#wait wait} and - * {@link Object#notify notification} methods invoked. - * Acquiring the monitor lock of a {@code Condition} instance, or using its - * monitor methods, has no specified relationship with acquiring the - * {@link Lock} associated with that {@code Condition} or the use of its - * {@linkplain #await waiting} and {@linkplain #signal signalling} methods. - * It is recommended that to avoid confusion you never use {@code Condition} - * instances in this way, except perhaps within their own implementation. - * - *

Except where noted, passing a {@code null} value for any parameter - * will result in a {@link NullPointerException} being thrown. - * - *

Implementation Considerations

- * - *

When waiting upon a {@code Condition}, a "spurious - * wakeup" is permitted to occur, in - * general, as a concession to the underlying platform semantics. - * This has little practical impact on most application programs as a - * {@code Condition} should always be waited upon in a loop, testing - * the state predicate that is being waited for. An implementation is - * free to remove the possibility of spurious wakeups but it is - * recommended that applications programmers always assume that they can - * occur and so always wait in a loop. - * - *

The three forms of condition waiting - * (interruptible, non-interruptible, and timed) may differ in their ease of - * implementation on some platforms and in their performance characteristics. - * In particular, it may be difficult to provide these features and maintain - * specific semantics such as ordering guarantees. - * Further, the ability to interrupt the actual suspension of the thread may - * not always be feasible to implement on all platforms. - * - *

Consequently, an implementation is not required to define exactly the - * same guarantees or semantics for all three forms of waiting, nor is it - * required to support interruption of the actual suspension of the thread. - * - *

An implementation is required to - * clearly document the semantics and guarantees provided by each of the - * waiting methods, and when an implementation does support interruption of - * thread suspension then it must obey the interruption semantics as defined - * in this interface. - * - *

As interruption generally implies cancellation, and checks for - * interruption are often infrequent, an implementation can favor responding - * to an interrupt over normal method return. This is true even if it can be - * shown that the interrupt occurred after another action may have unblocked - * the thread. An implementation should document this behavior. - * - * @since 1.5 - * @author Doug Lea - */ -public interface Condition { - - /** - * Causes the current thread to wait until it is signalled or - * {@linkplain Thread#interrupt interrupted}. - * - *

The lock associated with this {@code Condition} is atomically - * released and the current thread becomes disabled for thread scheduling - * purposes and lies dormant until one of four things happens: - *

    - *
  • Some other thread invokes the {@link #signal} method for this - * {@code Condition} and the current thread happens to be chosen as the - * thread to be awakened; or - *
  • Some other thread invokes the {@link #signalAll} method for this - * {@code Condition}; or - *
  • Some other thread {@linkplain Thread#interrupt interrupts} the - * current thread, and interruption of thread suspension is supported; or - *
  • A "spurious wakeup" occurs. - *
- * - *

In all cases, before this method can return the current thread must - * re-acquire the lock associated with this condition. When the - * thread returns it is guaranteed to hold this lock. - * - *

If the current thread: - *

    - *
  • has its interrupted status set on entry to this method; or - *
  • is {@linkplain Thread#interrupt interrupted} while waiting - * and interruption of thread suspension is supported, - *
- * then {@link InterruptedException} is thrown and the current thread's - * interrupted status is cleared. It is not specified, in the first - * case, whether or not the test for interruption occurs before the lock - * is released. - * - *

Implementation Considerations - * - *

The current thread is assumed to hold the lock associated with this - * {@code Condition} when this method is called. - * It is up to the implementation to determine if this is - * the case and if not, how to respond. Typically, an exception will be - * thrown (such as {@link IllegalMonitorStateException}) and the - * implementation must document that fact. - * - *

An implementation can favor responding to an interrupt over normal - * method return in response to a signal. In that case the implementation - * must ensure that the signal is redirected to another waiting thread, if - * there is one. - * - * @throws InterruptedException if the current thread is interrupted - * (and interruption of thread suspension is supported) - */ - void await() throws InterruptedException; - - /** - * Causes the current thread to wait until it is signalled. - * - *

The lock associated with this condition is atomically - * released and the current thread becomes disabled for thread scheduling - * purposes and lies dormant until one of three things happens: - *

    - *
  • Some other thread invokes the {@link #signal} method for this - * {@code Condition} and the current thread happens to be chosen as the - * thread to be awakened; or - *
  • Some other thread invokes the {@link #signalAll} method for this - * {@code Condition}; or - *
  • A "spurious wakeup" occurs. - *
- * - *

In all cases, before this method can return the current thread must - * re-acquire the lock associated with this condition. When the - * thread returns it is guaranteed to hold this lock. - * - *

If the current thread's interrupted status is set when it enters - * this method, or it is {@linkplain Thread#interrupt interrupted} - * while waiting, it will continue to wait until signalled. When it finally - * returns from this method its interrupted status will still - * be set. - * - *

Implementation Considerations - * - *

The current thread is assumed to hold the lock associated with this - * {@code Condition} when this method is called. - * It is up to the implementation to determine if this is - * the case and if not, how to respond. Typically, an exception will be - * thrown (such as {@link IllegalMonitorStateException}) and the - * implementation must document that fact. - */ - void awaitUninterruptibly(); - -// /** -// * Causes the current thread to wait until it is signalled or interrupted, -// * or the specified waiting time elapses. -// * -// *

The lock associated with this condition is atomically -// * released and the current thread becomes disabled for thread scheduling -// * purposes and lies dormant until one of five things happens: -// *

    -// *
  • Some other thread invokes the {@link #signal} method for this -// * Condition and the current thread happens to be chosen as the -// * thread to be awakened; or -// *
  • Some other thread invokes the {@link #signalAll} method for this -// * Condition; or -// *
  • Some other thread {@link Thread#interrupt interrupts} the current -// * thread, and interruption of thread suspension is supported; or -// *
  • The specified waiting time elapses; or -// *
  • A "spurious wakeup" occurs. -// *
-// * -// *

In all cases, before this method can return the current thread must -// * re-acquire the lock associated with this condition. When the -// * thread returns it is guaranteed to hold this lock. -// * -// *

If the current thread: -// *

    -// *
  • has its interrupted status set on entry to this method; or -// *
  • is {@link Thread#interrupt interrupted} while waiting -// * and interruption of thread suspension is supported, -// *
-// * then {@link InterruptedException} is thrown and the current thread's -// * interrupted status is cleared. It is not specified, in the first -// * case, whether or not the test for interruption occurs before the lock -// * is released. -// * -// *

The method returns an estimate of the number of nanoseconds -// * remaining to wait given the supplied nanosTimeout -// * value upon return, or a value less than or equal to zero if it -// * timed out. This value can be used to determine whether and how -// * long to re-wait in cases where the wait returns but an awaited -// * condition still does not hold. Typical uses of this method take -// * the following form: -// * -// *

-//     * synchronized boolean aMethod(long timeout, TimeUnit unit) {
-//     *   long nanosTimeout = unit.toNanos(timeout);
-//     *   while (!conditionBeingWaitedFor) {
-//     *     if (nanosTimeout > 0)
-//     *         nanosTimeout = theCondition.awaitNanos(nanosTimeout);
-//     *      else
-//     *        return false;
-//     *   }
-//     *   // ...
-//     * }
-//     * 
-// * -// *

Design note: This method requires a nanosecond argument so -// * as to avoid truncation errors in reporting remaining times. -// * Such precision loss would make it difficult for programmers to -// * ensure that total waiting times are not systematically shorter -// * than specified when re-waits occur. -// * -// *

Implementation Considerations -// *

The current thread is assumed to hold the lock associated with this -// * Condition when this method is called. -// * It is up to the implementation to determine if this is -// * the case and if not, how to respond. Typically, an exception will be -// * thrown (such as {@link IllegalMonitorStateException}) and the -// * implementation must document that fact. -// * -// *

An implementation can favor responding to an interrupt over normal -// * method return in response to a signal, or over indicating the elapse -// * of the specified waiting time. In either case the implementation -// * must ensure that the signal is redirected to another waiting thread, if -// * there is one. -// * -// * @param nanosTimeout the maximum time to wait, in nanoseconds -// * @return A value less than or equal to zero if the wait has -// * timed out; otherwise an estimate, that -// * is strictly less than the nanosTimeout argument, -// * of the time still remaining when this method returned. -// * -// * @throws InterruptedException if the current thread is interrupted (and -// * interruption of thread suspension is supported). -// */ -// long awaitNanos(long nanosTimeout) throws InterruptedException; - - /** - * Causes the current thread to wait until it is signalled or interrupted, - * or the specified waiting time elapses. This method is behaviorally - * equivalent to:
- *

-     *   awaitNanos(unit.toNanos(time)) > 0
-     * 
- * @param time the maximum time to wait - * @param unit the time unit of the {@code time} argument - * @return {@code false} if the waiting time detectably elapsed - * before return from the method, else {@code true} - * @throws InterruptedException if the current thread is interrupted - * (and interruption of thread suspension is supported) - */ - boolean await(long time, TimeUnit unit) throws InterruptedException; - - /** - * Causes the current thread to wait until it is signalled or interrupted, - * or the specified deadline elapses. - * - *

The lock associated with this condition is atomically - * released and the current thread becomes disabled for thread scheduling - * purposes and lies dormant until one of five things happens: - *

    - *
  • Some other thread invokes the {@link #signal} method for this - * {@code Condition} and the current thread happens to be chosen as the - * thread to be awakened; or - *
  • Some other thread invokes the {@link #signalAll} method for this - * {@code Condition}; or - *
  • Some other thread {@linkplain Thread#interrupt interrupts} the - * current thread, and interruption of thread suspension is supported; or - *
  • The specified deadline elapses; or - *
  • A "spurious wakeup" occurs. - *
- * - *

In all cases, before this method can return the current thread must - * re-acquire the lock associated with this condition. When the - * thread returns it is guaranteed to hold this lock. - * - * - *

If the current thread: - *

    - *
  • has its interrupted status set on entry to this method; or - *
  • is {@linkplain Thread#interrupt interrupted} while waiting - * and interruption of thread suspension is supported, - *
- * then {@link InterruptedException} is thrown and the current thread's - * interrupted status is cleared. It is not specified, in the first - * case, whether or not the test for interruption occurs before the lock - * is released. - * - * - *

The return value indicates whether the deadline has elapsed, - * which can be used as follows: - *

-     * synchronized boolean aMethod(Date deadline) {
-     *   boolean stillWaiting = true;
-     *   while (!conditionBeingWaitedFor) {
-     *     if (stillWaiting)
-     *         stillWaiting = theCondition.awaitUntil(deadline);
-     *      else
-     *        return false;
-     *   }
-     *   // ...
-     * }
-     * 
- * - *

Implementation Considerations - * - *

The current thread is assumed to hold the lock associated with this - * {@code Condition} when this method is called. - * It is up to the implementation to determine if this is - * the case and if not, how to respond. Typically, an exception will be - * thrown (such as {@link IllegalMonitorStateException}) and the - * implementation must document that fact. - * - *

An implementation can favor responding to an interrupt over normal - * method return in response to a signal, or over indicating the passing - * of the specified deadline. In either case the implementation - * must ensure that the signal is redirected to another waiting thread, if - * there is one. - * - * @param deadline the absolute time to wait until - * @return {@code false} if the deadline has elapsed upon return, else - * {@code true} - * @throws InterruptedException if the current thread is interrupted - * (and interruption of thread suspension is supported) - */ - boolean awaitUntil(Date deadline) throws InterruptedException; - - /** - * Wakes up one waiting thread. - * - *

If any threads are waiting on this condition then one - * is selected for waking up. That thread must then re-acquire the - * lock before returning from {@code await}. - */ - void signal(); - - /** - * Wakes up all waiting threads. - * - *

If any threads are waiting on this condition then they are - * all woken up. Each thread must re-acquire the lock before it can - * return from {@code await}. - */ - void signalAll(); -} diff --git a/src/actors/scala/actors/threadpool/locks/FIFOCondVar.java b/src/actors/scala/actors/threadpool/locks/FIFOCondVar.java deleted file mode 100644 index 144ac54d37..0000000000 --- a/src/actors/scala/actors/threadpool/locks/FIFOCondVar.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - File: ConditionVariable.java - Originally written by Doug Lea and released into the public domain. - This may be used for any purposes whatsoever without acknowledgment. - Thanks for the assistance and support of Sun Microsystems Labs, - and everyone contributing, testing, and using this code. - History: - Date Who What - 11Jun1998 dl Create public version - */ - -package scala.actors.threadpool.locks; - -import java.util.Collection; -import java.util.Date; -import scala.actors.threadpool.*; -import scala.actors.threadpool.helpers.*; - -class FIFOCondVar extends CondVar implements Condition, java.io.Serializable { - private static final long serialVersionUID = -497497271881010475L; - - private static final WaitQueue.QueuedSync sync = new WaitQueue.QueuedSync() { - public boolean recheck(WaitQueue.WaitNode node) { return false; } - public void takeOver(WaitQueue.WaitNode node) {} - }; - - // wait queue; only accessed when holding the lock - private final WaitQueue wq = new FIFOWaitQueue(); - - /** - * Create a new CondVar that relies on the given mutual exclusion lock. - * @param lock A non-reentrant mutual exclusion lock. - */ - FIFOCondVar(ExclusiveLock lock) { - super(lock); - } - - public void awaitUninterruptibly() { - int holdCount = lock.getHoldCount(); - if (holdCount == 0) { - throw new IllegalMonitorStateException(); - } - WaitQueue.WaitNode n = new WaitQueue.WaitNode(); - wq.insert(n); - for (int i=holdCount; i>0; i--) lock.unlock(); - try { - n.doWaitUninterruptibly(sync); - } - finally { - for (int i=holdCount; i>0; i--) lock.lock(); - } - } - - public void await() throws InterruptedException { - int holdCount = lock.getHoldCount(); - if (holdCount == 0) { - throw new IllegalMonitorStateException(); - } - if (Thread.interrupted()) throw new InterruptedException(); - WaitQueue.WaitNode n = new WaitQueue.WaitNode(); - wq.insert(n); - for (int i=holdCount; i>0; i--) lock.unlock(); - try { - n.doWait(sync); - } - finally { - for (int i=holdCount; i>0; i--) lock.lock(); - } - } - - public boolean await(long timeout, TimeUnit unit) throws InterruptedException { - int holdCount = lock.getHoldCount(); - if (holdCount == 0) { - throw new IllegalMonitorStateException(); - } - if (Thread.interrupted()) throw new InterruptedException(); - long nanos = unit.toNanos(timeout); - WaitQueue.WaitNode n = new WaitQueue.WaitNode(); - wq.insert(n); - boolean success = false; - for (int i=holdCount; i>0; i--) lock.unlock(); - try { - success = n.doTimedWait(sync, nanos); - } - finally { - for (int i=holdCount; i>0; i--) lock.lock(); - } - return success; - } - -// public long awaitNanos(long timeout) throws InterruptedException { -// throw new UnsupportedOperationException(); -// } -// - public boolean awaitUntil(Date deadline) throws InterruptedException { - if (deadline == null) throw new NullPointerException(); - long abstime = deadline.getTime(); - long start = System.currentTimeMillis(); - long msecs = abstime - start; - return await(msecs, TimeUnit.MILLISECONDS); - } - - public void signal() { - if (!lock.isHeldByCurrentThread()) { - throw new IllegalMonitorStateException(); - } - for (;;) { - WaitQueue.WaitNode w = wq.extract(); - if (w == null) return; // no one to signal - if (w.signal(sync)) return; // notify if still waiting, else skip - } - } - - public void signalAll() { - if (!lock.isHeldByCurrentThread()) { - throw new IllegalMonitorStateException(); - } - for (;;) { - WaitQueue.WaitNode w = wq.extract(); - if (w == null) return; // no more to signal - w.signal(sync); - } - } - - protected boolean hasWaiters() { - if (!lock.isHeldByCurrentThread()) { - throw new IllegalMonitorStateException(); - } - return wq.hasNodes(); - } - - protected int getWaitQueueLength() { - if (!lock.isHeldByCurrentThread()) { - throw new IllegalMonitorStateException(); - } - return wq.getLength(); - } - - protected Collection getWaitingThreads() { - if (!lock.isHeldByCurrentThread()) { - throw new IllegalMonitorStateException(); - } - return wq.getWaitingThreads(); - } - - -} diff --git a/src/actors/scala/actors/threadpool/locks/Lock.java b/src/actors/scala/actors/threadpool/locks/Lock.java deleted file mode 100644 index 47a4e8e777..0000000000 --- a/src/actors/scala/actors/threadpool/locks/Lock.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool.locks; - -import scala.actors.threadpool.TimeUnit; - -/** - * {@code Lock} implementations provide more extensive locking - * operations than can be obtained using {@code synchronized} methods - * and statements. They allow more flexible structuring, may have - * quite different properties, and may support multiple associated - * {@link Condition} objects. - * - *

A lock is a tool for controlling access to a shared resource by - * multiple threads. Commonly, a lock provides exclusive access to a - * shared resource: only one thread at a time can acquire the lock and - * all access to the shared resource requires that the lock be - * acquired first. However, some locks may allow concurrent access to - * a shared resource, such as the read lock of a {@link ReadWriteLock}. - * - *

The use of {@code synchronized} methods or statements provides - * access to the implicit monitor lock associated with every object, but - * forces all lock acquisition and release to occur in a block-structured way: - * when multiple locks are acquired they must be released in the opposite - * order, and all locks must be released in the same lexical scope in which - * they were acquired. - * - *

While the scoping mechanism for {@code synchronized} methods - * and statements makes it much easier to program with monitor locks, - * and helps avoid many common programming errors involving locks, - * there are occasions where you need to work with locks in a more - * flexible way. For example, some algorithms for traversing - * concurrently accessed data structures require the use of - * "hand-over-hand" or "chain locking": you - * acquire the lock of node A, then node B, then release A and acquire - * C, then release B and acquire D and so on. Implementations of the - * {@code Lock} interface enable the use of such techniques by - * allowing a lock to be acquired and released in different scopes, - * and allowing multiple locks to be acquired and released in any - * order. - * - *

With this increased flexibility comes additional - * responsibility. The absence of block-structured locking removes the - * automatic release of locks that occurs with {@code synchronized} - * methods and statements. In most cases, the following idiom - * should be used: - * - *

     Lock l = ...;
- *     l.lock();
- *     try {
- *         // access the resource protected by this lock
- *     } finally {
- *         l.unlock();
- *     }
- * 
- * - * When locking and unlocking occur in different scopes, care must be - * taken to ensure that all code that is executed while the lock is - * held is protected by try-finally or try-catch to ensure that the - * lock is released when necessary. - * - *

{@code Lock} implementations provide additional functionality - * over the use of {@code synchronized} methods and statements by - * providing a non-blocking attempt to acquire a lock ({@link - * #tryLock()}), an attempt to acquire the lock that can be - * interrupted ({@link #lockInterruptibly}, and an attempt to acquire - * the lock that can timeout ({@link #tryLock(long, TimeUnit)}). - * - *

A {@code Lock} class can also provide behavior and semantics - * that is quite different from that of the implicit monitor lock, - * such as guaranteed ordering, non-reentrant usage, or deadlock - * detection. If an implementation provides such specialized semantics - * then the implementation must document those semantics. - * - *

Note that {@code Lock} instances are just normal objects and can - * themselves be used as the target in a {@code synchronized} statement. - * Acquiring the - * monitor lock of a {@code Lock} instance has no specified relationship - * with invoking any of the {@link #lock} methods of that instance. - * It is recommended that to avoid confusion you never use {@code Lock} - * instances in this way, except within their own implementation. - * - *

Except where noted, passing a {@code null} value for any - * parameter will result in a {@link NullPointerException} being - * thrown. - * - *

Memory Synchronization

- * - *

All {@code Lock} implementations must enforce the same - * memory synchronization semantics as provided by the built-in monitor - * lock, as described in - * The Java Language Specification, Third Edition (17.4 Memory Model): - *

    - *
  • A successful {@code lock} operation has the same memory - * synchronization effects as a successful Lock action. - *
  • A successful {@code unlock} operation has the same - * memory synchronization effects as a successful Unlock action. - *
- * - * Unsuccessful locking and unlocking operations, and reentrant - * locking/unlocking operations, do not require any memory - * synchronization effects. - * - *

Implementation Considerations

- * - *

The three forms of lock acquisition (interruptible, - * non-interruptible, and timed) may differ in their performance - * characteristics, ordering guarantees, or other implementation - * qualities. Further, the ability to interrupt the ongoing - * acquisition of a lock may not be available in a given {@code Lock} - * class. Consequently, an implementation is not required to define - * exactly the same guarantees or semantics for all three forms of - * lock acquisition, nor is it required to support interruption of an - * ongoing lock acquisition. An implementation is required to clearly - * document the semantics and guarantees provided by each of the - * locking methods. It must also obey the interruption semantics as - * defined in this interface, to the extent that interruption of lock - * acquisition is supported: which is either totally, or only on - * method entry. - * - *

As interruption generally implies cancellation, and checks for - * interruption are often infrequent, an implementation can favor responding - * to an interrupt over normal method return. This is true even if it can be - * shown that the interrupt occurred after another action may have unblocked - * the thread. An implementation should document this behavior. - * - * @see ReentrantLock - * @see Condition - * @see ReadWriteLock - * - * @since 1.5 - * @author Doug Lea - */ -public interface Lock { - - /** - * Acquires the lock. - * - *

If the lock is not available then the current thread becomes - * disabled for thread scheduling purposes and lies dormant until the - * lock has been acquired. - * - *

Implementation Considerations - * - *

A {@code Lock} implementation may be able to detect erroneous use - * of the lock, such as an invocation that would cause deadlock, and - * may throw an (unchecked) exception in such circumstances. The - * circumstances and the exception type must be documented by that - * {@code Lock} implementation. - */ - void lock(); - - /** - * Acquires the lock unless the current thread is - * {@linkplain Thread#interrupt interrupted}. - * - *

Acquires the lock if it is available and returns immediately. - * - *

If the lock is not available then the current thread becomes - * disabled for thread scheduling purposes and lies dormant until - * one of two things happens: - * - *

    - *
  • The lock is acquired by the current thread; or - *
  • Some other thread {@linkplain Thread#interrupt interrupts} the - * current thread, and interruption of lock acquisition is supported. - *
- * - *

If the current thread: - *

    - *
  • has its interrupted status set on entry to this method; or - *
  • is {@linkplain Thread#interrupt interrupted} while acquiring the - * lock, and interruption of lock acquisition is supported, - *
- * then {@link InterruptedException} is thrown and the current thread's - * interrupted status is cleared. - * - *

Implementation Considerations - * - *

The ability to interrupt a lock acquisition in some - * implementations may not be possible, and if possible may be an - * expensive operation. The programmer should be aware that this - * may be the case. An implementation should document when this is - * the case. - * - *

An implementation can favor responding to an interrupt over - * normal method return. - * - *

A {@code Lock} implementation may be able to detect - * erroneous use of the lock, such as an invocation that would - * cause deadlock, and may throw an (unchecked) exception in such - * circumstances. The circumstances and the exception type must - * be documented by that {@code Lock} implementation. - * - * @throws InterruptedException if the current thread is - * interrupted while acquiring the lock (and interruption - * of lock acquisition is supported). - */ - void lockInterruptibly() throws InterruptedException; - - /** - * Acquires the lock only if it is free at the time of invocation. - * - *

Acquires the lock if it is available and returns immediately - * with the value {@code true}. - * If the lock is not available then this method will return - * immediately with the value {@code false}. - * - *

A typical usage idiom for this method would be: - *

-     *      Lock lock = ...;
-     *      if (lock.tryLock()) {
-     *          try {
-     *              // manipulate protected state
-     *          } finally {
-     *              lock.unlock();
-     *          }
-     *      } else {
-     *          // perform alternative actions
-     *      }
-     * 
- * This usage ensures that the lock is unlocked if it was acquired, and - * doesn't try to unlock if the lock was not acquired. - * - * @return {@code true} if the lock was acquired and - * {@code false} otherwise - */ - boolean tryLock(); - - /** - * Acquires the lock if it is free within the given waiting time and the - * current thread has not been {@linkplain Thread#interrupt interrupted}. - * - *

If the lock is available this method returns immediately - * with the value {@code true}. - * If the lock is not available then - * the current thread becomes disabled for thread scheduling - * purposes and lies dormant until one of three things happens: - *

    - *
  • The lock is acquired by the current thread; or - *
  • Some other thread {@linkplain Thread#interrupt interrupts} the - * current thread, and interruption of lock acquisition is supported; or - *
  • The specified waiting time elapses - *
- * - *

If the lock is acquired then the value {@code true} is returned. - * - *

If the current thread: - *

    - *
  • has its interrupted status set on entry to this method; or - *
  • is {@linkplain Thread#interrupt interrupted} while acquiring - * the lock, and interruption of lock acquisition is supported, - *
- * then {@link InterruptedException} is thrown and the current thread's - * interrupted status is cleared. - * - *

If the specified waiting time elapses then the value {@code false} - * is returned. - * If the time is - * less than or equal to zero, the method will not wait at all. - * - *

Implementation Considerations - * - *

The ability to interrupt a lock acquisition in some implementations - * may not be possible, and if possible may - * be an expensive operation. - * The programmer should be aware that this may be the case. An - * implementation should document when this is the case. - * - *

An implementation can favor responding to an interrupt over normal - * method return, or reporting a timeout. - * - *

A {@code Lock} implementation may be able to detect - * erroneous use of the lock, such as an invocation that would cause - * deadlock, and may throw an (unchecked) exception in such circumstances. - * The circumstances and the exception type must be documented by that - * {@code Lock} implementation. - * - * @param time the maximum time to wait for the lock - * @param unit the time unit of the {@code time} argument - * @return {@code true} if the lock was acquired and {@code false} - * if the waiting time elapsed before the lock was acquired - * - * @throws InterruptedException if the current thread is interrupted - * while acquiring the lock (and interruption of lock - * acquisition is supported) - */ - boolean tryLock(long time, TimeUnit unit) throws InterruptedException; - - /** - * Releases the lock. - * - *

Implementation Considerations - * - *

A {@code Lock} implementation will usually impose - * restrictions on which thread can release a lock (typically only the - * holder of the lock can release it) and may throw - * an (unchecked) exception if the restriction is violated. - * Any restrictions and the exception - * type must be documented by that {@code Lock} implementation. - */ - void unlock(); - - /** - * Returns a new {@link Condition} instance that is bound to this - * {@code Lock} instance. - * - *

Before waiting on the condition the lock must be held by the - * current thread. - * A call to {@link Condition#await()} will atomically release the lock - * before waiting and re-acquire the lock before the wait returns. - * - *

Implementation Considerations - * - *

The exact operation of the {@link Condition} instance depends on - * the {@code Lock} implementation and must be documented by that - * implementation. - * - * @return A new {@link Condition} instance for this {@code Lock} instance - * @throws UnsupportedOperationException if this {@code Lock} - * implementation does not support conditions - */ - Condition newCondition(); -} diff --git a/src/actors/scala/actors/threadpool/locks/ReadWriteLock.java b/src/actors/scala/actors/threadpool/locks/ReadWriteLock.java deleted file mode 100644 index 02983f9bd4..0000000000 --- a/src/actors/scala/actors/threadpool/locks/ReadWriteLock.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool.locks; - -/** - * A ReadWriteLock maintains a pair of associated {@link - * Lock locks}, one for read-only operations and one for writing. - * The {@link #readLock read lock} may be held simultaneously by - * multiple reader threads, so long as there are no writers. The - * {@link #writeLock write lock} is exclusive. - * - *

All ReadWriteLock implementations must guarantee that - * the memory synchronization effects of writeLock operations - * (as specified in the {@link Lock} interface) also hold with respect - * to the associated readLock. That is, a thread successfully - * acquiring the read lock will see all updates made upon previous - * release of the write lock. - * - *

A read-write lock allows for a greater level of concurrency in - * accessing shared data than that permitted by a mutual exclusion lock. - * It exploits the fact that while only a single thread at a time (a - * writer thread) can modify the shared data, in many cases any - * number of threads can concurrently read the data (hence reader - * threads). - * In theory, the increase in concurrency permitted by the use of a read-write - * lock will lead to performance improvements over the use of a mutual - * exclusion lock. In practice this increase in concurrency will only be fully - * realized on a multi-processor, and then only if the access patterns for - * the shared data are suitable. - * - *

Whether or not a read-write lock will improve performance over the use - * of a mutual exclusion lock depends on the frequency that the data is - * read compared to being modified, the duration of the read and write - * operations, and the contention for the data - that is, the number of - * threads that will try to read or write the data at the same time. - * For example, a collection that is initially populated with data and - * thereafter infrequently modified, while being frequently searched - * (such as a directory of some kind) is an ideal candidate for the use of - * a read-write lock. However, if updates become frequent then the data - * spends most of its time being exclusively locked and there is little, if any - * increase in concurrency. Further, if the read operations are too short - * the overhead of the read-write lock implementation (which is inherently - * more complex than a mutual exclusion lock) can dominate the execution - * cost, particularly as many read-write lock implementations still serialize - * all threads through a small section of code. Ultimately, only profiling - * and measurement will establish whether the use of a read-write lock is - * suitable for your application. - * - * - *

Although the basic operation of a read-write lock is straight-forward, - * there are many policy decisions that an implementation must make, which - * may affect the effectiveness of the read-write lock in a given application. - * Examples of these policies include: - *

    - *
  • Determining whether to grant the read lock or the write lock, when - * both readers and writers are waiting, at the time that a writer releases - * the write lock. Writer preference is common, as writes are expected to be - * short and infrequent. Reader preference is less common as it can lead to - * lengthy delays for a write if the readers are frequent and long-lived as - * expected. Fair, or "in-order" implementations are also possible. - * - *
  • Determining whether readers that request the read lock while a - * reader is active and a writer is waiting, are granted the read lock. - * Preference to the reader can delay the writer indefinitely, while - * preference to the writer can reduce the potential for concurrency. - * - *
  • Determining whether the locks are reentrant: can a thread with the - * write lock reacquire it? Can it acquire a read lock while holding the - * write lock? Is the read lock itself reentrant? - * - *
  • Can the write lock be downgraded to a read lock without allowing - * an intervening writer? Can a read lock be upgraded to a write lock, - * in preference to other waiting readers or writers? - * - *
- * You should consider all of these things when evaluating the suitability - * of a given implementation for your application. - * - * @see ReentrantReadWriteLock - * @see Lock - * @see ReentrantLock - * - * @since 1.5 - * @author Doug Lea - */ -public interface ReadWriteLock { - /** - * Returns the lock used for reading. - * - * @return the lock used for reading. - */ - Lock readLock(); - - /** - * Returns the lock used for writing. - * - * @return the lock used for writing. - */ - Lock writeLock(); -} diff --git a/src/actors/scala/actors/threadpool/locks/ReentrantLock.java b/src/actors/scala/actors/threadpool/locks/ReentrantLock.java deleted file mode 100644 index b42ddd611b..0000000000 --- a/src/actors/scala/actors/threadpool/locks/ReentrantLock.java +++ /dev/null @@ -1,959 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool.locks; - -import java.util.Collection; -import scala.actors.threadpool.*; -import scala.actors.threadpool.helpers.*; - -/** - * A reentrant mutual exclusion {@link Lock} with the same basic - * behavior and semantics as the implicit monitor lock accessed using - * {@code synchronized} methods and statements, but with extended - * capabilities. - * - *

A {@code ReentrantLock} is owned by the thread last - * successfully locking, but not yet unlocking it. A thread invoking - * {@code lock} will return, successfully acquiring the lock, when - * the lock is not owned by another thread. The method will return - * immediately if the current thread already owns the lock. This can - * be checked using methods {@link #isHeldByCurrentThread}, and {@link - * #getHoldCount}. - * - *

The constructor for this class accepts an optional - * fairness parameter. When set {@code true}, under - * contention, locks favor granting access to the longest-waiting - * thread. Otherwise this lock does not guarantee any particular - * access order. Programs using fair locks accessed by many threads - * may display lower overall throughput (i.e., are slower; often much - * slower) than those using the default setting, but have smaller - * variances in times to obtain locks and guarantee lack of - * starvation. Note however, that fairness of locks does not guarantee - * fairness of thread scheduling. Thus, one of many threads using a - * fair lock may obtain it multiple times in succession while other - * active threads are not progressing and not currently holding the - * lock. - * Also note that the untimed {@link #tryLock() tryLock} method does not - * honor the fairness setting. It will succeed if the lock - * is available even if other threads are waiting. - * - *

It is recommended practice to always immediately - * follow a call to {@code lock} with a {@code try} block, most - * typically in a before/after construction such as: - * - *

- * class X {
- *   private final ReentrantLock lock = new ReentrantLock();
- *   // ...
- *
- *   public void m() {
- *     lock.lock();  // block until condition holds
- *     try {
- *       // ... method body
- *     } finally {
- *       lock.unlock()
- *     }
- *   }
- * }
- * 
- * - *

In addition to implementing the {@link Lock} interface, this - * class defines methods {@code isLocked} and - * {@code getLockQueueLength}, as well as some associated - * {@code protected} access methods that may be useful for - * instrumentation and monitoring. - * - *

Serialization of this class behaves in the same way as built-in - * locks: a deserialized lock is in the unlocked state, regardless of - * its state when serialized. - * - *

This lock supports a maximum of 2147483647 recursive locks by - * the same thread. Attempts to exceed this limit result in - * {@link Error} throws from locking methods. - * - * @since 1.5 - * @author Doug Lea - * @author Dawid Kurzyniec - */ -public class ReentrantLock implements Lock, java.io.Serializable, - CondVar.ExclusiveLock { - private static final long serialVersionUID = 7373984872572414699L; - - private final Sync sync; - - /** - * Base of synchronization control for this lock. Subclassed - * into fair and nonfair versions below. - */ - static abstract class Sync implements java.io.Serializable { - private static final long serialVersionUID = -5179523762034025860L; - - protected transient Thread owner_ = null; - protected transient int holds_ = 0; - - protected Sync() {} - - /** - * Performs {@link Lock#lock}. The main reason for subclassing - * is to allow fast path for nonfair version. - */ - public abstract void lock(); - - public abstract void lockInterruptibly() throws InterruptedException; - - final void incHolds() { - int nextHolds = ++holds_; - if (nextHolds < 0) - throw new Error("Maximum lock count exceeded"); - holds_ = nextHolds; - } - - public boolean tryLock() { - Thread caller = Thread.currentThread(); - synchronized (this) { - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return true; - } - else if (caller == owner_) { - incHolds(); - return true; - } - } - return false; - } - - public abstract boolean tryLock(long nanos) throws InterruptedException; - - public abstract void unlock(); - - public synchronized int getHoldCount() { - return isHeldByCurrentThread() ? holds_ : 0; - } - - public synchronized boolean isHeldByCurrentThread() { - return holds_ > 0 && Thread.currentThread() == owner_; - } - - public synchronized boolean isLocked() { - return owner_ != null; - } - - public abstract boolean isFair(); - - protected synchronized Thread getOwner() { - return owner_; - } - - public boolean hasQueuedThreads() { - throw new UnsupportedOperationException("Use FAIR version"); - } - - public int getQueueLength() { - throw new UnsupportedOperationException("Use FAIR version"); - } - - public Collection getQueuedThreads() { - throw new UnsupportedOperationException("Use FAIR version"); - } - - public boolean isQueued(Thread thread) { - throw new UnsupportedOperationException("Use FAIR version"); - } - } - - /** - * Sync object for non-fair locks - */ - final static class NonfairSync extends Sync { - private static final long serialVersionUID = 7316153563782823691L; - - NonfairSync() {} - - /** - * Performs lock. Try immediate barge, backing up to normal - * acquire on failure. - */ - public void lock() { - Thread caller = Thread.currentThread(); - synchronized (this) { - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return; - } - else if (caller == owner_) { - incHolds(); - return; - } - else { - boolean wasInterrupted = Thread.interrupted(); - try { - while (true) { - try { - wait(); - } - catch (InterruptedException e) { - wasInterrupted = true; - // no need to notify; if we were signalled, we - // will act as signalled, ignoring the - // interruption - } - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return; - } - } - } - finally { - if (wasInterrupted) Thread.currentThread().interrupt(); - } - } - } - } - - public void lockInterruptibly() throws InterruptedException { - if (Thread.interrupted()) throw new InterruptedException(); - Thread caller = Thread.currentThread(); - synchronized (this) { - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return; - } - else if (caller == owner_) { - incHolds(); - return; - } - else { - try { - do { wait(); } while (owner_ != null); - owner_ = caller; - holds_ = 1; - return; - } - catch (InterruptedException ex) { - if (owner_ == null) notify(); - throw ex; - } - } - } - } - - public boolean tryLock(long nanos) throws InterruptedException { - if (Thread.interrupted()) throw new InterruptedException(); - Thread caller = Thread.currentThread(); - - synchronized (this) { - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return true; - } - else if (caller == owner_) { - incHolds(); - return true; - } - else if (nanos <= 0) - return false; - else { - long deadline = Utils.nanoTime() + nanos; - try { - for (; ; ) { - TimeUnit.NANOSECONDS.timedWait(this, nanos); - if (caller == owner_) { - incHolds(); - return true; - } - else if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return true; - } - else { - nanos = deadline - Utils.nanoTime(); - if (nanos <= 0) - return false; - } - } - } - catch (InterruptedException ex) { - if (owner_ == null) notify(); - throw ex; - } - } - } - } - - public synchronized void unlock() { - if (Thread.currentThread() != owner_) - throw new IllegalMonitorStateException("Not owner"); - - if (--holds_ == 0) { - owner_ = null; - notify(); - } - } - - public final boolean isFair() { - return false; - } - } - - /** - * Sync object for fair locks - */ - final static class FairSync extends Sync implements WaitQueue.QueuedSync { - private static final long serialVersionUID = -3000897897090466540L; - - private transient WaitQueue wq_ = new FIFOWaitQueue(); - - FairSync() {} - - public synchronized boolean recheck(WaitQueue.WaitNode node) { - Thread caller = Thread.currentThread(); - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return true; - } - else if (caller == owner_) { - incHolds(); - return true; - } - wq_.insert(node); - return false; - } - - public synchronized void takeOver(WaitQueue.WaitNode node) { - // assert (holds_ == 1 && owner_ == Thread.currentThread() - owner_ = node.getOwner(); - } - - public void lock() { - Thread caller = Thread.currentThread(); - synchronized (this) { - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return; - } - else if (caller == owner_) { - incHolds(); - return; - } - } - WaitQueue.WaitNode n = new WaitQueue.WaitNode(); - n.doWaitUninterruptibly(this); - } - - public void lockInterruptibly() throws InterruptedException { - if (Thread.interrupted()) throw new InterruptedException(); - Thread caller = Thread.currentThread(); - synchronized (this) { - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return; - } - else if (caller == owner_) { - incHolds(); - return; - } - } - WaitQueue.WaitNode n = new WaitQueue.WaitNode(); - n.doWait(this); - } - - public boolean tryLock(long nanos) throws InterruptedException { - if (Thread.interrupted()) throw new InterruptedException(); - Thread caller = Thread.currentThread(); - synchronized (this) { - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return true; - } - else if (caller == owner_) { - incHolds(); - return true; - } - } - WaitQueue.WaitNode n = new WaitQueue.WaitNode(); - return n.doTimedWait(this, nanos); - } - - protected synchronized WaitQueue.WaitNode getSignallee(Thread caller) { - if (caller != owner_) - throw new IllegalMonitorStateException("Not owner"); - // assert (holds_ > 0) - if (holds_ >= 2) { // current thread will keep the lock - --holds_; - return null; - } - // assert (holds_ == 1) - WaitQueue.WaitNode w = wq_.extract(); - if (w == null) { // if none, clear for new arrivals - owner_ = null; - holds_ = 0; - } - return w; - } - - public void unlock() { - Thread caller = Thread.currentThread(); - for (;;) { - WaitQueue.WaitNode w = getSignallee(caller); - if (w == null) return; // no one to signal - if (w.signal(this)) return; // notify if still waiting, else skip - } - } - - public final boolean isFair() { - return true; - } - - public synchronized boolean hasQueuedThreads() { - return wq_.hasNodes(); - } - - public synchronized int getQueueLength() { - return wq_.getLength(); - } - - public synchronized Collection getQueuedThreads() { - return wq_.getWaitingThreads(); - } - - public synchronized boolean isQueued(Thread thread) { - return wq_.isWaiting(thread); - } - - private void readObject(java.io.ObjectInputStream in) - throws java.io.IOException, ClassNotFoundException { - in.defaultReadObject(); - synchronized (this) { - wq_ = new FIFOWaitQueue(); - } - } - } - - /** - * Creates an instance of {@code ReentrantLock}. - * This is equivalent to using {@code ReentrantLock(false)}. - */ - public ReentrantLock() { - sync = new NonfairSync(); - } - - /** - * Creates an instance of {@code ReentrantLock} with the - * given fairness policy. - * - * @param fair {@code true} if this lock should use a fair ordering policy - */ - public ReentrantLock(boolean fair) { - sync = (fair)? (Sync)new FairSync() : new NonfairSync(); - } - - - /** - * Acquires the lock. - * - *

Acquires the lock if it is not held by another thread and returns - * immediately, setting the lock hold count to one. - * - *

If the current thread already holds the lock then the hold - * count is incremented by one and the method returns immediately. - * - *

If the lock is held by another thread then the - * current thread becomes disabled for thread scheduling - * purposes and lies dormant until the lock has been acquired, - * at which time the lock hold count is set to one. - */ - public void lock() { - sync.lock(); - } - - /** - * Acquires the lock unless the current thread is - * {@linkplain Thread#interrupt interrupted}. - * - *

Acquires the lock if it is not held by another thread and returns - * immediately, setting the lock hold count to one. - * - *

If the current thread already holds this lock then the hold count - * is incremented by one and the method returns immediately. - * - *

If the lock is held by another thread then the - * current thread becomes disabled for thread scheduling - * purposes and lies dormant until one of two things happens: - * - *

    - * - *
  • The lock is acquired by the current thread; or - * - *
  • Some other thread {@linkplain Thread#interrupt interrupts} the - * current thread. - * - *
- * - *

If the lock is acquired by the current thread then the lock hold - * count is set to one. - * - *

If the current thread: - * - *

    - * - *
  • has its interrupted status set on entry to this method; or - * - *
  • is {@linkplain Thread#interrupt interrupted} while acquiring - * the lock, - * - *
- * - * then {@link InterruptedException} is thrown and the current thread's - * interrupted status is cleared. - * - *

In this implementation, as this method is an explicit - * interruption point, preference is given to responding to the - * interrupt over normal or reentrant acquisition of the lock. - * - * @throws InterruptedException if the current thread is interrupted - */ - public void lockInterruptibly() throws InterruptedException { - sync.lockInterruptibly(); - } - - /** - * Acquires the lock only if it is not held by another thread at the time - * of invocation. - * - *

Acquires the lock if it is not held by another thread and - * returns immediately with the value {@code true}, setting the - * lock hold count to one. Even when this lock has been set to use a - * fair ordering policy, a call to {@code tryLock()} will - * immediately acquire the lock if it is available, whether or not - * other threads are currently waiting for the lock. - * This "barging" behavior can be useful in certain - * circumstances, even though it breaks fairness. If you want to honor - * the fairness setting for this lock, then use - * {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) } - * which is almost equivalent (it also detects interruption). - * - *

If the current thread already holds this lock then the hold - * count is incremented by one and the method returns {@code true}. - * - *

If the lock is held by another thread then this method will return - * immediately with the value {@code false}. - * - * @return {@code true} if the lock was free and was acquired by the - * current thread, or the lock was already held by the current - * thread; and {@code false} otherwise - */ - public boolean tryLock() { - return sync.tryLock(); - } - - /** - * Acquires the lock if it is not held by another thread within the given - * waiting time and the current thread has not been - * {@linkplain Thread#interrupt interrupted}. - * - *

Acquires the lock if it is not held by another thread and returns - * immediately with the value {@code true}, setting the lock hold count - * to one. If this lock has been set to use a fair ordering policy then - * an available lock will not be acquired if any other threads - * are waiting for the lock. This is in contrast to the {@link #tryLock()} - * method. If you want a timed {@code tryLock} that does permit barging on - * a fair lock then combine the timed and un-timed forms together: - * - *

if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
-     * 
- * - *

If the current thread - * already holds this lock then the hold count is incremented by one and - * the method returns {@code true}. - * - *

If the lock is held by another thread then the - * current thread becomes disabled for thread scheduling - * purposes and lies dormant until one of three things happens: - * - *

    - * - *
  • The lock is acquired by the current thread; or - * - *
  • Some other thread {@linkplain Thread#interrupt interrupts} - * the current thread; or - * - *
  • The specified waiting time elapses - * - *
- * - *

If the lock is acquired then the value {@code true} is returned and - * the lock hold count is set to one. - * - *

If the current thread: - * - *

    - * - *
  • has its interrupted status set on entry to this method; or - * - *
  • is {@linkplain Thread#interrupt interrupted} while - * acquiring the lock, - * - *
- * then {@link InterruptedException} is thrown and the current thread's - * interrupted status is cleared. - * - *

If the specified waiting time elapses then the value {@code false} - * is returned. If the time is less than or equal to zero, the method - * will not wait at all. - * - *

In this implementation, as this method is an explicit - * interruption point, preference is given to responding to the - * interrupt over normal or reentrant acquisition of the lock, and - * over reporting the elapse of the waiting time. - * - * @param timeout the time to wait for the lock - * @param unit the time unit of the timeout argument - * @return {@code true} if the lock was free and was acquired by the - * current thread, or the lock was already held by the current - * thread; and {@code false} if the waiting time elapsed before - * the lock could be acquired - * @throws InterruptedException if the current thread is interrupted - * @throws NullPointerException if the time unit is null - * - */ - public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { - return sync.tryLock(unit.toNanos(timeout)); - } - - /** - * Attempts to release this lock. - * - *

If the current thread is the holder of this lock then the hold - * count is decremented. If the hold count is now zero then the lock - * is released. If the current thread is not the holder of this - * lock then {@link IllegalMonitorStateException} is thrown. - * - * @throws IllegalMonitorStateException if the current thread does not - * hold this lock - */ - public void unlock() { - sync.unlock(); - } - - /** - * Returns a {@link Condition} instance for use with this - * {@link Lock} instance. - * - *

The returned {@link Condition} instance supports the same - * usages as do the {@link Object} monitor methods ({@link - * Object#wait() wait}, {@link Object#notify notify}, and {@link - * Object#notifyAll notifyAll}) when used with the built-in - * monitor lock. - * - *

    - * - *
  • If this lock is not held when any of the {@link Condition} - * {@linkplain Condition#await() waiting} or {@linkplain - * Condition#signal signalling} methods are called, then an {@link - * IllegalMonitorStateException} is thrown. - * - *
  • When the condition {@linkplain Condition#await() waiting} - * methods are called the lock is released and, before they - * return, the lock is reacquired and the lock hold count restored - * to what it was when the method was called. - * - *
  • If a thread is {@linkplain Thread#interrupt interrupted} - * while waiting then the wait will terminate, an {@link - * InterruptedException} will be thrown, and the thread's - * interrupted status will be cleared. - * - *
  • Waiting threads are signalled in FIFO order. - * - *
  • The ordering of lock reacquisition for threads returning - * from waiting methods is the same as for threads initially - * acquiring the lock, which is in the default case not specified, - * but for fair locks favors those threads that have been - * waiting the longest. - * - *
- * - * @return the Condition object - */ - public Condition newCondition() { - return isFair() ? (Condition)new FIFOCondVar(this) : new CondVar(this); - } - - /** - * Queries the number of holds on this lock by the current thread. - * - *

A thread has a hold on a lock for each lock action that is not - * matched by an unlock action. - * - *

The hold count information is typically only used for testing and - * debugging purposes. For example, if a certain section of code should - * not be entered with the lock already held then we can assert that - * fact: - * - *

-     * class X {
-     *   ReentrantLock lock = new ReentrantLock();
-     *   // ...
-     *   public void m() {
-     *     assert lock.getHoldCount() == 0;
-     *     lock.lock();
-     *     try {
-     *       // ... method body
-     *     } finally {
-     *       lock.unlock();
-     *     }
-     *   }
-     * }
-     * 
- * - * @return the number of holds on this lock by the current thread, - * or zero if this lock is not held by the current thread - */ - public int getHoldCount() { - return sync.getHoldCount(); - } - - /** - * Queries if this lock is held by the current thread. - * - *

Analogous to the {@link Thread#holdsLock} method for built-in - * monitor locks, this method is typically used for debugging and - * testing. For example, a method that should only be called while - * a lock is held can assert that this is the case: - * - *

-     * class X {
-     *   ReentrantLock lock = new ReentrantLock();
-     *   // ...
-     *
-     *   public void m() {
-     *       assert lock.isHeldByCurrentThread();
-     *       // ... method body
-     *   }
-     * }
-     * 
- * - *

It can also be used to ensure that a reentrant lock is used - * in a non-reentrant manner, for example: - * - *

-     * class X {
-     *   ReentrantLock lock = new ReentrantLock();
-     *   // ...
-     *
-     *   public void m() {
-     *       assert !lock.isHeldByCurrentThread();
-     *       lock.lock();
-     *       try {
-     *           // ... method body
-     *       } finally {
-     *           lock.unlock();
-     *       }
-     *   }
-     * }
-     * 
- * - * @return {@code true} if current thread holds this lock and - * {@code false} otherwise - */ - public boolean isHeldByCurrentThread() { - return sync.isHeldByCurrentThread(); - } - - /** - * Queries if this lock is held by any thread. This method is - * designed for use in monitoring of the system state, - * not for synchronization control. - * - * @return {@code true} if any thread holds this lock and - * {@code false} otherwise - */ - public boolean isLocked() { - return sync.isLocked(); - } - - /** - * Returns {@code true} if this lock has fairness set true. - * - * @return {@code true} if this lock has fairness set true - */ - public final boolean isFair() { - return sync.isFair(); - } - - /** - * Returns the thread that currently owns this lock, or - * {@code null} if not owned. When this method is called by a - * thread that is not the owner, the return value reflects a - * best-effort approximation of current lock status. For example, - * the owner may be momentarily {@code null} even if there are - * threads trying to acquire the lock but have not yet done so. - * This method is designed to facilitate construction of - * subclasses that provide more extensive lock monitoring - * facilities. - * - * @return the owner, or {@code null} if not owned - */ - protected Thread getOwner() { - return sync.getOwner(); - } - - /** - * Queries whether any threads are waiting to acquire this lock. Note that - * because cancellations may occur at any time, a {@code true} - * return does not guarantee that any other thread will ever - * acquire this lock. This method is designed primarily for use in - * monitoring of the system state. - * - * @return {@code true} if there may be other threads waiting to - * acquire the lock - */ - public final boolean hasQueuedThreads() { - return sync.hasQueuedThreads(); - } - - - /** - * Queries whether the given thread is waiting to acquire this - * lock. Note that because cancellations may occur at any time, a - * {@code true} return does not guarantee that this thread - * will ever acquire this lock. This method is designed primarily for use - * in monitoring of the system state. - * - * @param thread the thread - * @return {@code true} if the given thread is queued waiting for this lock - * @throws NullPointerException if the thread is null - */ - public final boolean hasQueuedThread(Thread thread) { - return sync.isQueued(thread); - } - - - /** - * Returns an estimate of the number of threads waiting to - * acquire this lock. The value is only an estimate because the number of - * threads may change dynamically while this method traverses - * internal data structures. This method is designed for use in - * monitoring of the system state, not for synchronization - * control. - * - * @return the estimated number of threads waiting for this lock - */ - public final int getQueueLength() { - return sync.getQueueLength(); - } - - /** - * Returns a collection containing threads that may be waiting to - * acquire this lock. Because the actual set of threads may change - * dynamically while constructing this result, the returned - * collection is only a best-effort estimate. The elements of the - * returned collection are in no particular order. This method is - * designed to facilitate construction of subclasses that provide - * more extensive monitoring facilities. - * - * @return the collection of threads - */ - protected Collection getQueuedThreads() { - return sync.getQueuedThreads(); - } - - /** - * Queries whether any threads are waiting on the given condition - * associated with this lock. Note that because timeouts and - * interrupts may occur at any time, a {@code true} return does - * not guarantee that a future {@code signal} will awaken any - * threads. This method is designed primarily for use in - * monitoring of the system state. - * - * @param condition the condition - * @return {@code true} if there are any waiting threads - * @throws IllegalMonitorStateException if this lock is not held - * @throws IllegalArgumentException if the given condition is - * not associated with this lock - * @throws NullPointerException if the condition is null - */ - public boolean hasWaiters(Condition condition) { - return asCondVar(condition).hasWaiters(); - } - - /** - * Returns an estimate of the number of threads waiting on the - * given condition associated with this lock. Note that because - * timeouts and interrupts may occur at any time, the estimate - * serves only as an upper bound on the actual number of waiters. - * This method is designed for use in monitoring of the system - * state, not for synchronization control. - * - * @param condition the condition - * @return the estimated number of waiting threads - * @throws IllegalMonitorStateException if this lock is not held - * @throws IllegalArgumentException if the given condition is - * not associated with this lock - * @throws NullPointerException if the condition is null - */ - public int getWaitQueueLength(Condition condition) { - return asCondVar(condition).getWaitQueueLength(); - } - - /** - * Returns a collection containing those threads that may be - * waiting on the given condition associated with this lock. - * Because the actual set of threads may change dynamically while - * constructing this result, the returned collection is only a - * best-effort estimate. The elements of the returned collection - * are in no particular order. This method is designed to - * facilitate construction of subclasses that provide more - * extensive condition monitoring facilities. - * - * @param condition the condition - * @return the collection of threads - * @throws IllegalMonitorStateException if this lock is not held - * @throws IllegalArgumentException if the given condition is - * not associated with this lock - * @throws NullPointerException if the condition is null - */ - protected Collection getWaitingThreads(Condition condition) { - return asCondVar(condition).getWaitingThreads(); - } - - /** - * Returns a string identifying this lock, as well as its lock state. - * The state, in brackets, includes either the String {@code "Unlocked"} - * or the String {@code "Locked by"} followed by the - * {@linkplain Thread#getName name} of the owning thread. - * - * @return a string identifying this lock, as well as its lock state - */ - public String toString() { - Thread o = getOwner(); - return super.toString() + ((o == null) ? - "[Unlocked]" : - "[Locked by thread " + o.getName() + "]"); - } - - private CondVar asCondVar(Condition condition) { - if (condition == null) - throw new NullPointerException(); - if (!(condition instanceof CondVar)) - throw new IllegalArgumentException("not owner"); - CondVar condVar = (CondVar)condition; - if (condVar.lock != this) - throw new IllegalArgumentException("not owner"); - return condVar; - } -} diff --git a/src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java b/src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java deleted file mode 100644 index 914d242100..0000000000 --- a/src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java +++ /dev/null @@ -1,1341 +0,0 @@ -/* - * 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/licenses/publicdomain - */ - -package scala.actors.threadpool.locks; - -import java.util.HashMap; -import scala.actors.threadpool.*; -import scala.actors.threadpool.helpers.*; - -/** - * An implementation of {@link ReadWriteLock} supporting similar - * semantics to {@link ReentrantLock}. - *

This class has the following properties: - * - *

    - *
  • Acquisition order - * - *

    The order of entry - * to the read and write lock is unspecified, subject to reentrancy - * constraints. A nonfair lock that is continuously contended may - * indefinitely postpone one or more reader or writer threads, but - * will normally have higher throughput than a fair lock. - *

    - * - * DEPARTURE FROM java.util.concurrent: this implementation impose - * a writer-preference and thus its acquisition order may be different - * than in java.util.concurrent. - * - *

  • Reentrancy - * - *

    This lock allows both readers and writers to reacquire read or - * write locks in the style of a {@link ReentrantLock}. Non-reentrant - * readers are not allowed until all write locks held by the writing - * thread have been released. - * - *

    Additionally, a writer can acquire the read lock, but not - * vice-versa. Among other applications, reentrancy can be useful - * when write locks are held during calls or callbacks to methods that - * perform reads under read locks. If a reader tries to acquire the - * write lock it will never succeed. - * - *

  • Lock downgrading - *

    Reentrancy also allows downgrading from the write lock to a read lock, - * by acquiring the write lock, then the read lock and then releasing the - * write lock. However, upgrading from a read lock to the write lock is - * not possible. - * - *

  • Interruption of lock acquisition - *

    The read lock and write lock both support interruption during lock - * acquisition. - * - *

  • {@link Condition} support - *

    The write lock provides a {@link Condition} implementation that - * behaves in the same way, with respect to the write lock, as the - * {@link Condition} implementation provided by - * {@link ReentrantLock#newCondition} does for {@link ReentrantLock}. - * This {@link Condition} can, of course, only be used with the write lock. - * - *

    The read lock does not support a {@link Condition} and - * {@code readLock().newCondition()} throws - * {@code UnsupportedOperationException}. - * - *

  • Instrumentation - *

    This class supports methods to determine whether locks - * are held or contended. These methods are designed for monitoring - * system state, not for synchronization control. - *

- * - *

Serialization of this class behaves in the same way as built-in - * locks: a deserialized lock is in the unlocked state, regardless of - * its state when serialized. - * - *

Sample usages. Here is a code sketch showing how to exploit - * reentrancy to perform lock downgrading after updating a cache (exception - * handling is elided for simplicity): - *

- * class CachedData {
- *   Object data;
- *   volatile boolean cacheValid;
- *   ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
- *
- *   void processCachedData() {
- *     rwl.readLock().lock();
- *     if (!cacheValid) {
- *        // Must release read lock before acquiring write lock
- *        rwl.readLock().unlock();
- *        rwl.writeLock().lock();
- *        // Recheck state because another thread might have acquired
- *        //   write lock and changed state before we did.
- *        if (!cacheValid) {
- *          data = ...
- *          cacheValid = true;
- *        }
- *        // Downgrade by acquiring read lock before releasing write lock
- *        rwl.readLock().lock();
- *        rwl.writeLock().unlock(); // Unlock write, still hold read
- *     }
- *
- *     use(data);
- *     rwl.readLock().unlock();
- *   }
- * }
- * 
- * - * ReentrantReadWriteLocks can be used to improve concurrency in some - * uses of some kinds of Collections. This is typically worthwhile - * only when the collections are expected to be large, accessed by - * more reader threads than writer threads, and entail operations with - * overhead that outweighs synchronization overhead. For example, here - * is a class using a TreeMap that is expected to be large and - * concurrently accessed. - * - *
{@code
- * class RWDictionary {
- *    private final Map m = new TreeMap();
- *    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
- *    private final Lock r = rwl.readLock();
- *    private final Lock w = rwl.writeLock();
- *
- *    public Data get(String key) {
- *        r.lock();
- *        try { return m.get(key); }
- *        finally { r.unlock(); }
- *    }
- *    public String[] allKeys() {
- *        r.lock();
- *        try { return m.keySet().toArray(); }
- *        finally { r.unlock(); }
- *    }
- *    public Data put(String key, Data value) {
- *        w.lock();
- *        try { return m.put(key, value); }
- *        finally { w.unlock(); }
- *    }
- *    public void clear() {
- *        w.lock();
- *        try { m.clear(); }
- *        finally { w.unlock(); }
- *    }
- * }}
- * - *

Implementation Notes

- * - *

This lock supports a maximum of 65535 recursive write locks - * and 65535 read locks. Attempts to exceed these limits result in - * {@link Error} throws from locking methods. - * - * @since 1.5 - * @author Doug Lea - * - */ -public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable { - private static final long serialVersionUID = -3463448656717690166L; - - final ReadLock readerLock_ = new ReadLock(this); - final WriteLock writerLock_ = new WriteLock(this); - - final Sync sync; - - /** - * Creates a new {@code ReentrantReadWriteLock} with - * default (nonfair) ordering properties. - */ - public ReentrantReadWriteLock() { - this.sync = new NonfairSync(); - } - - public Lock writeLock() { return writerLock_; } - public Lock readLock() { return readerLock_; } - - /** - * Synchronization implementation for ReentrantReadWriteLock. - * Subclassed into fair and nonfair versions. - */ - private abstract static class Sync implements java.io.Serializable { - - private static final int NONE = 0; - private static final int READER = 1; - private static final int WRITER = 2; - - transient int activeReaders_ = 0; - transient Thread activeWriter_ = null; - transient int waitingReaders_ = 0; - transient int waitingWriters_ = 0; - - /** Number of acquires on write lock by activeWriter_ thread **/ - transient int writeHolds_ = 0; - - /** Number of acquires on read lock by any reader thread **/ - transient HashMap readers_ = new HashMap(); - - /** cache/reuse the special Integer value one to speed up readlocks **/ - static final Integer IONE = new Integer(1); - - Sync() {} - - /* - Each of these variants is needed to maintain atomicity - of wait counts during wait loops. They could be - made faster by manually inlining each other. We hope that - compilers do this for us though. - */ - - synchronized boolean startReadFromNewReader() { - boolean pass = startRead(); - if (!pass) ++waitingReaders_; - return pass; - } - - synchronized boolean startWriteFromNewWriter() { - boolean pass = startWrite(); - if (!pass) ++waitingWriters_; - return pass; - } - - synchronized boolean startReadFromWaitingReader() { - boolean pass = startRead(); - if (pass) --waitingReaders_; - return pass; - } - - synchronized boolean startWriteFromWaitingWriter() { - boolean pass = startWrite(); - if (pass) --waitingWriters_; - return pass; - } - - /* - A bunch of small synchronized methods are needed - to allow communication from the Lock objects - back to this object, that serves as controller - */ - - synchronized void cancelledWaitingReader() { --waitingReaders_; } - synchronized void cancelledWaitingWriter() { --waitingWriters_; } - - boolean allowReader() { - return (activeWriter_ == null && waitingWriters_ == 0) || - activeWriter_ == Thread.currentThread(); - } - - synchronized boolean startRead() { - Thread t = Thread.currentThread(); - Object c = readers_.get(t); - if (c != null) { // already held -- just increment hold count - readers_.put(t, new Integer( ( (Integer) (c)).intValue() + 1)); - ++activeReaders_; - return true; - } - else if (allowReader()) { - readers_.put(t, IONE); - ++activeReaders_; - return true; - } - else - return false; - } - - synchronized boolean startWrite() { - if (activeWriter_ == Thread.currentThread()) { // already held; re-acquire - ++writeHolds_; - return true; - } - else if (writeHolds_ == 0) { - if (activeReaders_ == 0 || - (readers_.size() == 1 && - readers_.get(Thread.currentThread()) != null)) { - activeWriter_ = Thread.currentThread(); - writeHolds_ = 1; - return true; - } - else - return false; - } - else - return false; - } - - synchronized int endRead() { - Thread t = Thread.currentThread(); - Object c = readers_.get(t); - if (c == null) - throw new IllegalMonitorStateException(); - --activeReaders_; - if (c != IONE) { // more than one hold; decrement count - int h = ( (Integer) (c)).intValue() - 1; - Integer ih = (h == 1) ? IONE : new Integer(h); - readers_.put(t, ih); - return NONE; - } - else { - readers_.remove(t); - - if (writeHolds_ > 0) // a write lock is still held by current thread - return NONE; - else if (activeReaders_ == 0 && waitingWriters_ > 0) - return WRITER; - else - return NONE; - } - } - - synchronized int endWrite() { - if (activeWriter_ != Thread.currentThread()) { - throw new IllegalMonitorStateException(); - } - --writeHolds_; - if (writeHolds_ > 0) // still being held - return NONE; - else { - activeWriter_ = null; - if (waitingReaders_ > 0 && allowReader()) - return READER; - else if (waitingWriters_ > 0) - return WRITER; - else - return NONE; - } - } - - synchronized Thread getOwner() { - return activeWriter_; - } - - synchronized int getReadLockCount() { - return activeReaders_; - } - - synchronized boolean isWriteLocked() { - return activeWriter_ != null; - } - - synchronized boolean isWriteLockedByCurrentThread() { - return activeWriter_ == Thread.currentThread(); - } - - synchronized int getWriteHoldCount() { - return isWriteLockedByCurrentThread() ? writeHolds_ : 0; - } - - synchronized int getReadHoldCount() { - if (activeReaders_ == 0) return 0; - Thread t = Thread.currentThread(); - Integer i = readers_.get(t); - return (i == null) ? 0 : i.intValue(); - } - - final synchronized boolean hasQueuedThreads() { - return waitingWriters_ > 0 || waitingReaders_ > 0; - } - - final synchronized int getQueueLength() { - return waitingWriters_ + waitingReaders_; - } - - private void readObject(java.io.ObjectInputStream in) - throws java.io.IOException, ClassNotFoundException { - in.defaultReadObject(); - // readers_ is transient, need to reinitialize. Let's flush the memory - // and ensure visibility by synchronizing (all other accesses to - // readers_ are also synchronized on "this") - synchronized (this) { - readers_ = new HashMap(); - } - } - } - - /** - * Nonfair version of Sync - */ - private static class NonfairSync extends Sync { - private static final long serialVersionUID = -2392241841540339773L; - - NonfairSync() {} - } - - /** - * The lock returned by method {@link ReentrantReadWriteLock#readLock}. - */ - public static class ReadLock implements Lock, java.io.Serializable { - - private static final long serialVersionUID = -5992448646407690164L; - - final ReentrantReadWriteLock lock; - - /** - * Constructor for use by subclasses - * - * @param lock the outer lock object - * @throws NullPointerException if the lock is null - */ - protected ReadLock(ReentrantReadWriteLock lock) { - if (lock == null) throw new NullPointerException(); - this.lock = lock; - } - - /** - * Acquires the read lock. - * - *

Acquires the read lock if the write lock is not held by - * another thread and returns immediately. - * - *

If the write lock is held by another thread then - * the current thread becomes disabled for thread scheduling - * purposes and lies dormant until the read lock has been acquired. - */ - public void lock() { - synchronized (this) { - if (lock.sync.startReadFromNewReader()) return; - boolean wasInterrupted = Thread.interrupted(); - try { - while (true) { - try { - ReadLock.this.wait(); - } - catch (InterruptedException ex) { - wasInterrupted = true; - // no need to propagate the potentially masked - // signal, since readers are always notified all - } - if (lock.sync.startReadFromWaitingReader()) return; - } - } - finally { - if (wasInterrupted) Thread.currentThread().interrupt(); - } - } - } - - /** - * Acquires the read lock unless the current thread is - * {@linkplain Thread#interrupt interrupted}. - * - *

Acquires the read lock if the write lock is not held - * by another thread and returns immediately. - * - *

If the write lock is held by another thread then the - * current thread becomes disabled for thread scheduling - * purposes and lies dormant until one of two things happens: - * - *

    - * - *
  • The read lock is acquired by the current thread; or - * - *
  • Some other thread {@linkplain Thread#interrupt interrupts} - * the current thread. - * - *
- * - *

If the current thread: - * - *

    - * - *
  • has its interrupted status set on entry to this method; or - * - *
  • is {@linkplain Thread#interrupt interrupted} while - * acquiring the read lock, - * - *
- * - * then {@link InterruptedException} is thrown and the current - * thread's interrupted status is cleared. - * - *

In this implementation, as this method is an explicit - * interruption point, preference is given to responding to - * the interrupt over normal or reentrant acquisition of the - * lock. - * - * @throws InterruptedException if the current thread is interrupted - */ - public void lockInterruptibly() throws InterruptedException { - if (Thread.interrupted()) throw new InterruptedException(); - InterruptedException ie = null; - synchronized (this) { - if (!lock.sync.startReadFromNewReader()) { - for (; ; ) { - try { - ReadLock.this.wait(); - if (lock.sync.startReadFromWaitingReader()) - return; - } - catch (InterruptedException ex) { - lock.sync.cancelledWaitingReader(); - ie = ex; - break; - } - } - } - } - if (ie != null) { - // fall through outside synch on interrupt. - // This notification is not really needed here, - // but may be in plausible subclasses - lock.writerLock_.signalWaiters(); - throw ie; - } - } - - /** - * Acquires the read lock only if the write lock is not held by - * another thread at the time of invocation. - * - *

Acquires the read lock if the write lock is not held by - * another thread and returns immediately with the value - * {@code true}. Even when this lock has been set to use a - * fair ordering policy, a call to {@code tryLock()} - * will immediately acquire the read lock if it is - * available, whether or not other threads are currently - * waiting for the read lock. This "barging" behavior - * can be useful in certain circumstances, even though it - * breaks fairness. If you want to honor the fairness setting - * for this lock, then use {@link #tryLock(long, TimeUnit) - * tryLock(0, TimeUnit.SECONDS) } which is almost equivalent - * (it also detects interruption). - * - *

If the write lock is held by another thread then - * this method will return immediately with the value - * {@code false}. - * - * @return {@code true} if the read lock was acquired - */ - public boolean tryLock() { - return lock.sync.startRead(); - } - - /** - * Acquires the read lock if the write lock is not held by - * another thread within the given waiting time and the - * current thread has not been {@linkplain Thread#interrupt - * interrupted}. - * - *

Acquires the read lock if the write lock is not held by - * another thread and returns immediately with the value - * {@code true}. If this lock has been set to use a fair - * ordering policy then an available lock will not be - * acquired if any other threads are waiting for the - * lock. This is in contrast to the {@link #tryLock()} - * method. If you want a timed {@code tryLock} that does - * permit barging on a fair lock then combine the timed and - * un-timed forms together: - * - *

if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
-         * 
- * - *

If the write lock is held by another thread then the - * current thread becomes disabled for thread scheduling - * purposes and lies dormant until one of three things happens: - * - *

    - * - *
  • The read lock is acquired by the current thread; or - * - *
  • Some other thread {@linkplain Thread#interrupt interrupts} - * the current thread; or - * - *
  • The specified waiting time elapses. - * - *
- * - *

If the read lock is acquired then the value {@code true} is - * returned. - * - *

If the current thread: - * - *

    - * - *
  • has its interrupted status set on entry to this method; or - * - *
  • is {@linkplain Thread#interrupt interrupted} while - * acquiring the read lock, - * - *
then {@link InterruptedException} is thrown and the - * current thread's interrupted status is cleared. - * - *

If the specified waiting time elapses then the value - * {@code false} is returned. If the time is less than or - * equal to zero, the method will not wait at all. - * - *

In this implementation, as this method is an explicit - * interruption point, preference is given to responding to - * the interrupt over normal or reentrant acquisition of the - * lock, and over reporting the elapse of the waiting time. - * - * @param timeout the time to wait for the read lock - * @param unit the time unit of the timeout argument - * @return {@code true} if the read lock was acquired - * @throws InterruptedException if the current thread is interrupted - * @throws NullPointerException if the time unit is null - * - */ - public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { - if (Thread.interrupted()) throw new InterruptedException(); - InterruptedException ie = null; - long nanos = unit.toNanos(timeout); - synchronized (this) { - if (nanos <= 0) - return lock.sync.startRead(); - else if (lock.sync.startReadFromNewReader()) - return true; - else { - long deadline = Utils.nanoTime() + nanos; - for (; ; ) { - try { - TimeUnit.NANOSECONDS.timedWait(ReadLock.this, nanos); - } - catch (InterruptedException ex) { - lock.sync.cancelledWaitingReader(); - ie = ex; - break; - } - if (lock.sync.startReadFromWaitingReader()) - return true; - else { - nanos = deadline - Utils.nanoTime(); - if (nanos <= 0) { - lock.sync.cancelledWaitingReader(); - break; - } - } - } - } - } - // safeguard on interrupt or timeout: - lock.writerLock_.signalWaiters(); - if (ie != null) - throw ie; - else - return false; // timed out - } - - /** - * Attempts to release this lock. - * - *

If the number of readers is now zero then the lock - * is made available for write lock attempts. - */ - public void unlock() { - switch (lock.sync.endRead()) { - case Sync.NONE: return; - case Sync.READER: lock.readerLock_.signalWaiters(); return; - case Sync.WRITER: lock.writerLock_.signalWaiters(); return; - } - } - - /** - * Throws {@code UnsupportedOperationException} because - * {@code ReadLocks} do not support conditions. - * - * @throws UnsupportedOperationException always - */ - public Condition newCondition() { - throw new UnsupportedOperationException(); - } - - synchronized void signalWaiters() { - notifyAll(); - } - - /** - * Returns a string identifying this lock, as well as its lock state. - * The state, in brackets, includes the String {@code "Read locks ="} - * followed by the number of held read locks. - * - * @return a string identifying this lock, as well as its lock state - */ - public String toString() { - int r = lock.getReadLockCount(); - return super.toString() + - "[Read locks = " + r + "]"; - } - - } - - /** - * The lock returned by method {@link ReentrantReadWriteLock#writeLock}. - */ - public static class WriteLock implements Lock, CondVar.ExclusiveLock, - java.io.Serializable { - - private static final long serialVersionUID = -4992448646407690164L; - final ReentrantReadWriteLock lock; - - /** - * Constructor for use by subclasses - * - * @param lock the outer lock object - * @throws NullPointerException if the lock is null - */ - protected WriteLock(ReentrantReadWriteLock lock) { - if (lock == null) throw new NullPointerException(); - this.lock = lock; - } - - /** - * Acquires the write lock. - * - *

Acquires the write lock if neither the read nor write lock - * are held by another thread - * and returns immediately, setting the write lock hold count to - * one. - * - *

If the current thread already holds the write lock then the - * hold count is incremented by one and the method returns - * immediately. - * - *

If the lock is held by another thread then the current - * thread becomes disabled for thread scheduling purposes and - * lies dormant until the write lock has been acquired, at which - * time the write lock hold count is set to one. - */ - public void lock() { - synchronized (this) { - if (lock.sync.startWriteFromNewWriter()) return; - boolean wasInterrupted = Thread.interrupted(); - try { - while (true) { - try { - WriteLock.this.wait(); - } - catch (InterruptedException ex) { - wasInterrupted = true; - // no need to notify; if we were notified, - // we will act as notified, and succeed in - // startWrite and return - } - if (lock.sync.startWriteFromWaitingWriter()) return; - } - } - finally { - if (wasInterrupted) Thread.currentThread().interrupt(); - } - } - } - - /** - * Acquires the write lock unless the current thread is - * {@linkplain Thread#interrupt interrupted}. - * - *

Acquires the write lock if neither the read nor write lock - * are held by another thread - * and returns immediately, setting the write lock hold count to - * one. - * - *

If the current thread already holds this lock then the - * hold count is incremented by one and the method returns - * immediately. - * - *

If the lock is held by another thread then the current - * thread becomes disabled for thread scheduling purposes and - * lies dormant until one of two things happens: - * - *

    - * - *
  • The write lock is acquired by the current thread; or - * - *
  • Some other thread {@linkplain Thread#interrupt interrupts} - * the current thread. - * - *
- * - *

If the write lock is acquired by the current thread then the - * lock hold count is set to one. - * - *

If the current thread: - * - *

    - * - *
  • has its interrupted status set on entry to this method; - * or - * - *
  • is {@linkplain Thread#interrupt interrupted} while - * acquiring the write lock, - * - *
- * - * then {@link InterruptedException} is thrown and the current - * thread's interrupted status is cleared. - * - *

In this implementation, as this method is an explicit - * interruption point, preference is given to responding to - * the interrupt over normal or reentrant acquisition of the - * lock. - * - * @throws InterruptedException if the current thread is interrupted - */ - public void lockInterruptibly() throws InterruptedException { - if (Thread.interrupted()) throw new InterruptedException(); - InterruptedException ie = null; - synchronized (this) { - if (!lock.sync.startWriteFromNewWriter()) { - for (; ; ) { - try { - WriteLock.this.wait(); - if (lock.sync.startWriteFromWaitingWriter()) - return; - } - catch (InterruptedException ex) { - lock.sync.cancelledWaitingWriter(); - WriteLock.this.notify(); - ie = ex; - break; - } - } - } - } - if (ie != null) { - // Fall through outside synch on interrupt. - // On exception, we may need to signal readers. - // It is not worth checking here whether it is strictly necessary. - lock.readerLock_.signalWaiters(); - throw ie; - } - } - - /** - * Acquires the write lock only if it is not held by another thread - * at the time of invocation. - * - *

Acquires the write lock if neither the read nor write lock - * are held by another thread - * and returns immediately with the value {@code true}, - * setting the write lock hold count to one. Even when this lock has - * been set to use a fair ordering policy, a call to - * {@code tryLock()} will immediately acquire the - * lock if it is available, whether or not other threads are - * currently waiting for the write lock. This "barging" - * behavior can be useful in certain circumstances, even - * though it breaks fairness. If you want to honor the - * fairness setting for this lock, then use {@link - * #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) } - * which is almost equivalent (it also detects interruption). - * - *

If the current thread already holds this lock then the - * hold count is incremented by one and the method returns - * {@code true}. - * - *

If the lock is held by another thread then this method - * will return immediately with the value {@code false}. - * - * @return {@code true} if the lock was free and was acquired - * by the current thread, or the write lock was already held - * by the current thread; and {@code false} otherwise. - */ - public boolean tryLock() { - return lock.sync.startWrite(); - } - - /** - * Acquires the write lock if it is not held by another thread - * within the given waiting time and the current thread has - * not been {@linkplain Thread#interrupt interrupted}. - * - *

Acquires the write lock if neither the read nor write lock - * are held by another thread - * and returns immediately with the value {@code true}, - * setting the write lock hold count to one. If this lock has been - * set to use a fair ordering policy then an available lock - * will not be acquired if any other threads are - * waiting for the write lock. This is in contrast to the {@link - * #tryLock()} method. If you want a timed {@code tryLock} - * that does permit barging on a fair lock then combine the - * timed and un-timed forms together: - * - *

if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
-         * 
- * - *

If the current thread already holds this lock then the - * hold count is incremented by one and the method returns - * {@code true}. - * - *

If the lock is held by another thread then the current - * thread becomes disabled for thread scheduling purposes and - * lies dormant until one of three things happens: - * - *

    - * - *
  • The write lock is acquired by the current thread; or - * - *
  • Some other thread {@linkplain Thread#interrupt interrupts} - * the current thread; or - * - *
  • The specified waiting time elapses - * - *
- * - *

If the write lock is acquired then the value {@code true} is - * returned and the write lock hold count is set to one. - * - *

If the current thread: - * - *

    - * - *
  • has its interrupted status set on entry to this method; - * or - * - *
  • is {@linkplain Thread#interrupt interrupted} while - * acquiring the write lock, - * - *
- * - * then {@link InterruptedException} is thrown and the current - * thread's interrupted status is cleared. - * - *

If the specified waiting time elapses then the value - * {@code false} is returned. If the time is less than or - * equal to zero, the method will not wait at all. - * - *

In this implementation, as this method is an explicit - * interruption point, preference is given to responding to - * the interrupt over normal or reentrant acquisition of the - * lock, and over reporting the elapse of the waiting time. - * - * @param timeout the time to wait for the write lock - * @param unit the time unit of the timeout argument - * - * @return {@code true} if the lock was free and was acquired - * by the current thread, or the write lock was already held by the - * current thread; and {@code false} if the waiting time - * elapsed before the lock could be acquired. - * - * @throws InterruptedException if the current thread is interrupted - * @throws NullPointerException if the time unit is null - * - */ - public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { - if (Thread.interrupted()) throw new InterruptedException(); - InterruptedException ie = null; - long nanos = unit.toNanos(timeout); - synchronized (this) { - if (nanos <= 0) - return lock.sync.startWrite(); - else if (lock.sync.startWriteFromNewWriter()) - return true; - else { - long deadline = Utils.nanoTime() + nanos; - for (; ; ) { - try { - TimeUnit.NANOSECONDS.timedWait(WriteLock.this, nanos); - } - catch (InterruptedException ex) { - lock.sync.cancelledWaitingWriter(); - WriteLock.this.notify(); - ie = ex; - break; - } - if (lock.sync.startWriteFromWaitingWriter()) - return true; - else { - nanos = deadline - Utils.nanoTime(); - if (nanos <= 0) { - lock.sync.cancelledWaitingWriter(); - WriteLock.this.notify(); - break; - } - } - } - } - } - - lock.readerLock_.signalWaiters(); - if (ie != null) - throw ie; - else - return false; // timed out - } - - /** - * Attempts to release this lock. - * - *

If the current thread is the holder of this lock then - * the hold count is decremented. If the hold count is now - * zero then the lock is released. If the current thread is - * not the holder of this lock then {@link - * IllegalMonitorStateException} is thrown. - * - * @throws IllegalMonitorStateException if the current thread does not - * hold this lock. - */ - public void unlock() { - switch (lock.sync.endWrite()) { - case Sync.NONE: return; - case Sync.READER: lock.readerLock_.signalWaiters(); return; - case Sync.WRITER: lock.writerLock_.signalWaiters(); return; - } - } - - /** - * Returns a {@link Condition} instance for use with this - * {@link Lock} instance. - *

The returned {@link Condition} instance supports the same - * usages as do the {@link Object} monitor methods ({@link - * Object#wait() wait}, {@link Object#notify notify}, and {@link - * Object#notifyAll notifyAll}) when used with the built-in - * monitor lock. - * - *

    - * - *
  • If this write lock is not held when any {@link - * Condition} method is called then an {@link - * IllegalMonitorStateException} is thrown. (Read locks are - * held independently of write locks, so are not checked or - * affected. However it is essentially always an error to - * invoke a condition waiting method when the current thread - * has also acquired read locks, since other threads that - * could unblock it will not be able to acquire the write - * lock.) - * - *
  • When the condition {@linkplain Condition#await() waiting} - * methods are called the write lock is released and, before - * they return, the write lock is reacquired and the lock hold - * count restored to what it was when the method was called. - * - *
  • If a thread is {@linkplain Thread#interrupt interrupted} while - * waiting then the wait will terminate, an {@link - * InterruptedException} will be thrown, and the thread's - * interrupted status will be cleared. - * - *
  • Waiting threads are signalled in FIFO order. - * - *
  • The ordering of lock reacquisition for threads returning - * from waiting methods is the same as for threads initially - * acquiring the lock, which is in the default case not specified, - * but for fair locks favors those threads that have been - * waiting the longest. - * - *
- * - * @return the Condition object - */ - public Condition newCondition() { - return new CondVar(this); - } - - synchronized void signalWaiters() { - notify(); - } - - /** - * Returns a string identifying this lock, as well as its lock - * state. The state, in brackets includes either the String - * {@code "Unlocked"} or the String {@code "Locked by"} - * followed by the {@linkplain Thread#getName name} of the owning thread. - * - * @return a string identifying this lock, as well as its lock state - */ - public String toString() { - Thread o = lock.getOwner(); - return super.toString() + ((o == null) ? - "[Unlocked]" : - "[Locked by thread " + o.getName() + "]"); - } - - /** - * Queries if this write lock is held by the current thread. - * Identical in effect to {@link - * ReentrantReadWriteLock#isWriteLockedByCurrentThread}. - * - * @return {@code true} if the current thread holds this lock and - * {@code false} otherwise - * @since 1.6 - */ - public boolean isHeldByCurrentThread() { - return lock.sync.isWriteLockedByCurrentThread(); - } - - /** - * Queries the number of holds on this write lock by the current - * thread. A thread has a hold on a lock for each lock action - * that is not matched by an unlock action. Identical in effect - * to {@link ReentrantReadWriteLock#getWriteHoldCount}. - * - * @return the number of holds on this lock by the current thread, - * or zero if this lock is not held by the current thread - * @since 1.6 - */ - public int getHoldCount() { - return lock.sync.getWriteHoldCount(); - } - - } - - // Instrumentation and status - - /** - * Returns {@code true} if this lock has fairness set true. - * - * @return {@code true} if this lock has fairness set true - */ - public final boolean isFair() { - return false; - } - - /** - * Returns the thread that currently owns the write lock, or - * {@code null} if not owned. When this method is called by a - * thread that is not the owner, the return value reflects a - * best-effort approximation of current lock status. For example, - * the owner may be momentarily {@code null} even if there are - * threads trying to acquire the lock but have not yet done so. - * This method is designed to facilitate construction of - * subclasses that provide more extensive lock monitoring - * facilities. - * - * @return the owner, or {@code null} if not owned - */ - protected Thread getOwner() { - return sync.getOwner(); - } - - /** - * Queries the number of read locks held for this lock. This - * method is designed for use in monitoring system state, not for - * synchronization control. - * @return the number of read locks held. - */ - public int getReadLockCount() { - return sync.getReadLockCount(); - } - - /** - * Queries if the write lock is held by any thread. This method is - * designed for use in monitoring system state, not for - * synchronization control. - * - * @return {@code true} if any thread holds the write lock and - * {@code false} otherwise - */ - public boolean isWriteLocked() { - return sync.isWriteLocked(); - } - - /** - * Queries if the write lock is held by the current thread. - * - * @return {@code true} if the current thread holds the write lock and - * {@code false} otherwise - */ - public boolean isWriteLockedByCurrentThread() { - return sync.isWriteLockedByCurrentThread(); - } - - /** - * Queries the number of reentrant write holds on this lock by the - * current thread. A writer thread has a hold on a lock for - * each lock action that is not matched by an unlock action. - * - * @return the number of holds on the write lock by the current thread, - * or zero if the write lock is not held by the current thread - */ - public int getWriteHoldCount() { - return sync.getWriteHoldCount(); - } - - /** - * Queries the number of reentrant read holds on this lock by the - * current thread. A reader thread has a hold on a lock for - * each lock action that is not matched by an unlock action. - * - * @return the number of holds on the read lock by the current thread, - * or zero if the read lock is not held by the current thread - * @since 1.6 - */ - public int getReadHoldCount() { - return sync.getReadHoldCount(); - } - - -// /** -// * Returns a collection containing threads that may be waiting to -// * acquire the write lock. Because the actual set of threads may -// * change dynamically while constructing this result, the returned -// * collection is only a best-effort estimate. The elements of the -// * returned collection are in no particular order. This method is -// * designed to facilitate construction of subclasses that provide -// * more extensive lock monitoring facilities. -// * @return the collection of threads -// */ -// protected Collection getQueuedWriterThreads() { -// return sync.getExclusiveQueuedThreads(); -// } -// -// /** -// * Returns a collection containing threads that may be waiting to -// * acquire the read lock. Because the actual set of threads may -// * change dynamically while constructing this result, the returned -// * collection is only a best-effort estimate. The elements of the -// * returned collection are in no particular order. This method is -// * designed to facilitate construction of subclasses that provide -// * more extensive lock monitoring facilities. -// * @return the collection of threads -// */ -// protected Collection getQueuedReaderThreads() { -// return sync.getSharedQueuedThreads(); -// } -// - /** - * Queries whether any threads are waiting to acquire the read or - * write lock. Note that because cancellations may occur at any - * time, a {@code true} return does not guarantee that any other - * thread will ever acquire a lock. This method is designed - * primarily for use in monitoring of the system state. - * - * @return {@code true} if there may be other threads waiting to - * acquire the lock - */ - public final boolean hasQueuedThreads() { - return sync.hasQueuedThreads(); - } -// -// /** -// * Queries whether the given thread is waiting to acquire either -// * the read or write lock. Note that because cancellations may -// * occur at any time, a true return does not guarantee -// * that this thread will ever acquire a lock. This method is -// * designed primarily for use in monitoring of the system state. -// * -// * @param thread the thread -// * @return true if the given thread is queued waiting for this lock. -// * @throws NullPointerException if thread is null -// */ -// public final boolean hasQueuedThread(Thread thread) { -// return sync.isQueued(thread); -// } - - /** - * Returns an estimate of the number of threads waiting to acquire - * either the read or write lock. The value is only an estimate - * because the number of threads may change dynamically while this - * method traverses internal data structures. This method is - * designed for use in monitoring of the system state, not for - * synchronization control. - * - * @return the estimated number of threads waiting for this lock - */ - public final int getQueueLength() { - return sync.getQueueLength(); - } - -// /** -// * Returns a collection containing threads that may be waiting to -// * acquire either the read or write lock. Because the actual set -// * of threads may change dynamically while constructing this -// * result, the returned collection is only a best-effort estimate. -// * The elements of the returned collection are in no particular -// * order. This method is designed to facilitate construction of -// * subclasses that provide more extensive monitoring facilities. -// * @return the collection of threads -// */ -// protected Collection getQueuedThreads() { -// return sync.getQueuedThreads(); -// } -// -// /** -// * Queries whether any threads are waiting on the given condition -// * associated with the write lock. Note that because timeouts and -// * interrupts may occur at any time, a true return does -// * not guarantee that a future signal will awaken any -// * threads. This method is designed primarily for use in -// * monitoring of the system state. -// * @param condition the condition -// * @return true if there are any waiting threads. -// * @throws IllegalMonitorStateException if this lock -// * is not held -// * @throws IllegalArgumentException if the given condition is -// * not associated with this lock -// * @throws NullPointerException if condition null -// */ -// public boolean hasWaiters(Condition condition) { -// if (condition == null) -// throw new NullPointerException(); -// if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) -// throw new IllegalArgumentException("not owner"); -// return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition); -// } - -// /** -// * Returns an estimate of the number of threads waiting on the -// * given condition associated with the write lock. Note that because -// * timeouts and interrupts may occur at any time, the estimate -// * serves only as an upper bound on the actual number of waiters. -// * This method is designed for use in monitoring of the system -// * state, not for synchronization control. -// * @param condition the condition -// * @return the estimated number of waiting threads. -// * @throws IllegalMonitorStateException if this lock -// * is not held -// * @throws IllegalArgumentException if the given condition is -// * not associated with this lock -// * @throws NullPointerException if condition null -// */ -// public int getWaitQueueLength(Condition condition) { -// if (condition == null) -// throw new NullPointerException(); -// if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) -// throw new IllegalArgumentException("not owner"); -// return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition); -// } -// -// /** -// * Returns a collection containing those threads that may be -// * waiting on the given condition associated with the write lock. -// * Because the actual set of threads may change dynamically while -// * constructing this result, the returned collection is only a -// * best-effort estimate. The elements of the returned collection -// * are in no particular order. This method is designed to -// * facilitate construction of subclasses that provide more -// * extensive condition monitoring facilities. -// * @param condition the condition -// * @return the collection of threads -// * @throws IllegalMonitorStateException if this lock -// * is not held -// * @throws IllegalArgumentException if the given condition is -// * not associated with this lock -// * @throws NullPointerException if condition null -// */ -// protected Collection getWaitingThreads(Condition condition) { -// if (condition == null) -// throw new NullPointerException(); -// if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) -// throw new IllegalArgumentException("not owner"); -// return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition); -// } - - /** - * Returns a string identifying this lock, as well as its lock state. - * The state, in brackets, includes the String {@code "Write locks ="} - * followed by the number of reentrantly held write locks, and the - * String {@code "Read locks ="} followed by the number of held - * read locks. - * - * @return a string identifying this lock, as well as its lock state - */ - public String toString() { - return super.toString() + - "[Write locks = " + getWriteHoldCount() + - ", Read locks = " + getReadLockCount() + "]"; - } -} diff --git a/src/build/bnd/scala-actors.bnd b/src/build/bnd/scala-actors.bnd deleted file mode 100644 index 69885fc2bf..0000000000 --- a/src/build/bnd/scala-actors.bnd +++ /dev/null @@ -1,7 +0,0 @@ -Bundle-Name: Scala Actors -Bundle-SymbolicName: org.scala-lang.scala-actors -ver: @VERSION@ -Bundle-Version: ${ver} -Export-Package: *;version=${ver} -Import-Package: scala.*;version="${range;[==,=+);${ver}}",* -Bundle-RequiredExecutionEnvironment: JavaSE-1.6, JavaSE-1.7 diff --git a/src/build/dbuild-meta-json-gen.scala b/src/build/dbuild-meta-json-gen.scala index d1d4c12b3f..c235978d77 100644 --- a/src/build/dbuild-meta-json-gen.scala +++ b/src/build/dbuild-meta-json-gen.scala @@ -30,10 +30,6 @@ val meta = // Seq(ProjectRef("scala-interactive", "org.scala-lang")), // Seq(ProjectRef("scala-compiler", "org.scala-lang"), ProjectRef("scaladoc", "org.scala-lang"))), - Project("scala-actors", "org.scala-lang", - Seq(ProjectRef("scala-actors", "org.scala-lang")), - Seq(ProjectRef("scala-library", "org.scala-lang"))), - // Project("scaladoc", "org.scala-lang", // Seq(ProjectRef("scaladoc", "org.scala-lang")), // Seq(ProjectRef("scala-compiler", "org.scala-lang"),ProjectRef("scala-partest", "org.scala-lang"), ProjectRef("scala-xml", "org.scala-lang"), ProjectRef("scala-parser-combinators", "org.scala-lang"))), diff --git a/src/build/maven/scala-actors-pom.xml b/src/build/maven/scala-actors-pom.xml deleted file mode 100644 index a0ebcecad1..0000000000 --- a/src/build/maven/scala-actors-pom.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - 4.0.0 - org.scala-lang - scala-actors - jar - @VERSION@ - Scala Actors library - Deprecated Actors Library for Scala - http://www.scala-lang.org/ - 2006 - - LAMP/EPFL - http://lamp.epfl.ch/ - - - - BSD 3-Clause - http://www.scala-lang.org/license.html - repo - - - - scm:git:git://github.com/scala/scala.git - https://github.com/scala/scala.git - - - JIRA - https://issues.scala-lang.org/ - - - http://www.scala-lang.org/api/@VERSION@/ - - - - org.scala-lang - scala-library - @VERSION@ - - - - - lamp - EPFL LAMP - - - Typesafe - Typesafe, Inc. - - - diff --git a/src/build/maven/scala-library-all-pom.xml b/src/build/maven/scala-library-all-pom.xml index 8b857ccc2a..8cf6f660c9 100644 --- a/src/build/maven/scala-library-all-pom.xml +++ b/src/build/maven/scala-library-all-pom.xml @@ -59,11 +59,6 @@ akka-actor_@SCALA_BINARY_VERSION@ @AKKA_ACTOR_VERSION@ - - org.scala-lang - scala-actors-migration_@SCALA_BINARY_VERSION@ - @ACTORS_MIGRATION_VERSION@ - diff --git a/src/intellij-14/actors.iml.SAMPLE b/src/intellij-14/actors.iml.SAMPLE deleted file mode 100644 index 3da7a5f777..0000000000 --- a/src/intellij-14/actors.iml.SAMPLE +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/intellij-14/scala.ipr.SAMPLE b/src/intellij-14/scala.ipr.SAMPLE index 1e3d07466d..af0502034e 100644 --- a/src/intellij-14/scala.ipr.SAMPLE +++ b/src/intellij-14/scala.ipr.SAMPLE @@ -42,7 +42,6 @@ - diff --git a/src/intellij-14/test-junit.iml.SAMPLE b/src/intellij-14/test-junit.iml.SAMPLE index 786f02e2e2..0dd9044066 100644 --- a/src/intellij-14/test-junit.iml.SAMPLE +++ b/src/intellij-14/test-junit.iml.SAMPLE @@ -9,7 +9,6 @@ - diff --git a/src/intellij-14/test.iml.SAMPLE b/src/intellij-14/test.iml.SAMPLE index a384d72266..4492f66db6 100644 --- a/src/intellij-14/test.iml.SAMPLE +++ b/src/intellij-14/test.iml.SAMPLE @@ -7,7 +7,6 @@ - diff --git a/src/intellij/actors.iml.SAMPLE b/src/intellij/actors.iml.SAMPLE deleted file mode 100644 index b15af8b110..0000000000 --- a/src/intellij/actors.iml.SAMPLE +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/src/intellij/scala-lang.ipr.SAMPLE b/src/intellij/scala-lang.ipr.SAMPLE index 0cd3fdae6a..a22bbd11dd 100644 --- a/src/intellij/scala-lang.ipr.SAMPLE +++ b/src/intellij/scala-lang.ipr.SAMPLE @@ -202,7 +202,6 @@ - diff --git a/src/intellij/test-junit.iml.SAMPLE b/src/intellij/test-junit.iml.SAMPLE index bb51c30a4f..b633166f7a 100644 --- a/src/intellij/test-junit.iml.SAMPLE +++ b/src/intellij/test-junit.iml.SAMPLE @@ -15,7 +15,6 @@ - diff --git a/src/intellij/test-osgi.iml.SAMPLE b/src/intellij/test-osgi.iml.SAMPLE index a589aaa0a9..d2ed5be974 100644 --- a/src/intellij/test-osgi.iml.SAMPLE +++ b/src/intellij/test-osgi.iml.SAMPLE @@ -7,7 +7,6 @@ - diff --git a/src/intellij/test.iml.SAMPLE b/src/intellij/test.iml.SAMPLE index cb4a8568a1..7e19a83d34 100644 --- a/src/intellij/test.iml.SAMPLE +++ b/src/intellij/test.iml.SAMPLE @@ -20,7 +20,6 @@ - diff --git a/src/library/rootdoc.txt b/src/library/rootdoc.txt index 0e9a175fcc..95f9836cc9 100644 --- a/src/library/rootdoc.txt +++ b/src/library/rootdoc.txt @@ -46,8 +46,6 @@ Additional parts of the standard library are shipped as separate libraries. Thes - [[scala.swing `scala.swing`]] - A convenient wrapper around Java's GUI framework called Swing (scala-swing.jar) - [[scala.util.parsing `scala.util.parsing`]] - [[scala.util.parsing.combinator Parser combinators]], including an example implementation of a [[scala.util.parsing.json JSON parser]] (scala-parser-combinators.jar) - - [[scala.actors `scala.actors`]] - Actor-based concurrency (deprecated and replaced by Akka actors, - scala-actors.jar) == Automatic imports == -- cgit v1.2.3