summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/ant/FastScalac.scala3
-rw-r--r--src/compiler/scala/tools/nsc/CompileClient.scala29
-rw-r--r--src/compiler/scala/tools/nsc/CompileServer.scala59
-rw-r--r--src/compiler/scala/tools/nsc/CompileSocket.scala72
-rw-r--r--src/compiler/scala/tools/nsc/CompilerCommand.scala4
-rw-r--r--src/compiler/scala/tools/nsc/GenericRunnerCommand.scala21
-rw-r--r--src/compiler/scala/tools/nsc/MainGenericRunner.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ScriptRunner.scala6
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Power.scala199
-rw-r--r--src/compiler/scala/tools/nsc/io/Socket.scala56
-rw-r--r--src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala4
-rw-r--r--src/compiler/scala/tools/nsc/settings/FscSettings.scala20
-rw-r--r--src/compiler/scala/tools/nsc/settings/MutableSettings.scala49
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala4
-rw-r--r--src/compiler/scala/tools/util/SocketServer.scala133
-rw-r--r--src/library/scala/collection/Iterator.scala5
-rw-r--r--src/library/scala/collection/MapLike.scala6
-rw-r--r--src/library/scala/collection/Parallelizable.scala49
-rw-r--r--src/library/scala/collection/SeqLike.scala5
-rw-r--r--src/library/scala/collection/SetLike.scala6
-rw-r--r--src/library/scala/collection/TraversableLike.scala6
-rw-r--r--src/library/scala/collection/TraversableOnce.scala60
-rw-r--r--src/library/scala/collection/immutable/HashMap.scala8
-rw-r--r--src/library/scala/collection/immutable/HashSet.scala9
-rw-r--r--src/library/scala/collection/immutable/Iterable.scala5
-rw-r--r--src/library/scala/collection/immutable/MapLike.scala4
-rw-r--r--src/library/scala/collection/immutable/Range.scala10
-rw-r--r--src/library/scala/collection/immutable/Seq.scala5
-rw-r--r--src/library/scala/collection/immutable/Set.scala5
-rw-r--r--src/library/scala/collection/immutable/Vector.scala4
-rw-r--r--src/library/scala/collection/interfaces/TraversableOnceMethods.scala4
-rw-r--r--src/library/scala/collection/mutable/ArrayBuffer.scala8
-rw-r--r--src/library/scala/collection/mutable/ArrayOps.scala4
-rw-r--r--src/library/scala/collection/mutable/ArraySeq.scala8
-rw-r--r--src/library/scala/collection/mutable/HashMap.scala9
-rw-r--r--src/library/scala/collection/mutable/HashSet.scala8
-rw-r--r--src/library/scala/collection/mutable/Iterable.scala5
-rw-r--r--src/library/scala/collection/mutable/MapLike.scala4
-rw-r--r--src/library/scala/collection/mutable/SeqLike.scala6
-rw-r--r--src/library/scala/collection/mutable/SetLike.scala4
-rw-r--r--src/library/scala/collection/mutable/WrappedArray.scala8
-rw-r--r--src/library/scala/collection/parallel/ParIterableLike.scala43
-rw-r--r--src/library/scala/collection/parallel/ParMapLike.scala4
-rw-r--r--src/library/scala/collection/parallel/ParSeqLike.scala4
-rw-r--r--src/library/scala/collection/parallel/ParSetLike.scala3
-rw-r--r--src/library/scala/collection/parallel/immutable/ParIterable.scala10
-rw-r--r--src/library/scala/collection/parallel/immutable/ParMap.scala2
-rw-r--r--src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled4
-rw-r--r--src/library/scala/collection/parallel/immutable/ParRange.scala4
-rw-r--r--src/library/scala/collection/parallel/immutable/ParSet.scala4
-rw-r--r--src/library/scala/collection/parallel/mutable/ParIterable.scala5
-rw-r--r--src/library/scala/collection/parallel/mutable/ParMapLike.scala6
-rw-r--r--src/library/scala/collection/parallel/mutable/ParSeq.scala2
-rw-r--r--src/library/scala/collection/parallel/mutable/ParSetLike.scala1
-rw-r--r--src/library/scala/sys/BooleanProp.scala7
-rw-r--r--src/library/scala/sys/Prop.scala4
-rw-r--r--src/library/scala/sys/PropImpl.scala6
-rw-r--r--src/library/scala/sys/SystemProperties.scala14
-rw-r--r--test/files/run/coder/Coder.scala2
-rw-r--r--test/files/run/coder2/Coder2.scala58
-rw-r--r--test/files/run/pc-conversions.scala47
-rw-r--r--test/files/run/treePrint.scala2
62 files changed, 634 insertions, 514 deletions
diff --git a/src/compiler/scala/tools/ant/FastScalac.scala b/src/compiler/scala/tools/ant/FastScalac.scala
index 3c39bcf24d..403d9cc117 100644
--- a/src/compiler/scala/tools/ant/FastScalac.scala
+++ b/src/compiler/scala/tools/ant/FastScalac.scala
@@ -80,7 +80,6 @@ class FastScalac extends Scalac {
* Most likely this manifests in confusing and very difficult to debug behavior in fsc.
* We should warn or fix.
*/
-
val stringSettings =
List(s.outdir, s.classpath, s.bootclasspath, s.extdirs, s.encoding) flatMap (x => List(x.name, x.value))
@@ -104,7 +103,7 @@ class FastScalac extends Scalac {
val args = (cmdOptions ::: (sourceFiles map (_.toString))).toArray
try {
- if (scala.tools.nsc.CompileClient.main0(args) > 0 && failonerror)
+ if (scala.tools.nsc.CompileClient.process(args) != 0 && failonerror)
buildError("Compile failed; see the compiler error output for details.")
}
catch {
diff --git a/src/compiler/scala/tools/nsc/CompileClient.scala b/src/compiler/scala/tools/nsc/CompileClient.scala
index d1b1f751ef..9987eb0204 100644
--- a/src/compiler/scala/tools/nsc/CompileClient.scala
+++ b/src/compiler/scala/tools/nsc/CompileClient.scala
@@ -6,40 +6,37 @@
package scala.tools.nsc
import java.io.{ BufferedReader, File, InputStreamReader, PrintWriter }
-import Properties.fileEndings
-import io.Path
import settings.FscSettings
+import scala.tools.util.CompileOutputCommon
+import sys.SystemProperties.preferIPv4Stack
/** The client part of the fsc offline compiler. Instead of compiling
* things itself, it send requests to a CompileServer.
*/
-class StandardCompileClient extends HasCompileSocket {
+class StandardCompileClient extends HasCompileSocket with CompileOutputCommon {
lazy val compileSocket: CompileSocket = CompileSocket
val versionMsg = "Fast " + Properties.versionMsg
var verbose = false
- def logVerbose(msg: String) =
- if (verbose)
- Console println msg
-
- def main0(argsIn: Array[String]): Int = {
- // TODO: put -J -and -D options back. Right now they are lost
- // because bash parses them out and they don't arrive.
- val (vmArgs, fscArgs) = (Nil, argsIn.toList)
+ def process(args: Array[String]): Int = {
+ val fscArgs = args.toList
val settings = new FscSettings
val command = new CompilerCommand(fscArgs, settings)
verbose = settings.verbose.value
val shutdown = settings.shutdown.value
+ val vmArgs = settings.jvmargs.unparse ++ settings.defines.unparse ++ (
+ if (settings.preferIPv4.value) List("-D%s=true".format(preferIPv4Stack.key)) else Nil
+ )
if (settings.version.value) {
Console println versionMsg
return 0
}
- logVerbose(versionMsg)
- logVerbose(fscArgs.mkString("[Given arguments: ", " ", "]"))
- logVerbose(vmArgs.mkString("[VM arguments: ", " ", "]"))
+ info(versionMsg)
+ info(fscArgs.mkString("[Given arguments: ", " ", "]"))
+ info(vmArgs.mkString("[VM arguments: ", " ", "]"))
val socket =
if (settings.server.value == "") compileSocket.getOrCreateSocket(vmArgs mkString " ", !shutdown)
@@ -48,7 +45,7 @@ class StandardCompileClient extends HasCompileSocket {
val success = socket match {
case Some(sock) => compileOnServer(sock, fscArgs)
case _ =>
- Console.println(
+ echo(
if (shutdown) "[No compilation server running.]"
else "Compilation failed."
)
@@ -60,7 +57,7 @@ class StandardCompileClient extends HasCompileSocket {
object CompileClient extends StandardCompileClient {
def main(args: Array[String]): Unit = sys exit {
- try main0(args)
+ try process(args)
catch { case _: Exception => 1 }
}
}
diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala
index fc98e30085..a34be6226b 100644
--- a/src/compiler/scala/tools/nsc/CompileServer.scala
+++ b/src/compiler/scala/tools/nsc/CompileServer.scala
@@ -21,6 +21,11 @@ import settings.FscSettings
*/
class StandardCompileServer extends SocketServer {
lazy val compileSocket: CompileSocket = CompileSocket
+ private var compiler: Global = null
+
+ var reporter: ConsoleReporter = _
+ var shutdown = false
+ var verbose = false
val versionMsg = "Fast Scala compiler " +
Properties.versionString + " -- " +
@@ -28,16 +33,6 @@ class StandardCompileServer extends SocketServer {
val MaxCharge = 0.8
- private var compiler: Global = null
- var reporter: ConsoleReporter = _
- var shutdown = false
-
- private def exit(code: Int): Nothing = {
- System.err.close()
- System.out.close()
- sys.exit(code)
- }
-
private val runtime = Runtime.getRuntime()
import runtime.{ totalMemory, freeMemory, maxMemory }
@@ -53,9 +48,9 @@ class StandardCompileServer extends SocketServer {
}
def printMemoryStats() {
- System.out.println("New session, total memory = %s, max memory = %s, free memory = %s".format(
- totalMemory, maxMemory, freeMemory))
- System.out.flush()
+ def mb(bytes: Long) = "%dMB".format(bytes / 1000000)
+ info("New session: total memory = %s, max memory = %s, free memory = %s".format(
+ mb(totalMemory), mb(maxMemory), mb(freeMemory)))
}
def isMemoryFullEnough() = {
@@ -97,13 +92,18 @@ class StandardCompileServer extends SocketServer {
if (input == null || password != guessedPassword)
return
- val args = input.split("\0", -1).toList
+ val args = input.split("\0", -1).toList
val settings = new FscSettings(fscError)
- def logVerbose(msg: String) =
- if (settings.verbose.value)
- out println msg
+ val command = newOfflineCompilerCommand(args, settings)
- val command = newOfflineCompilerCommand(args, settings)
+ // Update the idle timeout if given
+ if (!settings.idleMins.isDefault) {
+ val mins = settings.idleMins.value
+ if (mins == 0) echo("Disabling idle timeout on compile server.")
+ else echo("Setting idle timeout to " + mins + " minutes.")
+
+ this.idleMinutes = mins
+ }
if (settings.shutdown.value) {
shutdown = true
return out.println("[Compile server exited]")
@@ -112,6 +112,7 @@ class StandardCompileServer extends SocketServer {
compiler = null
return out.println("[Compile server was reset]")
}
+ this.verbose = settings.verbose.value
reporter = new ConsoleReporter(command.settings, in, out) {
// disable prompts, so that compile server cannot block
@@ -119,14 +120,14 @@ class StandardCompileServer extends SocketServer {
}
def isCompilerReusable: Boolean = {
if (compiler == null) {
- logVerbose("[Creating new instance for compile server.]")
- logVerbose("[Compiler version: " + Properties.versionString + ".]")
+ info("[Creating new instance for compile server.]")
+ info("[Compiler version: " + Properties.versionString + ".]")
return false
}
val unequal = unequalSettings(command.settings, compiler.settings)
if (unequal.nonEmpty) {
- logVerbose("[Replacing compiler with new instance because settings are unequal.]")
- logVerbose("[Asymmetric settings: " + unequal.mkString(", ") + "]")
+ info("[Replacing compiler with new instance because settings are unequal.]")
+ info("[Asymmetric settings: " + unequal.mkString(", ") + "]")
}
unequal.isEmpty
}
@@ -144,8 +145,7 @@ class StandardCompileServer extends SocketServer {
compiler = newGlobal(command.settings, reporter)
}
val c = compiler
- val run = new c.Run()
- try run compile command.files
+ try new c.Run() compile command.files
catch {
case ex @ FatalError(msg) =>
reporter.error(null, "fatal error: " + msg)
@@ -157,7 +157,7 @@ class StandardCompileServer extends SocketServer {
}
reporter.printSummary()
if (isMemoryFullEnough) {
- logVerbose("Nulling out compiler due to memory utilization.")
+ info("Nulling out compiler due to memory utilization.")
compiler = null
}
}
@@ -166,12 +166,19 @@ class StandardCompileServer extends SocketServer {
object CompileServer extends StandardCompileServer {
/** A directory holding redirected output */
- private val redirectDir = (compileSocket.tmpDir / "output-redirects").createDirectory()
+ private lazy val redirectDir = (compileSocket.tmpDir / "output-redirects").createDirectory()
private def redirect(setter: PrintStream => Unit, filename: String): Unit =
setter(new PrintStream((redirectDir / filename).createFile().bufferedOutput()))
def main(args: Array[String]) {
+ val debug = args contains "-v"
+
+ if (debug) {
+ echo("Starting CompileServer on port " + port)
+ echo("Redirect dir is " + redirectDir)
+ }
+
redirect(System.setOut, "scala-compile-server-out.log")
redirect(System.setErr, "scala-compile-server-err.log")
System.err.println("...starting server on socket "+port+"...")
diff --git a/src/compiler/scala/tools/nsc/CompileSocket.scala b/src/compiler/scala/tools/nsc/CompileSocket.scala
index c75c6d0f22..1fd37eb70c 100644
--- a/src/compiler/scala/tools/nsc/CompileSocket.scala
+++ b/src/compiler/scala/tools/nsc/CompileSocket.scala
@@ -10,14 +10,19 @@ import java.io.{ BufferedReader, FileReader }
import java.util.regex.Pattern
import java.net._
import java.security.SecureRandom
-
-import io.{ File, Path, Socket }
+import io.{ File, Path, Directory, Socket }
import scala.util.control.Exception.catching
+import scala.tools.util.CompileOutputCommon
import scala.tools.util.StringOps.splitWhere
import scala.sys.process._
trait HasCompileSocket {
def compileSocket: CompileSocket
+
+ // This is kind of a suboptimal way to identify error situations.
+ val errorMarkers = Set("error:", "error found", "errors found", "bad option")
+ def isErrorMessage(msg: String) = errorMarkers exists (msg contains _)
+
def compileOnServer(sock: Socket, args: Seq[String]): Boolean = {
var noErrors = true
@@ -28,10 +33,10 @@ trait HasCompileSocket {
def loop(): Boolean = in.readLine() match {
case null => noErrors
case line =>
- if (compileSocket.errorPattern matcher line matches)
+ if (isErrorMessage(line))
noErrors = false
- Console.err println line
+ compileSocket.echo(line)
loop()
}
try loop()
@@ -41,8 +46,9 @@ trait HasCompileSocket {
}
/** This class manages sockets for the fsc offline compiler. */
-class CompileSocket {
+class CompileSocket extends CompileOutputCommon {
protected lazy val compileClient: StandardCompileClient = CompileClient
+ def verbose = compileClient.verbose
/** The prefix of the port identification file, which is followed
* by the port number.
@@ -60,23 +66,8 @@ class CompileSocket {
}
/** The class name of the scala compile server */
- protected val serverClass = "scala.tools.nsc.CompileServer"
-
- /** A regular expression for checking compiler output for errors */
- val errorRegex = ".*(errors? found|don't know|bad option).*"
-
- /** A Pattern object for checking compiler output for errors */
- val errorPattern = Pattern compile errorRegex
-
- protected def fscError(msg: String) = System.err.println(msg)
-
- protected def fatal(msg: String) = {
- fscError(msg)
- sys.error("fsc failure")
- }
-
- protected def info(msg: String) =
- if (compileClient.verbose) System.out.println(msg)
+ protected val serverClass = "scala.tools.nsc.CompileServer"
+ protected def serverClassArgs = if (verbose) List("-v") else Nil // debug
/** A temporary directory to use */
val tmpDir = {
@@ -93,23 +84,17 @@ class CompileSocket {
/* A directory holding port identification files */
val portsDir = (tmpDir / dirName).createDirectory()
- /** Maximum number of polls for an available port */
- private val MaxAttempts = 100
-
- /** Time (in ms) to sleep between two polls */
- private val sleepTime = 20
-
/** The command which starts the compile server, given vm arguments.
*
* @param vmArgs the argument string to be passed to the java or scala command
*/
private def serverCommand(vmArgs: Seq[String]): Seq[String] =
- Seq(vmCommand) ++ vmArgs ++ Seq(serverClass) filterNot (_ == "")
+ Seq(vmCommand) ++ vmArgs ++ Seq(serverClass) ++ serverClassArgs filterNot (_ == "")
/** Start a new server. */
private def startNewServer(vmArgs: String) = {
val cmd = serverCommand(vmArgs split " " toSeq)
- info("[Executing command: %s]" format cmd)
+ info("[Executing command: %s]" format cmd.mkString(" "))
cmd.daemonized().run()
}
@@ -117,18 +102,18 @@ class CompileSocket {
def portFile(port: Int) = portsDir / File(port.toString)
/** Poll for a server port number; return -1 if none exists yet */
- private def pollPort(): Int = portsDir.list match {
- case it if !it.hasNext => -1
- case it =>
- val ret = it.next.name.toInt
- it foreach (_.delete())
- ret
+ private def pollPort(): Int = portsDir.list.toList match {
+ case Nil => -1
+ case x :: xs => try x.name.toInt finally xs foreach (_.delete())
}
/** Get the port number to which a scala compile server is connected;
* If no server is running yet, then create one.
*/
def getPort(vmArgs: String): Int = {
+ val maxPolls = 300
+ val sleepTime = 25
+
var attempts = 0
var port = pollPort()
@@ -136,15 +121,14 @@ class CompileSocket {
info("No compile server running: starting one with args '" + vmArgs + "'")
startNewServer(vmArgs)
}
-
- while (port < 0 && attempts < MaxAttempts) {
+ while (port < 0 && attempts < maxPolls) {
attempts += 1
Thread.sleep(sleepTime)
port = pollPort()
}
info("[Port number: " + port + "]")
if (port < 0)
- fatal("Could not connect to compilation daemon.")
+ fatal("Could not connect to compilation daemon after " + attempts + " attempts.")
port
}
@@ -167,17 +151,17 @@ class CompileSocket {
* cannot be established.
*/
def getOrCreateSocket(vmArgs: String, create: Boolean = true): Option[Socket] = {
- // try for 10 seconds
- val retryDelay = 100
- val maxAttempts = (10 * 1000) / retryDelay
+ val maxMillis = 10 * 1000 // try for 10 seconds
+ val retryDelay = 50
+ val maxAttempts = maxMillis / retryDelay
def getsock(attempts: Int): Option[Socket] = attempts match {
- case 0 => fscError("Unable to establish connection to compilation daemon") ; None
+ case 0 => warn("Unable to establish connection to compilation daemon") ; None
case num =>
val port = if (create) getPort(vmArgs) else pollPort()
if (port < 0) return None
- Socket(InetAddress.getLocalHost(), port).either match {
+ Socket.localhost(port).either match {
case Right(socket) =>
info("[Connected to compilation daemon at port %d]" format port)
Some(socket)
diff --git a/src/compiler/scala/tools/nsc/CompilerCommand.scala b/src/compiler/scala/tools/nsc/CompilerCommand.scala
index 2e3bc32007..1c0fd8b9de 100644
--- a/src/compiler/scala/tools/nsc/CompilerCommand.scala
+++ b/src/compiler/scala/tools/nsc/CompilerCommand.scala
@@ -17,9 +17,11 @@ class CompilerCommand(arguments: List[String], val settings: Settings) {
/** file extensions of files that the compiler can process */
lazy val fileEndings = Properties.fileEndings
- val (ok, files) =
+ private val processArgumentsResult =
if (shouldProcessArguments) processArguments
else (true, Nil)
+ def ok = processArgumentsResult._1
+ def files = processArgumentsResult._2
/** The name of the command */
def cmdName = "scalac"
diff --git a/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala b/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala
index c8e86a752d..68689a4109 100644
--- a/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala
+++ b/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala
@@ -27,8 +27,8 @@ extends CompilerCommand(args, settings) {
/** thingToRun: What to run. If it is None, then the interpreter should be started
* arguments: Arguments to pass to the object or script to run
*/
- val (thingToRun, arguments) = {
- val (_, remaining) = settings.processArguments(args, false)
+ val (_ok, thingToRun, arguments) = {
+ val (ok, remaining) = settings.processArguments(args, false)
val mainClass =
if (settings.jarfile.isDefault) None
else new io.Jar(settings.jarfile.value).mainClass
@@ -37,17 +37,23 @@ extends CompilerCommand(args, settings) {
// Otherwise, the first remaining argument is the program to run, and the rest
// of the arguments go to it. If remaining is empty, we'll start the repl.
mainClass match {
- case Some(name) => (Some(name), remaining)
- case _ => (remaining.headOption, remaining drop 1)
+ case Some(name) => (ok, Some(name), remaining)
+ case _ => (ok, remaining.headOption, remaining drop 1)
}
}
+ override def ok = _ok
- override def usageMsg ="""
+ private def interpolate(s: String) = s.trim.replaceAll("@cmd@", cmdName).replaceAll("@compileCmd@", compCmdName) + "\n"
+
+ def shortUsageMsg = interpolate("""
Usage: @cmd@ <options> [<script|class|object> <arguments>]
or @cmd@ <options> [-jar <jarfile> <arguments>]
+ or @cmd@ -help
-All options to @compileCmd@ are allowed. See @compileCmd@ -help.
+All options to @compileCmd@ are also allowed. See @compileCmd@ -help.
+ """)
+ override def usageMsg = shortUsageMsg + "\n" + interpolate("""
The first given argument other than options to @cmd@ designates
what to run. Runnable targets are:
@@ -74,6 +80,5 @@ A file argument will be run as a scala script unless it contains only top
level classes and objects, and exactly one runnable main method. In that
case the file will be compiled and the main method invoked. This provides
a bridge between scripts and standard scala source.
-
- """.replaceAll("@cmd@", cmdName).replaceAll("@compileCmd@", compCmdName)
+ """) + "\n"
}
diff --git a/src/compiler/scala/tools/nsc/MainGenericRunner.scala b/src/compiler/scala/tools/nsc/MainGenericRunner.scala
index ad7cde1e30..e40fdea3b9 100644
--- a/src/compiler/scala/tools/nsc/MainGenericRunner.scala
+++ b/src/compiler/scala/tools/nsc/MainGenericRunner.scala
@@ -38,7 +38,7 @@ object MainGenericRunner {
import command.settings
def sampleCompiler = new Global(settings) // def so its not created unless needed
- if (!command.ok) return errorFn("%s\n%s".format(command.usageMsg, sampleCompiler.pluginOptionsHelp))
+ if (!command.ok) return errorFn("\n" + command.shortUsageMsg)
else if (settings.version.value) return errorFn("Scala code runner %s -- %s".format(versionString, copyrightString))
else if (command.shouldStopWithInfo) return errorFn(command getInfoMessage sampleCompiler)
diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala
index 5eb6027d0a..07aa62d164 100644
--- a/src/compiler/scala/tools/nsc/ScriptRunner.scala
+++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala
@@ -49,12 +49,6 @@ import util.Exceptional.unwrap
class ScriptRunner extends HasCompileSocket {
lazy val compileSocket = CompileSocket
- /* While I'm chasing down the fsc and script bugs. */
- def DBG(msg: Any) {
- System.err.println(msg.toString)
- System.err.flush()
- }
-
/** Default name to use for the wrapped script */
val defaultScriptMain = "Main"
diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/compiler/scala/tools/nsc/interpreter/Power.scala
index 8ad799a265..6dc8cee219 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Power.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Power.scala
@@ -7,6 +7,7 @@ package scala.tools.nsc
package interpreter
import scala.collection.{ mutable, immutable }
+import scala.util.matching.Regex
import scala.tools.nsc.util.{ BatchSourceFile }
import session.{ History }
@@ -17,29 +18,68 @@ class Power(repl: ILoop, intp: IMain) {
def this(intp: IMain) = this(null, intp)
val global: intp.global.type = intp.global
-
import global._
- import definitions.{ getMember, getModule, getClass => getCompilerClass }
import intp.{ beQuietDuring, interpret, parse }
- object phased extends Phased {
- val global: Power.this.global.type = Power.this.global
- }
-
- class ReplSnippet[T](val path: String, initial: T) {
- var code: String = ""
- var value: T = initial
+ abstract class SymSlurper {
+ def isKeep(sym: Symbol): Boolean
+ def isIgnore(sym: Symbol): Boolean
+ def isRecur(sym: Symbol): Boolean
+ def isFinished(): Boolean
+
+ val keep = mutable.HashSet[Symbol]()
+ val seen = mutable.HashSet[Symbol]()
+ def processed = keep.size + seen.size
+ def discarded = seen.size - keep.size
+
+ def members(x: Symbol): List[Symbol] =
+ if (x.rawInfo.isComplete) x.info.members
+ else Nil
+
+ var lastCount = -1
+ var pass = 0
+ val unseenHistory = new mutable.ListBuffer[Int]
+
+ def loop(todo: Set[Symbol]): Set[Symbol] = {
+ pass += 1
+ val (repeats, unseen) = todo partition seen
+ unseenHistory += unseen.size
+ if (opt.verbose) {
+ println("%3d %s accumulated, %s discarded. This pass: %s unseen, %s repeats".format(
+ pass, keep.size, discarded, unseen.size, repeats.size))
+ }
+ if (lastCount == processed || unseen.isEmpty || isFinished())
+ return keep.toSet
+
+ lastCount = processed
+ keep ++= (unseen filter isKeep filterNot isIgnore)
+ seen ++= unseen
+ loop(unseen filter isRecur flatMap members)
+ }
- def set(code: String) = interpret(path + ".value = " + code)
- def get: T = value
- override def toString = "intp." + path + ".value = \"" + code + "\""
+ def apply(sym: Symbol): Set[Symbol] = {
+ keep.clear()
+ seen.clear()
+ loop(Set(sym))
+ }
}
- object vars {
- private def create[T](name: String, initial: T): ReplSnippet[T] =
- new ReplSnippet[T]("power.vars." + name, initial)
+ class PackageSlurper(pkgName: String) extends SymSlurper {
+ val pkgSymbol = getCompilerModule(pkgName)
+ val modClass = pkgSymbol.moduleClass
+
+ /** Looking for dwindling returns */
+ def droppedEnough() = unseenHistory.size >= 4 && (
+ unseenHistory.takeRight(4).sliding(2) map (_.toList) forall {
+ case List(a, b) => a > b
+ }
+ )
- val symfilter = create("symfilter", (s: Symbol) => true)
+ def isRecur(sym: Symbol) = true
+ def isIgnore(sym: Symbol) = sym.isAnonOrRefinementClass || (sym.name.toString contains "$mc")
+ def isKeep(sym: Symbol) = sym.hasTransOwner(modClass)
+ def isFinished() = droppedEnough()
+ def slurp() = apply(modClass)
}
def banner = """
@@ -56,7 +96,8 @@ class Power(repl: ILoop, intp: IMain) {
|val global: intp.global.type = intp.global
|import global._
|import definitions._
- |import power.{ phased, show, clazz, module }
+ |import power.phased
+ |import power.Implicits._
""".stripMargin
/** Starts up power mode and runs whatever is in init.
@@ -74,62 +115,94 @@ class Power(repl: ILoop, intp: IMain) {
init split '\n' foreach interpret
}
- object show {
- private def defStrings(sym: Symbol, p: Symbol => Boolean) =
- phased(sym.info.members filter p map (_.defString))
-
- private def display(sym: Symbol, p: Symbol => Boolean) =
- defStrings(sym, p) foreach println
-
- def methods[T: Manifest] = display(clazz[T], _.isMethod)
- def apply[T: Manifest] = display(clazz[T], vars.symfilter.get)
- }
-
- abstract class NameBased[T <: Name] {
- def mkName(s: String): T
- def mkSymbol(s: String): Symbol
-
- def apply[T: Manifest] = mkSymbol(manifest[T].erasure.getName)
- def tpe[T: Manifest] = apply[T].tpe
- def members[T: Manifest] = tpe[T].members
- def member[T: Manifest](name: Name) = getMember(apply[T], name)
- def vmember[T: Manifest](name: String) = member[T](newTermName(name))
- def tmember[T: Manifest](name: String) = member[T](newTypeName(name))
- }
private def missingWrap(op: => Symbol): Symbol =
try op
catch { case _: MissingRequirementError => NoSymbol }
- object clazz extends NameBased[TypeName] {
- def mkName(s: String) = newTypeName(s)
- def mkSymbol(s: String): Symbol = missingWrap(getCompilerClass(s))
+ private def getCompilerClass(name: String) = missingWrap(definitions.getClass(name))
+ private def getCompilerModule(name: String) = missingWrap(definitions.getModule(name))
+
+ object InternalInfo {
+ implicit def apply[T: Manifest] : InternalInfo[T] = new InternalInfo[T](None)
}
- object module extends NameBased[TermName] {
- def mkName(s: String) = newTermName(s)
- def mkSymbol(s: String): Symbol = missingWrap(getModule(s))
+ /** Todo: translate manifest type arguments into applied types. */
+ class InternalInfo[T: Manifest](value: Option[T] = None) {
+ def companion = symbol.companionSymbol
+ def info = symbol.info
+ def module = symbol.moduleClass
+ def owner = symbol.owner
+ def symDef = symbol.defString
+ def symName = symbol.name
+ def tpe = symbol.tpe
+
+ def declares = members filter (_.owner == symbol)
+ def inherits = members filterNot (_.owner == symbol)
+ def types = members filter (_.name.isTypeName)
+ def methods = members filter (_.isMethod)
+ def overrides = declares filter (_.isOverride)
+
+ def erasure = manifest[T].erasure
+ def symbol = getCompilerClass(erasure.getName)
+ def members = tpe.members
+ def bts = info.baseTypeSeq.toList
+ def btsmap = bts map (x => (x, x.decls.toList)) toMap
+ def pkgName = erasure.getPackage.getName
+ def pkg = getCompilerModule(pkgName)
+ def pkgmates = pkg.tpe.members
+ def pkgslurp = new PackageSlurper(pkgName) slurp()
+
+ def ? = this
+
+ def whoHas(name: String) = bts filter (_.decls.toList exists (_.name.toString == name))
+ def <:<[U: Manifest](other: U) = tpe <:< InternalInfo[U].tpe
+ def lub[U: Manifest](other: U) = global.lub(List(tpe, InternalInfo[U].tpe))
+ def glb[U: Manifest](other: U) = global.glb(List(tpe, InternalInfo[U].tpe))
+
+ def shortClass = erasure.getName split "[$.]" last
+ override def toString = value match {
+ case Some(x) => "%s (%s)".format(x, shortClass)
+ case _ => erasure.getName
+ }
}
- def mkContext(code: String = "") = analyzer.rootContext(mkUnit(code))
- def mkAlias(name: String, what: String) = interpret("type %s = %s".format(name, what))
- def mkSourceFile(code: String) = new BatchSourceFile("<console>", code)
- def mkUnit(code: String) = new CompilationUnit(mkSourceFile(code))
-
- def mkTree(code: String): Tree = mkTrees(code).headOption getOrElse EmptyTree
- def mkTrees(code: String): List[Tree] = parse(code) getOrElse Nil
- def mkTypedTrees(code: String*): List[Tree] = {
- class TyperRun extends Run {
- override def stopPhase(name: String) = name == "superaccessors"
+ trait PCFormatter extends (Any => List[String]) {
+ def apply(x: Any): List[String]
+ def show(x: Any): Unit = grep(x, _ => true)
+ def grep(x: Any, p: String => Boolean): Unit = apply(x) filter p foreach println
+ }
+ class PrintingConvenience[T](value: T)(implicit fmt: PCFormatter) {
+ def > : Unit = >(_ => true)
+ def >(s: String): Unit = >(_ contains s)
+ def >(r: Regex): Unit = >(_ matches r.pattern.toString)
+ def >(p: String => Boolean): Unit = fmt.grep(value, p)
+ }
+ object Implicits {
+ implicit lazy val powerNameOrdering: Ordering[Name] = Ordering[String] on (_.toString)
+ implicit object powerSymbolOrdering extends Ordering[Symbol] {
+ def compare(s1: Symbol, s2: Symbol) =
+ if (s1 eq s2) 0
+ else if (s1 isLess s2) -1
+ else 1
+ }
+ implicit def replPrinting[T](x: T)(implicit fmt: PCFormatter) = new PrintingConvenience[T](x)
+ implicit def replInternalInfo[T: Manifest](x: T): InternalInfo[T] = new InternalInfo[T](Some(x))
+ implicit object ReplDefaultFormatter extends PCFormatter {
+ def apply(x: Any): List[String] = x match {
+ case Tuple2(k, v) => apply(k) + " -> " + apply(v)
+ case xs: Traversable[_] => (xs.toList flatMap apply).sorted.distinct
+ case x => List("" + x)
+ }
}
+ }
- reporter.reset()
- val run = new TyperRun
- run compileSources (code.toList.zipWithIndex map {
- case (s, i) => new BatchSourceFile("<console %d>".format(i), s)
- })
- run.units.toList map (_.body)
+ object phased extends Phased {
+ val global: Power.this.global.type = Power.this.global
}
- def mkTypedTree(code: String) = mkTypedTrees(code).head
- def mkType(id: String): Type = intp.typeOfExpression(id) getOrElse NoType
+ def context(code: String) = analyzer.rootContext(unit(code))
+ def source(code: String) = new BatchSourceFile("<console>", code)
+ def unit(code: String) = new CompilationUnit(source(code))
+ def trees(code: String): List[Tree] = parse(code) getOrElse Nil
+ def typeOf(id: String): Type = intp.typeOfExpression(id) getOrElse NoType
override def toString = """
|** Power mode status **
diff --git a/src/compiler/scala/tools/nsc/io/Socket.scala b/src/compiler/scala/tools/nsc/io/Socket.scala
index 0be7de3873..b7920921fa 100644
--- a/src/compiler/scala/tools/nsc/io/Socket.scala
+++ b/src/compiler/scala/tools/nsc/io/Socket.scala
@@ -6,36 +6,56 @@
package scala.tools.nsc
package io
-import java.io.{ IOException, InputStreamReader, BufferedReader, PrintWriter }
-import java.net.{ InetAddress, Socket => JSocket }
-import scala.util.control.Exception._
+import java.io.{ IOException, InputStreamReader, BufferedReader, PrintWriter, Closeable }
+import java.io.{ BufferedOutputStream, BufferedReader }
+import java.net.{ ServerSocket, SocketException, SocketTimeoutException, InetAddress, Socket => JSocket }
+import scala.sys.SystemProperties._
+import scala.io.Codec
/** A skeletal only-as-much-as-I-need Socket wrapper.
*/
-object Socket
-{
- private val socketExceptions = List(classOf[IOException], classOf[SecurityException])
+object Socket {
+ def preferringIPv4[T](body: => T): T = exclusively {
+ val saved = preferIPv4Stack.value
+ try { preferIPv4Stack.enable() ; body }
+ finally preferIPv4Stack setValue saved
+ }
+
+ class Box[+T](f: () => T) {
+ private def handlerFn[U](f: Throwable => U): PartialFunction[Throwable, U] = {
+ case x @ (_: IOException | _: SecurityException) => f(x)
+ }
+ private val optHandler = handlerFn[Option[T]](_ => None)
+ private val eitherHandler = handlerFn[Either[Throwable, T]](x => Left(x))
- class SocketBox(f: () => Socket) {
- def either: Either[Throwable, Socket] = catching(socketExceptions: _*) either f()
- def opt: Option[Socket] = catching(socketExceptions: _*) opt f()
+ def getOrElse[T1 >: T](alt: T1): T1 = opt getOrElse alt
+ def either: Either[Throwable, T] = try Right(f()) catch eitherHandler
+ def opt: Option[T] = try Some(f()) catch optHandler
}
- def apply(host: InetAddress, port: Int) = new SocketBox(() => new Socket(new JSocket(host, port)))
- def apply(host: String, port: Int) = new SocketBox(() => new Socket(new JSocket(host, port)))
+ def newIPv4Server(port: Int = 0) = new Box(() => preferringIPv4(new ServerSocket(0)))
+ def newServer(port: Int = 0) = new Box(() => new ServerSocket(0))
+ def localhost(port: Int) = apply(InetAddress.getLocalHost(), port)
+ def apply(host: InetAddress, port: Int) = new Box(() => new Socket(new JSocket(host, port)))
+ def apply(host: String, port: Int) = new Box(() => new Socket(new JSocket(host, port)))
}
-class Socket(jsocket: JSocket) {
- def getOutputStream() = jsocket.getOutputStream()
- def getInputStream() = jsocket.getInputStream()
- def getPort() = jsocket.getPort()
- def close() = jsocket.close()
+class Socket(jsocket: JSocket) extends Streamable.Bytes with Closeable {
+ def inputStream() = jsocket.getInputStream()
+ def outputStream() = jsocket.getOutputStream()
+ def getPort() = jsocket.getPort()
+ def close() = jsocket.close()
+
+ def printWriter() = new PrintWriter(outputStream(), true)
+ def bufferedReader(implicit codec: Codec) = new BufferedReader(new InputStreamReader(inputStream()))
+ def bufferedOutput(size: Int) = new BufferedOutputStream(outputStream(), size)
/** Creates an InputStream and applies the closure, automatically closing it on completion.
*/
def applyReaderAndWriter[T](f: (BufferedReader, PrintWriter) => T): T = {
- val out = new PrintWriter(getOutputStream(), true)
- val in = new BufferedReader(new InputStreamReader(getInputStream()))
+ val out = printWriter()
+ val in = bufferedReader
+
try f(in, out)
finally {
in.close()
diff --git a/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala
index 80183791ed..6f130b9e74 100644
--- a/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala
@@ -16,7 +16,7 @@ trait AbsScalaSettings {
type PathSetting <: AbsSetting { type T = String }
type PhasesSetting <: AbsSetting { type T = List[String] }
type StringSetting <: AbsSetting { type T = String }
- type MapSetting <: AbsSetting { type T = Map[String, String] }
+ type PrefixSetting <: AbsSetting { type T = List[String] }
type OutputDirs
type OutputSetting <: AbsSetting
@@ -29,7 +29,7 @@ trait AbsScalaSettings {
def PathSetting(name: String, descr: String, default: String): PathSetting
def PhasesSetting(name: String, descr: String): PhasesSetting
def StringSetting(name: String, helpArg: String, descr: String, default: String): StringSetting
- def MapSetting(name: String, prefix: String, descr: String): MapSetting
+ def PrefixSetting(name: String, prefix: String, descr: String): PrefixSetting
/** **/
abstract class SettingGroup(val prefix: String) extends AbsSetting {
diff --git a/src/compiler/scala/tools/nsc/settings/FscSettings.scala b/src/compiler/scala/tools/nsc/settings/FscSettings.scala
index b7f0c553f6..a219148b16 100644
--- a/src/compiler/scala/tools/nsc/settings/FscSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/FscSettings.scala
@@ -14,16 +14,22 @@ class FscSettings(error: String => Unit) extends Settings(error) {
def this() = this(Console.println)
- val reset = BooleanSetting("-reset", "Reset compile server caches")
- val shutdown = BooleanSetting("-shutdown", "Shutdown compile server")
- val server = StringSetting ("-server", "hostname:portnumber", "Specify compile server socket", "")
+ val reset = BooleanSetting("-reset", "Reset compile server caches")
+ val shutdown = BooleanSetting("-shutdown", "Shutdown compile server")
+ val server = StringSetting ("-server", "hostname:portnumber", "Specify compile server socket", "")
+ val preferIPv4 = BooleanSetting("-ipv4", "Use IPv4 rather than IPv6 for the server socket")
+ val absClasspath = BooleanSetting("-absolute-cp", "Make classpath elements absolute paths before sending to server") .
+ withPostSetHook (_ => absolutizeClasspath())
+ val idleMins = IntSetting ("-max-idle", "Set idle timeout in minutes for fsc (use 0 for no timeout)",
+ 30, Some(0, Int.MaxValue), (_: String) => None)
disable(prompt)
disable(resident)
- // Make all paths absolute since we may be going from client to server
- userSetSettings foreach {
- case x: PathSetting => x.value = ClassPath.makeAbsolute(x.value)
- case _ => ()
+ // Make the classpath absolute: for going from client to server.
+ private def absolutizeClasspath() {
+ userSetSettings collect {
+ case x: PathSetting => x.value = ClassPath.makeAbsolute(x.value)
+ }
}
}
diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
index f67a9a84dc..6a357cc08a 100644
--- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
@@ -80,6 +80,11 @@ class MutableSettings(val errorFn: String => Unit) extends AbsSettings with Scal
*/
lazy val outputDirs = new OutputDirs
+ /** A list of settings which act based on prefix rather than an exact
+ * match. This is basically -D and -J.
+ */
+ lazy val prefixSettings = allSettings collect { case x: PrefixSetting => x }
+
/** Split the given line into parameters.
*/
def splitParams(line: String) = cmd.Parser.tokenize(line, errorFn)
@@ -124,12 +129,18 @@ class MutableSettings(val errorFn: String => Unit) extends AbsSettings with Scal
}
else {
// we dispatch differently based on the appearance of p:
- // 1) If it has a : it is presumed to be -Xfoo:bar,baz
- // 2) Otherwise, the whole string should be a command name
+ // 1) If it matches a prefix setting it is sent there directly.
+ // 2) If it has a : it is presumed to be -Xfoo:bar,baz
+ // 3) Otherwise, the whole string should be a command name
//
// Internally we use Option[List[String]] to discover error,
// but the outside expects our arguments back unchanged on failure
- if (arg contains ":") parseColonArg(arg) match {
+ val prefix = prefixSettings find (_ respondsTo arg)
+ if (prefix.isDefined) {
+ prefix.get tryToSet args
+ rest
+ }
+ else if (arg contains ":") parseColonArg(arg) match {
case Some(_) => rest
case None => args
}
@@ -188,7 +199,7 @@ class MutableSettings(val errorFn: String => Unit) extends AbsSettings with Scal
add(new PathSetting(name, descr, default, prepend, append))
}
- def MapSetting(name: String, prefix: String, descr: String): MapSetting = add(new MapSetting(name, prefix, descr))
+ def PrefixSetting(name: String, prefix: String, descr: String): PrefixSetting = add(new PrefixSetting(name, prefix, descr))
// basically this is a value which remembers if it's been modified
trait SettingValue extends AbsSettingValue {
@@ -410,31 +421,23 @@ class MutableSettings(val errorFn: String => Unit) extends AbsSettings with Scal
}
/** A special setting for accumulating arguments like -Dfoo=bar. */
- class MapSetting private[nsc](
+ class PrefixSetting private[nsc](
name: String,
prefix: String,
descr: String)
extends Setting(name, descr) {
- type T = Map[String, String]
- protected var v: Map[String, String] = Map()
-
- def tryToSet(args: List[String]) = {
- val (xs, rest) = args partition (_ startsWith prefix)
- val pairs = xs map (_ stripPrefix prefix) map { x =>
- (x indexOf '=') match {
- case -1 => (x, "")
- case idx => (x take idx, x drop (idx + 1))
- }
- }
- v = v ++ pairs
- Some(rest)
- }
+ type T = List[String]
+ protected var v: List[String] = Nil
- override def respondsTo(label: String) = label startsWith prefix
- def unparse: List[String] = v.toList map {
- case (k, "") => prefix + k
- case (k, v) => prefix + k + "=" + v
+ def tryToSet(args: List[String]) = args match {
+ case x :: xs if x startsWith prefix =>
+ v = v :+ x
+ Some(xs)
+ case _ =>
+ None
}
+ override def respondsTo(token: String) = token startsWith prefix
+ def unparse: List[String] = value
}
/** A setting represented by a string, (`default' unless set) */
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 16289f11d9..1670dfb94a 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -23,8 +23,8 @@ trait ScalaSettings extends AbsScalaSettings with StandardScalaSettings {
/** Disable a setting */
def disable(s: Setting) = allSettings -= s
- val jvmargs = MapSetting("-J<flag>", "-J", "Pass <flag> directly to the runtime system.")
- val defines = MapSetting("-Dproperty=value", "-D", "Pass -Dproperty=value directly to the runtime system.")
+ val jvmargs = PrefixSetting("-J<flag>", "-J", "Pass <flag> directly to the runtime system.")
+ val defines = PrefixSetting("-Dproperty=value", "-D", "Pass -Dproperty=value directly to the runtime system.")
val toolcp = PathSetting("-toolcp", "Add to the runner classpath.", "")
val nobootcp = BooleanSetting("-nobootcp", "Do not use the boot classpath for the scala jars.")
diff --git a/src/compiler/scala/tools/util/SocketServer.scala b/src/compiler/scala/tools/util/SocketServer.scala
index 0094333402..fba3d4ce48 100644
--- a/src/compiler/scala/tools/util/SocketServer.scala
+++ b/src/compiler/scala/tools/util/SocketServer.scala
@@ -6,100 +6,95 @@
** |/ **
\* */
-
package scala.tools.util
-import java.io.{ PrintWriter, BufferedOutputStream, BufferedReader, InputStreamReader, IOException }
-import java.net.{ Socket, ServerSocket, SocketException, SocketTimeoutException }
+import java.net.{ ServerSocket, SocketException, SocketTimeoutException }
+import java.io.{ PrintWriter, BufferedReader }
+import scala.tools.nsc.io.Socket
-object SocketServer {
- val BufferSize = 10240
+trait CompileOutputCommon {
+ def verbose: Boolean
- def bufferedReader(s: Socket) = new BufferedReader(new InputStreamReader(s.getInputStream()))
- def bufferedOutput(s: Socket) = new BufferedOutputStream(s.getOutputStream, BufferSize)
+ def info(msg: String) = if (verbose) echo(msg)
+ def echo(msg: String) = Console println msg
+ def warn(msg: String) = System.err println msg
+ def fatal(msg: String) = { warn(msg) ; sys.exit(1) }
}
-import SocketServer._
-/** The abstract class <code>SocketServer</code> implements the server
+/** The abstract class SocketServer implements the server
* communication for the fast Scala compiler.
*
* @author Martin Odersky
* @version 1.0
*/
-abstract class SocketServer {
- // After some number of idle minutes, politely exit.
- // Should the port file disappear, and the clients
- // therefore unable to contact this server instance,
- // the process will just eventually terminate by itself.
- def fscIdleMinutes = {
- sys.props("scala.config.fsc.idle-minutes") match {
- case null => 30
- case str => try str.toInt catch { case _: Exception => 30 }
- }
- }
- def fscIdleMillis = fscIdleMinutes * 60 * 1000
-
+abstract class SocketServer extends CompileOutputCommon {
def shutdown: Boolean
def session(): Unit
+ def timeout(): Unit = () // called after a timeout is detected for subclasses to cleanup
+ // a hook for subclasses
+ protected def createServerSocket(): ServerSocket = new ServerSocket(0)
- var out: PrintWriter = _
var in: BufferedReader = _
-
- def fatal(msg: String): Nothing = {
- System.err.println(msg)
- sys.exit(1)
- }
-
- private def warn(msg: String) {
- System.err.println(msg)
+ var out: PrintWriter = _
+ val BufferSize = 10240
+ lazy val serverSocket = createServerSocket()
+ lazy val port = serverSocket.getLocalPort()
+
+ // Default to 30 minute idle timeout, settable with -max-idle
+ protected var idleMinutes = 30
+ private var savedTimeout = 0
+ private val acceptBox = new Socket.Box(() => {
+ // update the timeout if it has changed
+ if (savedTimeout != idleMinutes) {
+ savedTimeout = idleMinutes
+ setTimeoutOnSocket(savedTimeout)
+ }
+ new Socket(serverSocket.accept())
+ })
+ private def setTimeoutOnSocket(mins: Int) = {
+ try {
+ serverSocket setSoTimeout (mins * 60 * 1000)
+ info("Set socket timeout to " + mins + " minutes.")
+ true
+ }
+ catch {
+ case ex: SocketException =>
+ warn("Failed to set socket timeout: " + ex)
+ false
+ }
}
- // called after a timeout is detected,
- // for SocketServer subclasses to perform
- // some cleanup, if any
- def timeout() {}
-
- val serverSocket =
- try new ServerSocket(0)
- catch { case e: IOException => fatal("Could not listen on any port; exiting.") }
-
- val port: Int = serverSocket.getLocalPort()
-
- // @todo: this is going to be a prime candidate for ARM
def doSession(clientSocket: Socket) = {
- out = new PrintWriter(clientSocket.getOutputStream(), true)
- in = bufferedReader(clientSocket)
- val bufout = bufferedOutput(clientSocket)
+ clientSocket.applyReaderAndWriter { (in, out) =>
+ this.in = in
+ this.out = out
+ val bufout = clientSocket.bufferedOutput(BufferSize)
- try scala.Console.withOut(bufout)(session())
- finally {
- bufout.close()
- out.close()
- in.close()
+ try scala.Console.withOut(bufout)(session())
+ finally bufout.close()
}
}
def run() {
- def fail(s: String) = fatal(s format port)
- Console.println("Setting timeout to " + fscIdleMillis)
- try serverSocket setSoTimeout fscIdleMillis catch {
- case e: SocketException => fatal("Could not set timeout on server socket; exiting.")
- }
-
- try {
- while (!shutdown) {
- val clientSocket = try serverSocket.accept() catch {
- case e: IOException => fail("Accept on port %d failed; exiting.")
- }
- try doSession(clientSocket)
- finally clientSocket.close()
+ info("Starting SocketServer run() loop.")
+
+ def loop() {
+ acceptBox.either match {
+ case Right(clientSocket) =>
+ try doSession(clientSocket)
+ finally clientSocket.close()
+ case Left(_: SocketTimeoutException) =>
+ warn("Idle timeout exceeded on port %d; exiting" format port)
+ timeout()
+ return
+ case _ =>
+ warn("Accept on port %d failed")
}
+ if (!shutdown)
+ loop()
}
- catch {
- case e: SocketTimeoutException =>
- warn("Timeout elapsed with no requests from clients on port %d; exiting" format port)
- timeout()
- }
+ try loop()
+ catch { case ex: SocketException => fatal("Compile server caught fatal exception: " + ex) }
finally serverSocket.close()
}
}
diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala
index 4e349cb423..d8a3514954 100644
--- a/src/library/scala/collection/Iterator.scala
+++ b/src/library/scala/collection/Iterator.scala
@@ -12,6 +12,7 @@ package scala.collection
import mutable.ArrayBuffer
import annotation.{ tailrec, migration }
+import parallel.ParIterable
/** The `Iterator` object provides various functions for
* creating specialized iterators.
@@ -250,7 +251,7 @@ import Iterator.empty
* @define mayNotTerminateInf
* Note: may not terminate for infinite iterators.
*/
-trait Iterator[+A] extends TraversableOnce[A] {
+trait Iterator[+A] extends TraversableOnce[A] with Parallelizable[A, ParIterable[A]] {
self =>
/** Tests whether this iterator can provide another element.
@@ -275,6 +276,8 @@ trait Iterator[+A] extends TraversableOnce[A] {
*/
def isTraversableAgain = false
+ protected[this] def parCombiner = ParIterable.newCombiner[A]
+
/** Tests whether this Iterator has a known size.
*
* @return `true` for empty Iterators, `false` otherwise.
diff --git a/src/library/scala/collection/MapLike.scala b/src/library/scala/collection/MapLike.scala
index 6fb971d128..fd58540086 100644
--- a/src/library/scala/collection/MapLike.scala
+++ b/src/library/scala/collection/MapLike.scala
@@ -12,6 +12,7 @@ package scala.collection
import generic._
import mutable.{ Builder, MapBuilder }
import annotation.migration
+import parallel.ParMap
/** A template trait for maps, which associate keys with values.
*
@@ -56,7 +57,8 @@ import annotation.migration
trait MapLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]]
extends PartialFunction[A, B]
with IterableLike[(A, B), This]
- with Subtractable[A, This] {
+ with Subtractable[A, This]
+ with Parallelizable[(A, B), ParMap[A, B]] {
self =>
/** The empty map of the same type as this map
@@ -311,6 +313,8 @@ self =>
result
}
+ protected[this] override def parCombiner = ParMap.newCombiner[A, B]
+
/** Appends all bindings of this map to a string builder using start, end, and separator strings.
* The written text begins with the string `start` and ends with the string
* `end`. Inside, the string representations of all bindings of this map
diff --git a/src/library/scala/collection/Parallelizable.scala b/src/library/scala/collection/Parallelizable.scala
index 999849fbab..207bb25cb6 100644
--- a/src/library/scala/collection/Parallelizable.scala
+++ b/src/library/scala/collection/Parallelizable.scala
@@ -1,8 +1,18 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+
package scala.collection
import parallel.ParIterableLike
+import parallel.Combiner
@@ -10,19 +20,50 @@ import parallel.ParIterableLike
* by invoking the method `par`. Parallelizable collections may be parametrized with
* a target type different than their own.
*
+ * @tparam A the type of the elements in the collection
* @tparam ParRepr the actual type of the collection, which has to be parallel
*/
-trait Parallelizable[+ParRepr <: Parallel] {
-
- /** Returns a parallel implementation of a collection.
+trait Parallelizable[+A, +ParRepr <: Parallel] {
+self: TraversableOnce[A] =>
+
+ /** Returns a parallel implementation of this collection.
+ *
+ * For most collection types, this method creates a new parallel collection by copying
+ * all the elements. For these collection, `par` takes linear time. Mutable collections
+ * in this category do not produce a mutable parallel collection that has the same
+ * underlying dataset, so changes in one collection will not be reflected in the other one.
+ *
+ * Specific collections (e.g. `ParArray` or `mutable.ParHashMap`) override this default
+ * behaviour by creating a parallel collection which shares the same underlying dataset.
+ * For these collections, `par` takes constant or sublinear time.
+ *
+ * All parallel collections return a reference to themselves.
+ *
+ * @return a parallel implementation of this collection
*/
- def par: ParRepr
+ def par: ParRepr = {
+ val cb = parCombiner
+ for (x <- this) cb += x
+ cb.result
+ }
+
+ /** The default `par` implementation uses the combiner provided by this method
+ * to create a new parallel collection.
+ *
+ * @return a combiner for the parallel collection of type `ParRepr`
+ */
+ protected[this] def parCombiner: Combiner[A, ParRepr]
}
+trait CustomParallelizable[+A, +ParRepr <: Parallel] extends Parallelizable[A, ParRepr] {
+self: TraversableOnce[A] =>
+ override def par: ParRepr
+ protected override def parCombiner = throw new UnsupportedOperationException("")
+}
diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala
index 12e4c45c75..4936e652b2 100644
--- a/src/library/scala/collection/SeqLike.scala
+++ b/src/library/scala/collection/SeqLike.scala
@@ -13,6 +13,7 @@ package scala.collection
import mutable.{ListBuffer, HashMap, ArraySeq}
import immutable.{List, Range}
import generic._
+import parallel.ParSeq
/** The companion object for trait `SeqLike`.
*/
@@ -168,7 +169,7 @@ object SeqLike {
*
* Note: will not terminate for infinite-sized collections.
*/
-trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
+trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] with Parallelizable[A, ParSeq[A]] { self =>
override protected[this] def thisCollection: Seq[A] = this.asInstanceOf[Seq[A]]
override protected[this] def toCollection(repr: Repr): Seq[A] = repr.asInstanceOf[Seq[A]]
@@ -191,6 +192,8 @@ trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
*/
def apply(idx: Int): A
+ protected[this] override def parCombiner = ParSeq.newCombiner[A]
+
/** Compares the length of this $coll to a test value.
*
* @param len the test value that gets compared with the length.
diff --git a/src/library/scala/collection/SetLike.scala b/src/library/scala/collection/SetLike.scala
index 73f0b9c839..7cbb8ee2ef 100644
--- a/src/library/scala/collection/SetLike.scala
+++ b/src/library/scala/collection/SetLike.scala
@@ -12,6 +12,7 @@ package scala.collection
import generic._
import mutable.{ Builder, SetBuilder }
import scala.annotation.migration
+import parallel.ParSet
/** A template trait for sets.
*
@@ -57,7 +58,8 @@ import scala.annotation.migration
*/
trait SetLike[A, +This <: SetLike[A, This] with Set[A]]
extends IterableLike[A, This]
- with Subtractable[A, This] {
+ with Subtractable[A, This]
+ with Parallelizable[A, ParSet[A]] {
self =>
/** The empty set of the same type as this set
@@ -72,6 +74,8 @@ self =>
*/
override protected[this] def newBuilder: Builder[A, This] = new SetBuilder[A, This](empty)
+ protected[this] override def parCombiner = ParSet.newCombiner[A]
+
/** Overridden for efficiency. */
override def toSeq: Seq[A] = toBuffer[A]
override def toBuffer[A1 >: A]: mutable.Buffer[A1] = {
diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala
index 9cf73142e6..70d5c37837 100644
--- a/src/library/scala/collection/TraversableLike.scala
+++ b/src/library/scala/collection/TraversableLike.scala
@@ -15,6 +15,7 @@ import mutable.{ Builder, ListBuffer }
import annotation.tailrec
import annotation.migration
import annotation.unchecked.{ uncheckedVariance => uV }
+import parallel.ParIterable
/** A template trait for traversable collections of type `Traversable[A]`.
@@ -90,7 +91,8 @@ import annotation.unchecked.{ uncheckedVariance => uV }
*/
trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
with FilterMonadic[A, Repr]
- with TraversableOnce[A] {
+ with TraversableOnce[A]
+ with Parallelizable[A, ParIterable[A]] {
self =>
import Traversable.breaks._
@@ -119,6 +121,8 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
*/
protected[this] def newBuilder: Builder[A, Repr]
+ protected[this] def parCombiner = ParIterable.newCombiner[A]
+
/** Applies a function `f` to all elements of this $coll.
*
* Note: this method underlies the implementation of most other bulk operations.
diff --git a/src/library/scala/collection/TraversableOnce.scala b/src/library/scala/collection/TraversableOnce.scala
index 5b8abb3e5e..de3b4770f3 100644
--- a/src/library/scala/collection/TraversableOnce.scala
+++ b/src/library/scala/collection/TraversableOnce.scala
@@ -501,66 +501,6 @@ trait TraversableOnce[+A] {
b.result
}
- /* The following 4 methods are implemented in a generic way here,
- * but are specialized further down the hierarchy where possible.
- * In particular:
- *
- * - all concrete sequential collection classes that can be
- * parallelized have their corresponding `toPar*` methods
- * overridden (e.g. ArrayBuffer overrides `toParIterable`
- * and `toParSeq`)
- * - ParIterableLike overrides all 4 methods
- * - ParSeqLike again overrides `toParSeq`
- * - ParSetLike again overrides `toParSet`
- * - ParMapLike again overrides `toParMap`
- * - immutable.ParIterable overrides all 4 methods to have immutable return types
- * - immutable.ParSet overrides `toParSet` to `this`
- * - immutable.ParSeq overrides nothing yet TODO vector
- * - immutable.ParMap overrides `toParMap` to `this`
- */
-
- /** Converts this $coll to a parallel iterable.
- * $willNotTerminateInf
- * @return a parallel iterable containing all elements of this $coll.
- */
- def toParIterable: parallel.ParIterable[A] = toParSeq
-
- /** Converts this $coll to a parallel sequence.
- * $willNotTerminateInf
- * @return a parallel sequence containing all elements of this $coll.
- */
- def toParSeq: parallel.ParSeq[A] = {
- val cb = parallel.mutable.ParArray.newCombiner[A]
- for (elem <- this) cb += elem
- cb.result
- }
-
- /** Converts this $coll to a parallel set.
- * $willNotTerminateInf
- * @return a parallel set containing all elements of this $coll.
- */
- def toParSet[B >: A]: parallel.ParSet[B] = {
- val cb = parallel.mutable.ParHashSet.newCombiner[B]
- for (elem <- this) cb += elem
- cb.result
- }
-
- /** Converts this $coll to a parallel map.
- * $willNotTerminateInf
- *
- * This operation is only available on collections containing pairs of elements.
- *
- * @return a parallel map containing all elements of this $coll.
- * @usecase def toParMap[T, U]: ParMap[T, U]
- * @return a parallel map of type `parallel.ParMap[T, U]`
- * containing all key/value pairs of type `(T, U)` of this $coll.
- */
- def toParMap[T, U](implicit ev: A <:< (T, U)): parallel.ParMap[T, U] = {
- val cb = parallel.mutable.ParHashMap.newCombiner[T, U]
- for (elem <- this) cb += elem
- cb.result
- }
-
/** Displays all elements of this $coll in a string using start, end, and
* separator strings.
*
diff --git a/src/library/scala/collection/immutable/HashMap.scala b/src/library/scala/collection/immutable/HashMap.scala
index d44791c2eb..cf7b0d423a 100644
--- a/src/library/scala/collection/immutable/HashMap.scala
+++ b/src/library/scala/collection/immutable/HashMap.scala
@@ -33,7 +33,7 @@ import parallel.immutable.ParHashMap
* @define willNotTerminateInf
*/
@SerialVersionUID(2L)
-class HashMap[A, +B] extends Map[A,B] with MapLike[A, B, HashMap[A, B]] with Parallelizable[ParHashMap[A, B]] with Serializable {
+class HashMap[A, +B] extends Map[A,B] with MapLike[A, B, HashMap[A, B]] with CustomParallelizable[(A, B), ParHashMap[A, B]] with Serializable {
override def size: Int = 0
@@ -87,12 +87,8 @@ class HashMap[A, +B] extends Map[A,B] with MapLike[A, B, HashMap[A, B]] with Par
protected def merge0[B1 >: B](that: HashMap[A, B1], level: Int, merger: Merger[B1]): HashMap[A, B1] = that
- def par = ParHashMap.fromTrie(this)
+ override def par = ParHashMap.fromTrie(this)
- override def toParIterable = par
-
- private type C = (A, B)
- override def toParMap[D, E](implicit ev: C <:< (D, E)) = par.asInstanceOf[ParHashMap[D, E]]
}
/** $factoryInfo
diff --git a/src/library/scala/collection/immutable/HashSet.scala b/src/library/scala/collection/immutable/HashSet.scala
index 7d31f20e14..951f6d235e 100644
--- a/src/library/scala/collection/immutable/HashSet.scala
+++ b/src/library/scala/collection/immutable/HashSet.scala
@@ -32,13 +32,15 @@ import collection.parallel.immutable.ParHashSet
class HashSet[A] extends Set[A]
with GenericSetTemplate[A, HashSet]
with SetLike[A, HashSet[A]]
- with Parallelizable[ParHashSet[A]]
+ with CustomParallelizable[A, ParHashSet[A]]
with Serializable
{
override def companion: GenericCompanion[HashSet] = HashSet
//class HashSet[A] extends Set[A] with SetLike[A, HashSet[A]] {
+ override def par = ParHashSet.fromTrie(this)
+
override def size: Int = 0
override def empty = HashSet.empty[A]
@@ -58,8 +60,6 @@ class HashSet[A] extends Set[A]
def - (e: A): HashSet[A] =
removed0(e, computeHash(e), 0)
- def par = ParHashSet.fromTrie(this)
-
protected def elemHashCode(key: A) = key.##
protected final def improve(hcode: Int) = {
@@ -79,8 +79,7 @@ class HashSet[A] extends Set[A]
protected def removed0(key: A, hash: Int, level: Int): HashSet[A] = this
protected def writeReplace(): AnyRef = new HashSet.SerializationProxy(this)
- override def toParIterable = par
- override def toParSet[B >: A] = par.asInstanceOf[ParHashSet[B]]
+
}
/** $factoryInfo
diff --git a/src/library/scala/collection/immutable/Iterable.scala b/src/library/scala/collection/immutable/Iterable.scala
index 51227556ad..7f5cb055f4 100644
--- a/src/library/scala/collection/immutable/Iterable.scala
+++ b/src/library/scala/collection/immutable/Iterable.scala
@@ -13,6 +13,7 @@ package immutable
import generic._
import mutable.Builder
+import parallel.immutable.ParIterable
/** A base trait for iterable collections that are guaranteed immutable.
* $iterableInfo
@@ -23,8 +24,10 @@ import mutable.Builder
trait Iterable[+A] extends Traversable[A]
with scala.collection.Iterable[A]
with GenericTraversableTemplate[A, Iterable]
- with IterableLike[A, Iterable[A]] {
+ with IterableLike[A, Iterable[A]]
+ with Parallelizable[A, ParIterable[A]] {
override def companion: GenericCompanion[Iterable] = Iterable
+ protected[this] override def parCombiner = ParIterable.newCombiner[A] // if `immutable.IterableLike` gets introduced, please move this there!
}
/** $factoryInfo
diff --git a/src/library/scala/collection/immutable/MapLike.scala b/src/library/scala/collection/immutable/MapLike.scala
index a0f1632d1e..13054b9f83 100644
--- a/src/library/scala/collection/immutable/MapLike.scala
+++ b/src/library/scala/collection/immutable/MapLike.scala
@@ -10,6 +10,7 @@ package scala.collection
package immutable
import generic._
+import parallel.immutable.ParMap
/**
* A generic template for immutable maps from keys of type `A`
@@ -46,8 +47,11 @@ import generic._
*/
trait MapLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]]
extends scala.collection.MapLike[A, B, This]
+ with Parallelizable[(A, B), ParMap[A, B]]
{ self =>
+ protected[this] override def parCombiner = ParMap.newCombiner[A, B]
+
/** A new immutable map containing updating this map with a given key/value mapping.
* @param key the key
* @param value the value
diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala
index f8b3dfa54f..90a1383353 100644
--- a/src/library/scala/collection/immutable/Range.scala
+++ b/src/library/scala/collection/immutable/Range.scala
@@ -41,10 +41,10 @@ import scala.collection.parallel.immutable.ParRange
@SerialVersionUID(7618862778670199309L)
class Range(val start: Int, val end: Int, val step: Int)
extends IndexedSeq[Int]
- with collection.Parallelizable[ParRange]
+ with collection.CustomParallelizable[Int, ParRange]
with Serializable
{
- def par = new ParRange(this)
+ override def par = new ParRange(this)
// Note that this value is calculated eagerly intentionally: it also
// serves to enforce conditions (step != 0) && (length <= Int.MaxValue)
@@ -205,11 +205,9 @@ extends IndexedSeq[Int]
final def contains(x: Int) = isWithinBoundaries(x) && ((x - start) % step == 0)
- override def toParIterable = par
+ override def toIterable = this
- override def toParSeq = par
-
- override def toParSet[U >: Int] = par.toParSet[U]
+ override def toSeq = this
override def equals(other: Any) = other match {
case x: Range =>
diff --git a/src/library/scala/collection/immutable/Seq.scala b/src/library/scala/collection/immutable/Seq.scala
index c3c34d3f89..4f061983de 100644
--- a/src/library/scala/collection/immutable/Seq.scala
+++ b/src/library/scala/collection/immutable/Seq.scala
@@ -13,6 +13,7 @@ package immutable
import generic._
import mutable.Builder
+import parallel.immutable.ParSeq
/** A subtrait of `collection.Seq` which represents sequences
* that are guaranteed immutable.
@@ -24,9 +25,11 @@ import mutable.Builder
trait Seq[+A] extends Iterable[A]
with scala.collection.Seq[A]
with GenericTraversableTemplate[A, Seq]
- with SeqLike[A, Seq[A]] {
+ with SeqLike[A, Seq[A]]
+ with Parallelizable[A, ParSeq[A]] {
override def companion: GenericCompanion[Seq] = Seq
override def toSeq: Seq[A] = this
+ protected[this] override def parCombiner = ParSeq.newCombiner[A] // if `immutable.SeqLike` gets introduced, please move this there!
}
/** $factoryInfo
diff --git a/src/library/scala/collection/immutable/Set.scala b/src/library/scala/collection/immutable/Set.scala
index e2bad2f052..1b61c6f565 100644
--- a/src/library/scala/collection/immutable/Set.scala
+++ b/src/library/scala/collection/immutable/Set.scala
@@ -12,6 +12,7 @@ package scala.collection
package immutable
import generic._
+import parallel.immutable.ParSet
/** A generic trait for immutable sets.
*
@@ -27,9 +28,11 @@ import generic._
trait Set[A] extends Iterable[A]
with scala.collection.Set[A]
with GenericSetTemplate[A, Set]
- with SetLike[A, Set[A]] {
+ with SetLike[A, Set[A]]
+ with Parallelizable[A, ParSet[A]] {
override def companion: GenericCompanion[Set] = Set
override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set[B]]
+ protected override def parCombiner = ParSet.newCombiner[A] // if `immutable.SetLike` gets introduced, please move this there!
}
/** $factoryInfo
diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala
index 92a6160213..3078a26411 100644
--- a/src/library/scala/collection/immutable/Vector.scala
+++ b/src/library/scala/collection/immutable/Vector.scala
@@ -39,7 +39,7 @@ extends IndexedSeq[A]
with IndexedSeqLike[A, Vector[A]]
with VectorPointer[A @uncheckedVariance]
with Serializable
- with Parallelizable[ParVector[A]]
+ with CustomParallelizable[A, ParVector[A]]
{ self =>
override def companion: GenericCompanion[Vector] = Vector
@@ -53,7 +53,7 @@ override def companion: GenericCompanion[Vector] = Vector
def length = endIndex - startIndex
- def par = new ParVector(this)
+ override def par = new ParVector(this)
override def lengthCompare(len: Int): Int = length - len
diff --git a/src/library/scala/collection/interfaces/TraversableOnceMethods.scala b/src/library/scala/collection/interfaces/TraversableOnceMethods.scala
index 8967e15a34..5e1325fef6 100644
--- a/src/library/scala/collection/interfaces/TraversableOnceMethods.scala
+++ b/src/library/scala/collection/interfaces/TraversableOnceMethods.scala
@@ -53,10 +53,6 @@ trait TraversableOnceMethods[+A] {
def toIterator: Iterator[A]
def toList: List[A]
def toMap[T, U](implicit ev: A <:< (T, U)): immutable.Map[T, U]
- def toParIterable: parallel.ParIterable[A]
- def toParMap[T, U](implicit ev: A <:< (T, U)): parallel.ParMap[T, U]
- def toParSeq: parallel.ParSeq[A]
- def toParSet[B >: A]: parallel.ParSet[B]
def toSeq: Seq[A]
def toSet[B >: A]: immutable.Set[B]
def toStream: Stream[A]
diff --git a/src/library/scala/collection/mutable/ArrayBuffer.scala b/src/library/scala/collection/mutable/ArrayBuffer.scala
index 9d07294f51..daa3c48578 100644
--- a/src/library/scala/collection/mutable/ArrayBuffer.scala
+++ b/src/library/scala/collection/mutable/ArrayBuffer.scala
@@ -48,7 +48,7 @@ class ArrayBuffer[A](override protected val initialSize: Int)
with IndexedSeqOptimized[A, ArrayBuffer[A]]
with Builder[A, ArrayBuffer[A]]
with ResizableArray[A]
- with Parallelizable[ParArray[A]]
+ with CustomParallelizable[A, ParArray[A]]
with Serializable {
override def companion: GenericCompanion[ArrayBuffer] = ArrayBuffer
@@ -67,7 +67,7 @@ class ArrayBuffer[A](override protected val initialSize: Int)
}
}
- def par = ParArray.handoff[A](array.asInstanceOf[Array[A]], size)
+ override def par = ParArray.handoff[A](array.asInstanceOf[Array[A]], size)
/** Appends a single element to this buffer and returns
* the identity of the buffer. It takes constant amortized time.
@@ -177,10 +177,6 @@ class ArrayBuffer[A](override protected val initialSize: Int)
*/
override def stringPrefix: String = "ArrayBuffer"
- override def toParIterable = par
-
- override def toParSeq = par
-
}
/** Factory object for the `ArrayBuffer` class.
diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala
index 3cf1795e80..b72206e6f3 100644
--- a/src/library/scala/collection/mutable/ArrayOps.scala
+++ b/src/library/scala/collection/mutable/ArrayOps.scala
@@ -35,7 +35,7 @@ import parallel.mutable.ParArray
* @define mayNotTerminateInf
* @define willNotTerminateInf
*/
-abstract class ArrayOps[T] extends ArrayLike[T, Array[T]] with Parallelizable[ParArray[T]] {
+abstract class ArrayOps[T] extends ArrayLike[T, Array[T]] with CustomParallelizable[T, ParArray[T]] {
private def rowBuilder[U]: Builder[U, Array[U]] =
Array.newBuilder(
@@ -55,7 +55,7 @@ abstract class ArrayOps[T] extends ArrayLike[T, Array[T]] with Parallelizable[Pa
else
super.toArray[U]
- def par = ParArray.handoff(repr)
+ override def par = ParArray.handoff(repr)
/** Flattens a two-dimensional array by concatenating all its rows
* into a single array.
diff --git a/src/library/scala/collection/mutable/ArraySeq.scala b/src/library/scala/collection/mutable/ArraySeq.scala
index cd53a24680..0b3f0ebc5b 100644
--- a/src/library/scala/collection/mutable/ArraySeq.scala
+++ b/src/library/scala/collection/mutable/ArraySeq.scala
@@ -44,7 +44,7 @@ class ArraySeq[A](override val length: Int)
extends IndexedSeq[A]
with GenericTraversableTemplate[A, ArraySeq]
with IndexedSeqOptimized[A, ArraySeq[A]]
- with Parallelizable[ParArray[A]]
+ with CustomParallelizable[A, ParArray[A]]
with Serializable
{
@@ -52,7 +52,7 @@ extends IndexedSeq[A]
val array: Array[AnyRef] = new Array[AnyRef](length)
- def par = ParArray.handoff(array.asInstanceOf[Array[A]])
+ override def par = ParArray.handoff(array.asInstanceOf[Array[A]])
def apply(idx: Int): A = {
if (idx >= length) throw new IndexOutOfBoundsException(idx.toString)
@@ -86,10 +86,6 @@ extends IndexedSeq[A]
Array.copy(array, 0, xs, start, len1)
}
- override def toParIterable = par
-
- override def toParSeq = par
-
}
/** $factoryInfo
diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala
index 890a6cbf24..e78e9a1296 100644
--- a/src/library/scala/collection/mutable/HashMap.scala
+++ b/src/library/scala/collection/mutable/HashMap.scala
@@ -44,7 +44,7 @@ class HashMap[A, B] private[collection] (contents: HashTable.Contents[A, Default
extends Map[A, B]
with MapLike[A, B, HashMap[A, B]]
with HashTable[A, DefaultEntry[A, B]]
- with Parallelizable[ParHashMap[A, B]]
+ with CustomParallelizable[(A, B), ParHashMap[A, B]]
with Serializable
{
initWithContents(contents)
@@ -57,7 +57,7 @@ extends Map[A, B]
def this() = this(null)
- def par = new ParHashMap[A, B](hashTableContents)
+ override def par = new ParHashMap[A, B](hashTableContents)
def get(key: A): Option[B] = {
val e = findEntry(key)
@@ -130,11 +130,6 @@ extends Map[A, B]
init[B](in, new Entry(_, _))
}
- override def toParIterable = par
-
- private type C = (A, B)
- override def toParMap[D, E](implicit ev: C <:< (D, E)) = par.asInstanceOf[ParHashMap[D, E]]
-
}
/** $factoryInfo
diff --git a/src/library/scala/collection/mutable/HashSet.scala b/src/library/scala/collection/mutable/HashSet.scala
index a1b85fa16e..2ba5065964 100644
--- a/src/library/scala/collection/mutable/HashSet.scala
+++ b/src/library/scala/collection/mutable/HashSet.scala
@@ -44,7 +44,7 @@ extends Set[A]
with GenericSetTemplate[A, HashSet]
with SetLike[A, HashSet[A]]
with FlatHashTable[A]
- with Parallelizable[ParHashSet[A]]
+ with CustomParallelizable[A, ParHashSet[A]]
with Serializable
{
initWithContents(contents)
@@ -60,7 +60,7 @@ extends Set[A]
def += (elem: A): this.type = { addEntry(elem); this }
def -= (elem: A): this.type = { removeEntry(elem); this }
- def par = new ParHashSet(hashTableContents)
+ override def par = new ParHashSet(hashTableContents)
override def add(elem: A): Boolean = addEntry(elem)
override def remove(elem: A): Boolean = removeEntry(elem).isDefined
@@ -93,10 +93,6 @@ extends Set[A]
if (!isSizeMapDefined) sizeMapInitAndRebuild
} else sizeMapDisable
- override def toParIterable = par
-
- override def toParSet[B >: A] = par.asInstanceOf[ParHashSet[B]]
-
}
/** $factoryInfo
diff --git a/src/library/scala/collection/mutable/Iterable.scala b/src/library/scala/collection/mutable/Iterable.scala
index ddf917ba82..8e244d980d 100644
--- a/src/library/scala/collection/mutable/Iterable.scala
+++ b/src/library/scala/collection/mutable/Iterable.scala
@@ -9,6 +9,7 @@ package scala.collection
package mutable
import generic._
+import parallel.mutable.ParIterable
/** A base trait for iterable collections that can be mutated.
* $iterableInfo
@@ -16,8 +17,10 @@ import generic._
trait Iterable[A] extends Traversable[A]
with scala.collection.Iterable[A]
with GenericTraversableTemplate[A, Iterable]
- with IterableLike[A, Iterable[A]] {
+ with IterableLike[A, Iterable[A]]
+ with Parallelizable[A, ParIterable[A]] {
override def companion: GenericCompanion[Iterable] = Iterable
+ protected[this] override def parCombiner = ParIterable.newCombiner[A] // if `mutable.IterableLike` gets introduced, please move this there!
}
/** $factoryInfo
diff --git a/src/library/scala/collection/mutable/MapLike.scala b/src/library/scala/collection/mutable/MapLike.scala
index 1708d25234..04ba8608b9 100644
--- a/src/library/scala/collection/mutable/MapLike.scala
+++ b/src/library/scala/collection/mutable/MapLike.scala
@@ -13,6 +13,7 @@ package mutable
import generic._
import annotation.migration
+import parallel.mutable.ParMap
/** A template trait for mutable maps.
* $mapNote
@@ -25,6 +26,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
with Growable[(A, B)]
with Shrinkable[A]
with Cloneable[This]
+ with Parallelizable[(A, B), ParMap[A, B]]
{ self =>
import scala.collection.Traversable
@@ -36,6 +38,8 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
*/
override protected[this] def newBuilder: Builder[(A, B), This] = empty
+ protected[this] override def parCombiner = ParMap.newCombiner[A, B]
+
/** Adds a new key/value pair to this map and optionally returns previously bound value.
* If the map already contains a
* mapping for the key, it will be overridden by the new value.
diff --git a/src/library/scala/collection/mutable/SeqLike.scala b/src/library/scala/collection/mutable/SeqLike.scala
index 910dd1aab9..4d315b8256 100644
--- a/src/library/scala/collection/mutable/SeqLike.scala
+++ b/src/library/scala/collection/mutable/SeqLike.scala
@@ -10,6 +10,7 @@ package scala.collection
package mutable
import generic._
+import parallel.mutable.ParSeq
/** A template trait for mutable sequences of type `mutable.Seq[A]`.
* @tparam A the type of the elements of the set
@@ -18,9 +19,12 @@ import generic._
*/
trait SeqLike[A, +This <: SeqLike[A, This] with Seq[A]]
extends scala.collection.SeqLike[A, This]
- with Cloneable[This] {
+ with Cloneable[This]
+ with Parallelizable[A, ParSeq[A]] {
self =>
+ protected[this] override def parCombiner = ParSeq.newCombiner[A]
+
/** Replaces element at given index with a new value.
*
* @param n the index of the element to replace.
diff --git a/src/library/scala/collection/mutable/SetLike.scala b/src/library/scala/collection/mutable/SetLike.scala
index c85349fc1a..985e7a3b47 100644
--- a/src/library/scala/collection/mutable/SetLike.scala
+++ b/src/library/scala/collection/mutable/SetLike.scala
@@ -14,6 +14,7 @@ package mutable
import generic._
import script._
import scala.annotation.migration
+import parallel.mutable.ParSet
/** A template trait for mutable sets of type `mutable.Set[A]`.
* @tparam A the type of the elements of the set
@@ -60,6 +61,7 @@ trait SetLike[A, +This <: SetLike[A, This] with Set[A]]
with Growable[A]
with Shrinkable[A]
with Cloneable[mutable.Set[A]]
+ with Parallelizable[A, ParSet[A]]
{ self =>
/** A common implementation of `newBuilder` for all mutable sets
@@ -68,6 +70,8 @@ trait SetLike[A, +This <: SetLike[A, This] with Set[A]]
*/
override protected[this] def newBuilder: Builder[A, This] = empty
+ protected[this] override def parCombiner = ParSet.newCombiner[A]
+
/** Adds an element to this $coll.
*
* @param elem the element to be added
diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala
index 319053d488..21e62306e7 100644
--- a/src/library/scala/collection/mutable/WrappedArray.scala
+++ b/src/library/scala/collection/mutable/WrappedArray.scala
@@ -33,7 +33,7 @@ import scala.collection.parallel.mutable.ParArray
abstract class WrappedArray[T]
extends IndexedSeq[T]
with ArrayLike[T, WrappedArray[T]]
- with Parallelizable[ParArray[T]]
+ with CustomParallelizable[T, ParArray[T]]
{
override protected[this] def thisCollection: WrappedArray[T] = this
@@ -54,7 +54,7 @@ extends IndexedSeq[T]
/** The underlying array */
def array: Array[T]
- def par = ParArray.handoff(array)
+ override def par = ParArray.handoff(array)
override def toArray[U >: T : ClassManifest]: Array[U] =
if (implicitly[ClassManifest[U]].erasure eq array.getClass.getComponentType)
@@ -72,10 +72,6 @@ extends IndexedSeq[T]
override protected[this] def newBuilder: Builder[T, WrappedArray[T]] =
new WrappedArrayBuilder[T](elemManifest)
- override def toParIterable = par
-
- override def toParSeq = par
-
}
/** A companion object used to create instances of `WrappedArray`.
diff --git a/src/library/scala/collection/parallel/ParIterableLike.scala b/src/library/scala/collection/parallel/ParIterableLike.scala
index a92c4f15fb..6b7f244867 100644
--- a/src/library/scala/collection/parallel/ParIterableLike.scala
+++ b/src/library/scala/collection/parallel/ParIterableLike.scala
@@ -16,7 +16,7 @@ import scala.collection.mutable.Builder
import scala.collection.mutable.ArrayBuffer
import scala.collection.IterableLike
import scala.collection.Parallel
-import scala.collection.Parallelizable
+import scala.collection.CustomParallelizable
import scala.collection.Sequentializable
import scala.collection.generic._
import immutable.HashMapCombiner
@@ -82,10 +82,15 @@ import annotation.unchecked.uncheckedVariance
* def par: Repr
* }}}
*
- * produce a view of the collection that has sequential or parallel operations, respectively.
- * These methods are efficient - they will not copy the elements, but have fixed target
- * types. The combination of methods `toParMap`, `toParSeq` or `toParSet` is more flexible,
- * but may copy the elements in some cases.
+ * produce the sequential or parallel implementation of the collection, respectively.
+ * Method `par` just returns a reference to this parallel collection.
+ * Method `seq` is efficient - it will not copy the elements. Instead,
+ * it will create a sequential version of the collection using the same underlying data structure.
+ * Note that this is not the case for sequential collections in general - they may copy the elements
+ * and produce a different underlying data structure.
+ *
+ * The combination of methods `toMap`, `toSeq` or `toSet` along with `par` and `seq` is a flexible
+ * way to change between different collection types.
*
* The method:
*
@@ -152,9 +157,9 @@ import annotation.unchecked.uncheckedVariance
* that splitters may set and read the `indexFlag` state.
*
*/
-trait ParIterableLike[+T, +Repr <: Parallel, +Sequential <: Iterable[T] with IterableLike[T, Sequential]]
+trait ParIterableLike[+T, +Repr <: ParIterable[T], +Sequential <: Iterable[T] with IterableLike[T, Sequential]]
extends IterableLike[T, Repr]
- with Parallelizable[Repr]
+ with CustomParallelizable[T, Repr]
with Sequentializable[T, Sequential]
with Parallel
with HasNewCombiner[T, Repr]
@@ -215,7 +220,7 @@ self =>
*/
def iterator: Splitter[T] = parallelIterator
- def par = repr
+ override def par = repr
/** Denotes whether this parallel collection has strict splitters.
*
@@ -730,8 +735,6 @@ self =>
def parallelIterator = self.parallelIterator
}
- override def toIterable: Iterable[T] = seq.drop(0).asInstanceOf[Iterable[T]]
-
override def toArray[U >: T: ClassManifest]: Array[U] = {
val arr = new Array[U](size)
copyToArray(arr)
@@ -744,25 +747,21 @@ self =>
override def toStream: Stream[T] = seq.toStream
- override def toSet[U >: T]: collection.immutable.Set[U] = seq.toSet
-
- override def toSeq: Seq[T] = seq.toSeq
-
- override def toIterator: Iterator[T] = seq.toIterator
+ override def toIterator: Iterator[T] = parallelIterator
- override def toTraversable: Traversable[T] = seq.toTraversable
+ // the methods below are overridden
- override def toBuffer[U >: T]: collection.mutable.Buffer[U] = seq.toBuffer
+ override def toBuffer[U >: T]: collection.mutable.Buffer[U] = seq.toBuffer // have additional, parallel buffers?
- override def toMap[K, V](implicit ev: T <:< (K, V)): collection.immutable.Map[K, V] = seq.toMap
+ override def toTraversable: Traversable[T] = this.asInstanceOf[Traversable[T]] // TODO add ParTraversable[T]
- override def toParIterable: ParIterable[T] = this.asInstanceOf[ParIterable[T]]
+ override def toIterable: ParIterable[T] = this.asInstanceOf[ParIterable[T]]
- override def toParSeq: ParSeq[T] = toParCollection[T, ParSeq[T]](() => mutable.ParArrayCombiner[T]())
+ override def toSeq: ParSeq[T] = toParCollection[T, ParSeq[T]](() => ParSeq.newCombiner[T])
- override def toParSet[U >: T]: ParSet[U] = toParCollection[U, ParSet[U]](() => mutable.ParHashSetCombiner[U])
+ override def toSet[U >: T]: immutable.ParSet[U] = toParCollection[U, immutable.ParSet[U]](() => immutable.ParSet.newCombiner[U])
- override def toParMap[K, V](implicit ev: T <:< (K, V)): ParMap[K, V] = toParMap[K, V, mutable.ParHashMap[K, V]](() => mutable.ParHashMapCombiner[K, V])
+ override def toMap[K, V](implicit ev: T <:< (K, V)): immutable.ParMap[K, V] = toParMap[K, V, immutable.ParMap[K, V]](() => immutable.ParMap.newCombiner[K, V])
/* tasks */
diff --git a/src/library/scala/collection/parallel/ParMapLike.scala b/src/library/scala/collection/parallel/ParMapLike.scala
index e8f076dc4f..1cd5ad02d7 100644
--- a/src/library/scala/collection/parallel/ParMapLike.scala
+++ b/src/library/scala/collection/parallel/ParMapLike.scala
@@ -48,9 +48,7 @@ extends MapLike[K, V, Repr]
override def empty: Repr
- private type T = (K, V)
- override def toParMap[K, V](implicit ev: T <:< (K, V)) = this.asInstanceOf[ParMap[K, V]]
-
+ // note - should not override toMap (could be mutable)
}
diff --git a/src/library/scala/collection/parallel/ParSeqLike.scala b/src/library/scala/collection/parallel/ParSeqLike.scala
index d40ced0cd8..1e49f69753 100644
--- a/src/library/scala/collection/parallel/ParSeqLike.scala
+++ b/src/library/scala/collection/parallel/ParSeqLike.scala
@@ -45,7 +45,7 @@ import scala.collection.generic.VolatileAbort
* @author Aleksandar Prokopec
* @since 2.9
*/
-trait ParSeqLike[+T, +Repr <: Parallel, +Sequential <: Seq[T] with SeqLike[T, Sequential]]
+trait ParSeqLike[+T, +Repr <: ParSeq[T], +Sequential <: Seq[T] with SeqLike[T, Sequential]]
extends scala.collection.SeqLike[T, Repr]
with ParIterableLike[T, Repr, Sequential] {
self =>
@@ -314,7 +314,7 @@ self =>
override def toString = seq.mkString(stringPrefix + "(", ", ", ")")
- override def toParSeq = this.asInstanceOf[ParSeq[T]] // TODO add a type bound for `Repr`
+ override def toSeq = this.asInstanceOf[ParSeq[T]]
override def view = new ParSeqView[T, Repr, Sequential] {
protected lazy val underlying = self.repr
diff --git a/src/library/scala/collection/parallel/ParSetLike.scala b/src/library/scala/collection/parallel/ParSetLike.scala
index d888d5865f..9e769f425b 100644
--- a/src/library/scala/collection/parallel/ParSetLike.scala
+++ b/src/library/scala/collection/parallel/ParSetLike.scala
@@ -45,8 +45,7 @@ extends SetLike[T, Repr]
override def empty: Repr
- override def toParSet[U >: T] = this.asInstanceOf[ParSet[U]]
-
+ // note: should not override toSet (could be mutable)
}
diff --git a/src/library/scala/collection/parallel/immutable/ParIterable.scala b/src/library/scala/collection/parallel/immutable/ParIterable.scala
index 0118452cb8..c4da1ced8e 100644
--- a/src/library/scala/collection/parallel/immutable/ParIterable.scala
+++ b/src/library/scala/collection/parallel/immutable/ParIterable.scala
@@ -36,16 +36,14 @@ extends collection.immutable.Iterable[T]
{
override def companion: GenericCompanion[ParIterable] with GenericParCompanion[ParIterable] = ParIterable
- override def toParIterable: ParIterable[T] = this
+ // if `immutable.ParIterableLike` is introduced, please move these 4 methods there
+ override def toIterable: ParIterable[T] = this
- // override def toParSeq: ParSeq TODO vector
-
- override def toParSet[U >: T]: ParSet[U] = toParCollection[U, ParHashSet[U]](() => HashSetCombiner[U])
-
- override def toParMap[K, V](implicit ev: T <:< (K, V)): ParMap[K, V] = toParMap(() => HashMapCombiner[K, V])
+ override def toSeq: ParSeq[T] = toParCollection[T, ParSeq[T]](() => ParSeq.newCombiner[T])
}
+
/** $factoryinfo
*/
object ParIterable extends ParFactory[ParIterable] {
diff --git a/src/library/scala/collection/parallel/immutable/ParMap.scala b/src/library/scala/collection/parallel/immutable/ParMap.scala
index d99091c57c..5db07a6a3b 100644
--- a/src/library/scala/collection/parallel/immutable/ParMap.scala
+++ b/src/library/scala/collection/parallel/immutable/ParMap.scala
@@ -50,7 +50,7 @@ self =>
override def stringPrefix = "ParMap"
- override def toParMap[P, Q](implicit ev: (K, V) <:< (P, Q)): ParMap[P, Q] = this.asInstanceOf[ParMap[P, Q]]
+ override def toMap[P, Q](implicit ev: (K, V) <:< (P, Q)): ParMap[P, Q] = this.asInstanceOf[ParMap[P, Q]]
}
diff --git a/src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled b/src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled
index a32d7bb086..fb411ec0ac 100644
--- a/src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled
+++ b/src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled
@@ -49,10 +49,6 @@ self =>
type SCPI = SignalContextPassingIterator[ParNumericRangeIterator]
- override def toParSeq = this
-
- override def toParSet[U >: T] = toParCollection[U, ParSet[U]](() => HashSetCombiner[U])
-
class ParNumericRangeIterator(range: NumericRange[T] = self.range, num: Integral[T] = self.num)
extends ParIterator {
me: SignalContextPassingIterator[ParNumericRangeIterator] =>
diff --git a/src/library/scala/collection/parallel/immutable/ParRange.scala b/src/library/scala/collection/parallel/immutable/ParRange.scala
index 19d2a6d3b8..f68c7c9062 100644
--- a/src/library/scala/collection/parallel/immutable/ParRange.scala
+++ b/src/library/scala/collection/parallel/immutable/ParRange.scala
@@ -49,10 +49,6 @@ self =>
type SCPI = SignalContextPassingIterator[ParRangeIterator]
- override def toParSeq = this
-
- override def toParSet[U >: Int] = toParCollection[U, ParSet[U]](() => HashSetCombiner[U])
-
class ParRangeIterator(range: Range = self.range)
extends ParIterator {
me: SignalContextPassingIterator[ParRangeIterator] =>
diff --git a/src/library/scala/collection/parallel/immutable/ParSet.scala b/src/library/scala/collection/parallel/immutable/ParSet.scala
index 2002d6432d..73d27df994 100644
--- a/src/library/scala/collection/parallel/immutable/ParSet.scala
+++ b/src/library/scala/collection/parallel/immutable/ParSet.scala
@@ -42,8 +42,8 @@ self =>
override def stringPrefix = "ParSet"
- override def toParSet[U >: T] = this.asInstanceOf[ParSet[U]]
-
+ // ok, because this could only violate `apply` and we can live with that
+ override def toSet[U >: T]: ParSet[U] = this.asInstanceOf[ParSet[U]]
}
diff --git a/src/library/scala/collection/parallel/mutable/ParIterable.scala b/src/library/scala/collection/parallel/mutable/ParIterable.scala
index eba4ff2e72..fcba75452f 100644
--- a/src/library/scala/collection/parallel/mutable/ParIterable.scala
+++ b/src/library/scala/collection/parallel/mutable/ParIterable.scala
@@ -32,6 +32,11 @@ trait ParIterable[T] extends collection.mutable.Iterable[T]
with GenericParTemplate[T, ParIterable]
with ParIterableLike[T, ParIterable[T], Iterable[T]] {
override def companion: GenericCompanion[ParIterable] with GenericParCompanion[ParIterable] = ParIterable
+
+ // if `mutable.ParIterableLike` is introduced, please move these 4 methods there
+ override def toIterable: ParIterable[T] = this
+
+ override def toSeq: ParSeq[T] = toParCollection[T, ParSeq[T]](() => ParSeq.newCombiner[T])
}
/** $factoryinfo
diff --git a/src/library/scala/collection/parallel/mutable/ParMapLike.scala b/src/library/scala/collection/parallel/mutable/ParMapLike.scala
index cd2bea1419..46352829aa 100644
--- a/src/library/scala/collection/parallel/mutable/ParMapLike.scala
+++ b/src/library/scala/collection/parallel/mutable/ParMapLike.scala
@@ -33,5 +33,9 @@ trait ParMapLike[K,
+Repr <: ParMapLike[K, V, Repr, Sequential] with ParMap[K, V],
+Sequential <: collection.mutable.Map[K, V] with collection.mutable.MapLike[K, V, Sequential]]
extends collection.mutable.MapLike[K, V, Repr]
- with collection.parallel.ParMapLike[K, V, Repr, Sequential]
+ with collection.parallel.ParMapLike[K, V, Repr, Sequential] {
+
+ // note: should not override toMap
+
+}
diff --git a/src/library/scala/collection/parallel/mutable/ParSeq.scala b/src/library/scala/collection/parallel/mutable/ParSeq.scala
index 10d3033701..1b2b9f9854 100644
--- a/src/library/scala/collection/parallel/mutable/ParSeq.scala
+++ b/src/library/scala/collection/parallel/mutable/ParSeq.scala
@@ -39,6 +39,8 @@ trait ParSeq[T] extends collection.mutable.Seq[T]
def update(i: Int, elem: T): Unit
+ override def toSeq: ParSeq[T] = this
+
}
diff --git a/src/library/scala/collection/parallel/mutable/ParSetLike.scala b/src/library/scala/collection/parallel/mutable/ParSetLike.scala
index df87eff42c..68f142cda7 100644
--- a/src/library/scala/collection/parallel/mutable/ParSetLike.scala
+++ b/src/library/scala/collection/parallel/mutable/ParSetLike.scala
@@ -46,6 +46,7 @@ extends mutable.SetLike[T, Repr]
override def empty: Repr
+ // note: should not override toSet
}
diff --git a/src/library/scala/sys/BooleanProp.scala b/src/library/scala/sys/BooleanProp.scala
index e598d81307..85719103de 100644
--- a/src/library/scala/sys/BooleanProp.scala
+++ b/src/library/scala/sys/BooleanProp.scala
@@ -31,7 +31,11 @@ trait BooleanProp extends Prop[Boolean] {
object BooleanProp {
private[sys]
class BooleanPropImpl(key: String, valueFn: String => Boolean) extends PropImpl(key, valueFn) with BooleanProp {
- def enable() = this set "true"
+ override def setValue[T1 >: Boolean](newValue: T1): Boolean = newValue match {
+ case x: Boolean if !x => val old = value ; clear() ; old
+ case x => super.setValue(newValue)
+ }
+ def enable() = this setValue true
def disable() = this.clear()
def toggle() = if (value) disable() else enable()
}
@@ -39,6 +43,7 @@ object BooleanProp {
class ConstantImpl(val key: String, val value: Boolean) extends BooleanProp {
val isSet = value
def set(newValue: String) = "" + value
+ def setValue[T1 >: Boolean](newValue: T1): Boolean = value
def get: String = "" + value
val clear, enable, disable, toggle = ()
protected def zero = false
diff --git a/src/library/scala/sys/Prop.scala b/src/library/scala/sys/Prop.scala
index e3cbd4e515..de38a56c73 100644
--- a/src/library/scala/sys/Prop.scala
+++ b/src/library/scala/sys/Prop.scala
@@ -43,6 +43,10 @@ trait Prop[+T] {
*/
def set(newValue: String): String
+ /** Sets the property with a value of the represented type.
+ */
+ def setValue[T1 >: T](value: T1): T
+
/** Gets the current string value if any. Will not return null: use
* `isSet` to test for existence.
* @return the current string value if any, else the empty string
diff --git a/src/library/scala/sys/PropImpl.scala b/src/library/scala/sys/PropImpl.scala
index 55073c35d3..888e9d7327 100644
--- a/src/library/scala/sys/PropImpl.scala
+++ b/src/library/scala/sys/PropImpl.scala
@@ -20,6 +20,12 @@ private[sys] class PropImpl[+T](val key: String, valueFn: String => T) extends P
underlying(key) = newValue
old
}
+ def setValue[T1 >: T](newValue: T1): T = {
+ val old = value
+ if (newValue == null) set(null)
+ else set("" + newValue)
+ old
+ }
def get: String =
if (isSet) underlying.getOrElse(key, "")
else ""
diff --git a/src/library/scala/sys/SystemProperties.scala b/src/library/scala/sys/SystemProperties.scala
index 7c6286516b..228ca6315e 100644
--- a/src/library/scala/sys/SystemProperties.scala
+++ b/src/library/scala/sys/SystemProperties.scala
@@ -48,9 +48,14 @@ class SystemProperties extends mutable.Map[String, String] {
* }}}
*/
object SystemProperties {
+ /** An unenforceable, advisory only place to do some synchronization when
+ * mutating system properties.
+ */
+ def exclusively[T](body: => T) = this synchronized body
+
implicit def systemPropertiesToCompanion(p: SystemProperties): SystemProperties.type = this
private lazy val propertyHelp = mutable.Map[String, String]()
- private def bool(key: String, helpText: String) = {
+ private def bool(key: String, helpText: String): BooleanProp = {
val prop = (
if (key startsWith "java.") BooleanProp.valueIsTrue(key)
else BooleanProp.keyExists(key)
@@ -63,8 +68,9 @@ object SystemProperties {
// Todo: bring some sanity to the intersection of system properties aka "mutable
// state shared by everyone and everything" and the reality that there is no other
// mechanism for accomplishing some things on the jvm.
- lazy val headless = bool("java.awt.headless", "system should not utilize a display device")
- lazy val preferIPv4 = bool("java.net.preferIPv4Stack", "system should prefer IPv4 sockets")
- lazy val noTraceSupression = bool("scala.control.no-trace-suppression", "scala should not suppress any stack trace creation")
+ lazy val headless = bool("java.awt.headless", "system should not utilize a display device")
+ lazy val preferIPv4Stack = bool("java.net.preferIPv4Stack", "system should prefer IPv4 sockets")
+ lazy val preferIPv6Addresses = bool("java.net.preferIPv6Addresses", "system should prefer IPv6 addresses")
+ lazy val noTraceSupression = bool("scala.control.noTraceSuppression", "scala should not suppress any stack trace creation")
}
diff --git a/test/files/run/coder/Coder.scala b/test/files/run/coder/Coder.scala
index 5c81efc9c0..06dd4b6355 100644
--- a/test/files/run/coder/Coder.scala
+++ b/test/files/run/coder/Coder.scala
@@ -85,7 +85,7 @@ class ParCoder(words: List[String]) {
def encode(number: String): ParSet[List[String]] =
if (number.isEmpty) ParSet(List())
else {
- val splits = (1 to number.length).toParSet
+ val splits = (1 to number.length).toSet.par
// for {
// split <- splits
// word <- wordsForNum(number take split)
diff --git a/test/files/run/coder2/Coder2.scala b/test/files/run/coder2/Coder2.scala
index 7ecc5e67d1..abe284a398 100644
--- a/test/files/run/coder2/Coder2.scala
+++ b/test/files/run/coder2/Coder2.scala
@@ -77,7 +77,7 @@ class ParCoder(words: List[String]) {
* them e.g. `5282` -> List(`Java`, `Kata`, `Lava`, ...)
*/
val wordsForNum: Map[String, ParSeq[String]] =
- (words groupBy wordCode).map(t => (t._1, t._2.toParSeq)) withDefaultValue ParSeq()
+ (words groupBy wordCode).map(t => (t._1, t._2.toSeq.par)) withDefaultValue ParSeq()
val comparison = new SeqCoder(words)
@@ -85,7 +85,7 @@ class ParCoder(words: List[String]) {
def encode(number: String): ParSet[ParSeq[String]] =
if (number.isEmpty) ParSet(ParSeq())
else {
- val splits = (1 to number.length).toParSet
+ val splits = (1 to number.length).toSet.par
// for {
// split <- splits
// word <- wordsForNum(number take split)
@@ -118,7 +118,7 @@ class ParCoder(words: List[String]) {
def assertWfn(num: String, split: String, dropped: String, r: ParSeq[ParSeq[String]]) {
val m = comparison.wfnmemo((num, split))
- val rs = r.toParSet
+ val rs = r.toSet.par
val words: ParSeq[String] = wordsForNum(split)
if (rs != m) {
println("flatmap for number with split: " + num + ", " + split)
@@ -168,32 +168,32 @@ object Test {
/* */
def main(args : Array[String]) {
- // for (i <- 0 until 10) {
- // val seqcoder = new SeqCoder(Dictionary.wordlist)
- // val st = seqcoder.translate(code)
- // //println("Translation check: " + st.size)
-
- // val parcoder = new ParCoder(Dictionary.wordlist)
- // val pt = parcoder.translate(code)
- // //println("Translation check: " + pt.size)
-
- // // val st = sts.toList.sorted
- // // val pt = pts.toList.sorted
- // if (st.size != pt.size) {
- // // val zipped = st.zip(pt)
- // // val ind = zipped.indexWhere { case (a, b) => a != b }
- // // val sliced = zipped.slice(ind - 10, ind + 10)
- // // println(sliced.map(t => t._1 + "\n" + t._2 + "\n--------").mkString("\n"))
- // println(i + ") seq vs par: " + st.size + " vs " + pt.size)
- // }
- // if (st != pt) {
- // val zipped = (st.toList.sorted zip pt.toList.sorted);
- // val diffp = zipped indexWhere { case (x, y) => x != y }
- // println(zipped/*.slice(diffp - 10, diffp + 10)*/ mkString ("\n"))
- // println((st.toList.sorted zip pt.toList.sorted) map { case (x, y) => (x == y) } reduceLeft(_ && _))
- // }
- // assert(st == pt)
- // }
+ for (i <- 0 until 10) {
+ val seqcoder = new SeqCoder(Dictionary.wordlist)
+ val sts = seqcoder.translate(code)
+ //println("Translation check: " + st.size)
+
+ val parcoder = new ParCoder(Dictionary.wordlist)
+ val pts = parcoder.translate(code)
+ //println("Translation check: " + pt.size)
+
+ val st = sts.toList.sorted
+ val pt = pts.toList.sorted
+ if (st.size != pt.size) {
+ val zipped = st.zip(pt)
+ val ind = zipped.indexWhere { case (a, b) => a != b }
+ val sliced = zipped.slice(ind - 10, ind + 10)
+ //println(sliced.map(t => t._1 + "\n" + t._2 + "\n--------").mkString("\n"))
+ //println(i + ") seq vs par: " + st.size + " vs " + pt.size)
+ }
+ if (st != pt) {
+ val zipped = (st.toList.sorted zip pt.toList.sorted);
+ val diffp = zipped indexWhere { case (x, y) => x != y }
+ //println(zipped/*.slice(diffp - 10, diffp + 10)*/ mkString ("\n"))
+ //println((st.toList.sorted zip pt.toList.sorted) map { case (x, y) => (x == y) } reduceLeft(_ && _))
+ }
+ assert(st == pt)
+ }
}
}
diff --git a/test/files/run/pc-conversions.scala b/test/files/run/pc-conversions.scala
index 7e894f70f3..23fcb9fa59 100644
--- a/test/files/run/pc-conversions.scala
+++ b/test/files/run/pc-conversions.scala
@@ -30,7 +30,7 @@ object Test {
assertPar(immutable.HashMap(1 -> 1, 2 -> 2))
assertPar(immutable.HashSet(1, 2, 3))
- // toPar*
+ // par.to* and to*.par tests
assertToPar(List(1 -> 1, 2 -> 2, 3 -> 3))
assertToPar(Stream(1 -> 1, 2 -> 2))
assertToPar(Array(1 -> 1, 2 -> 2))
@@ -55,28 +55,49 @@ object Test {
def assertSeq[T](pc: parallel.ParIterable[T]) = assert(pc.seq == pc)
- def assertPar[T, P <: Parallel](xs: Iterable[T] with Parallelizable[P]) = assert(xs == xs.par)
+ def assertPar[T, P <: Parallel](xs: Iterable[T]) = assert(xs == xs.par)
def assertToPar[K, V](xs: Traversable[(K, V)]) {
xs match {
- case _: Seq[_] => assert(xs.toParIterable == xs)
+ case _: Seq[_] =>
+ assert(xs.toIterable.par == xs)
+ assert(xs.par.toIterable == xs)
case _ =>
}
- assert(xs.toParSeq == xs.toSeq)
- assert(xs.toParSet == xs.toSet)
- assert(xs.toParMap == xs.toMap)
+
+ assert(xs.toSeq.par == xs.toSeq)
+ assert(xs.par.toSeq == xs.toSeq)
+
+ assert(xs.toSet.par == xs.toSet)
+ assert(xs.par.toSet == xs.toSet)
+
+ assert(xs.toMap.par == xs.toMap)
+ assert(xs.par.toMap == xs.toMap)
}
- def assertToParWoMap[T](xs: Traversable[T]) {
- assert(xs.toParIterable == xs)
- assert(xs.toParSeq == xs.toSeq)
- assert(xs.toParSet == xs.toSet)
+ def assertToParWoMap[T](xs: Seq[T]) {
+ assert(xs.toIterable.par == xs.toIterable)
+ assert(xs.par.toIterable == xs.toIterable)
+
+ assert(xs.toSeq.par == xs.toSeq)
+ assert(xs.par.toSeq == xs.toSeq)
+
+ assert(xs.toSet.par == xs.toSet)
+ assert(xs.par.toSet == xs.toSet)
}
def assertToParIt[K, V](xs: =>Iterator[(K, V)]) {
- assert(xs.toParSeq == xs.toSeq)
- assert(xs.toParSet == xs.toSet)
- assert(xs.toParMap == xs.toMap)
+ assert(xs.toIterable.par == xs.toIterable)
+ assert(xs.par.toIterable == xs.toIterable)
+
+ assert(xs.toSeq.par == xs.toSeq)
+ assert(xs.par.toSeq == xs.toSeq)
+
+ assert(xs.toSet.par == xs.toSet)
+ assert(xs.par.toSet == xs.toSet)
+
+ assert(xs.toMap.par == xs.toMap)
+ assert(xs.par.toMap == xs.toMap)
}
}
diff --git a/test/files/run/treePrint.scala b/test/files/run/treePrint.scala
index 8a77a3c9dc..ce7dd04499 100644
--- a/test/files/run/treePrint.scala
+++ b/test/files/run/treePrint.scala
@@ -37,6 +37,6 @@ object Test {
val intp = new IMain(settings, new PrintWriter(new NullOutputStream))
val power = new Power(intp)
intp.interpret("""def initialize = "Have to interpret something or we get errors." """)
- println(power mkTree code)
+ power trees code foreach println
}
}