diff options
Diffstat (limited to 'src/library')
-rw-r--r-- | src/library/scala/App.scala | 66 | ||||
-rw-r--r-- | src/library/scala/Application.scala | 109 |
2 files changed, 127 insertions, 48 deletions
diff --git a/src/library/scala/App.scala b/src/library/scala/App.scala new file mode 100644 index 0000000000..59c6fccec3 --- /dev/null +++ b/src/library/scala/App.scala @@ -0,0 +1,66 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala + +import scala.compat.Platform.currentTime +import scala.collection.mutable.ListBuffer + +/** The `App` trait can be used to quickly turn objects + * into executable programs. Here is an example: + * {{{ + * object Main extends App { + * Console.println("Hello World: " + (arguments mkString ", ")) + * } + * }}} + * Here, object `Main` inherits the `main` method of `App`. + * + * `args` returns the current command line arguments as an array. + * + * @author Martin Odersky + * @version 2.1, 15/02/2011 + */ +trait App extends DelayedInit { + + /** The time when the execution of this program started, in milliseconds since 1 + * January 1970 UTC. */ + val executionStart: Long = currentTime + + /** The command line arguments passed to the application's `main` method. + */ + protected def args: Array[String] = _args + + private var _args: Array[String] = _ + + private val initCode = new ListBuffer[() => Unit] + + /** The init hook. This saves all initialization code for execution within `main`. + * This method is normally never called directly from user code. + * Instead it is called as compiler-generated code for those classes and objects + * (but not traits) that inherit from the `DelayedInit` trait and that do not themselves define + * a `delayedInit` method. + * @param body the initialization code to be stored for later execution + */ + override def delayedInit(body: => Unit) { + initCode += (() => body) + } + + /** The main method. + * This stores all argument so that they can be retrieved with `args` + * and the executes all initialization code segements in the order they were + * passed to `delayedInit` + * @param args the arguments passed to the main method + */ + def main(args: Array[String]) = { + this._args = args + for (proc <- initCode) proc() + if (util.Properties.propIsSet("scala.time")) { + val total = currentTime - executionStart + Console.println("[total " + total + "ms]") + } + } +} diff --git a/src/library/scala/Application.scala b/src/library/scala/Application.scala index 352f8ee3d6..2060b509b8 100644 --- a/src/library/scala/Application.scala +++ b/src/library/scala/Application.scala @@ -1,71 +1,84 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2010, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ - - - package scala import scala.compat.Platform.currentTime -import scala.collection.mutable.ListBuffer -/** The `Application` trait can be used to quickly turn objects - * into executable programs. Here is an example: - * {{{ - * object Main extends Application { - * Console.println("Hello World: " + (arguments mkString ", ")) - * } - * }}} - * Here, object `Main` inherits the `main` method of `Application`. +/** <p> + * The <code>Application</code> trait can be used to quickly turn objects + * into executable programs, but is <em>not recommended</em>. + * Here is an example: + * </p><pre> + * <b>object</b> Main <b>extends</b> Application { + * Console.println("Hello World!") + * } + * </pre> + * <p> + * Here, object <code>Main</code> inherits the <code>main</code> method + * of <code>Application</code>. The body of the <code>Main</code> object + * defines the main program. This technique does not work if the main + * program depends on command-line arguments (which are not accessible + * with the technique presented here). + * </p> + * <p> + * It is possible to time the execution of objects that inherit from class + * <code>Application</code> by setting the global <code>scala.time</code> + * property. Here is an example for benchmarking object <code>Main</code>: + * </p><pre> + * java -Dscala.time Main + * </pre> + * <p> + * In practice the <code>Application</code> trait has a number of serious + * pitfalls: + * </p> + * <ul> + * <li> Threaded code that references the object will block until static + * initialization is complete. However, because the entire execution of an + * <code>object</code> extending <code>Application</code> takes place during + * static initialization, concurrent code will <em>always</em> deadlock if + * it must synchronize with the enclosing object.</li> + * <li>As described above, there is no way to obtain the + * command-line arguments because all code in body of an <code>object</code> + * extending <code>Application</code> is run as part of the static initialization + * which occurs before <code>Application</code>'s <code>main</code> method + * even begins execution.</li> + * <li>Static initializers are run only once during program execution, and + * JVM authors usually assume their execution to be relatively short. + * Therefore, certain JVM configurations may become confused, or simply fail to + * optimize or JIT the code in the body of an <code>object</code> extending + * <code>Application</code>. This can lead to a significant + * performance degradation.</li> + * </ul> * - * `arguments` returns the current command line arguments as an array. - * - * Note: The use of Application was discouraged prior to 2.9 because - * application code would be run in the object constructor. This is no longer true. - * Application code is now stored and run in the main method. As a consequence, - * extending `Application` is now recommended over implementing `main` explicitly. + * It is recommended to use the `App` trait instead. + * <pre> + * <b>object</b> Main { + * <b>def</b> main(args: Array[String]) { + * //.. + * } + * } + * </pre> * - * @author Martin Odersky - * @version 2.0, 14/12/2010 + * @author Matthias Zenger + * @version 1.0, 10/09/2003 */ -trait Application extends DelayedInit { +@deprecated("use App instead") +trait Application { /** The time when the execution of this program started, in milliseconds since 1 * January 1970 UTC. */ val executionStart: Long = currentTime - /** The command line arguments passed to the application's `main` method. - */ - protected def arguments: Array[String] = args - - private var args: Array[String] = _ - - private val initCode = new ListBuffer[() => Unit] - - /** The init hook. This saves all initialization code for execution within `main`. - * This method is normally never called directly from user code. - * Instead it is called as compiler-generated code for those classes and objects - * (but not traits) that inherit from the `DelayedInit` trait and that do not themselves define - * a `delayedInit` method. - * @param body the initialization code to be stored for later execution - */ - override def delayedInit(body: => Unit) { - initCode += (() => body) - } - - /** The main method. - * This stores all argument so that they can be retrieved with `arguments` - * and the executes all initialization code segements in the order they were - * passed to `delayedInit` + /** The default main method. + * * @param args the arguments passed to the main method */ - def main(args: Array[String]) = { - this.args = args - for (proc <- initCode) proc() + def main(args: Array[String]) { if (util.Properties.propIsSet("scala.time")) { val total = currentTime - executionStart Console.println("[total " + total + "ms]") |