Using
A utility for performing automatic resource management. It can be used to perform an operation using resources, after which it releases the resources in reverse order of their creation.
==Usage==
There are multiple ways to automatically manage resources with Using. If you only need to manage a single resource, the `apply` method is easiest; it wraps the resource opening, operation, and resource releasing in a Try.
Example:
import java.io.{BufferedReader, FileReader}
import scala.util.{Try, Using}
val lines: Try[Seq[String]] =
Using(new BufferedReader(new FileReader("file.txt"))) { reader =>
Iterator.continually(reader.readLine()).takeWhile(_ != null).toSeq
}
If you need to manage multiple resources, `Using.Manager` should be used. It allows the managing of arbitrarily many resources, whose creation, use, and release are all wrapped in a Try.
Example:
import java.io.{BufferedReader, FileReader}
import scala.util.{Try, Using}
val files = List("file1.txt", "file2.txt", "file3.txt", "file4.txt")
val lines: Try[Seq[String]] = Using.Manager { use =>
// acquire resources
def mkreader(filename: String) = use(new BufferedReader(new FileReader(filename)))
// use your resources here
def lines(reader: BufferedReader): Iterator[String] =
Iterator.continually(reader.readLine()).takeWhile(_ != null)
files.map(mkreader).flatMap(lines)
}
Composed or "wrapped" resources may be acquired in order of construction, if "underlying" resources are not closed. Although redundant in this case, here is the previous example with a wrapped call to use:
def mkreader(filename: String) = use(new BufferedReader(use(new FileReader(filename))))
Custom resources can be registered on construction by requiring an implicit Manager. This ensures they will be released even if composition fails:
import scala.util.Using
case class X(x: String)(implicit mgr: Using.Manager) extends AutoCloseable {
override def close() = println(s"CLOSE $x")
mgr.acquire(this)
}
case class Y(y: String)(x: String)(implicit mgr: Using.Manager) extends AutoCloseable {
val xres = X(x)
override def close() = println(s"CLOSE $y")
// an error during construction releases previously acquired resources
require(y != null, "y is null")
mgr.acquire(this)
}
Using.Manager { implicit mgr =>
val y = Y("Y")("X")
println(s"USE $y")
}
println {
Using.Manager { implicit mgr =>
Y(null)("X")
}
} // Failure(java.lang.IllegalArgumentException: requirement failed: y is null)
If you wish to avoid wrapping management and operations in a Try, you can use `Using.resource`, which throws any exceptions that occur.
Example:
import java.io.{BufferedReader, FileReader}
import scala.util.Using
val lines: Seq[String] =
Using.resource(new BufferedReader(new FileReader("file.txt"))) { reader =>
Iterator.continually(reader.readLine()).takeWhile(_ != null).toSeq
}
==Suppression Behavior==
If two exceptions are thrown (e.g., by an operation and closing a resource), one of them is re-thrown, and the other is added to it as a suppressed exception. If the two exceptions are of different 'severities' (see below), the one of a higher severity is re-thrown, and the one of a lower severity is added to it as a suppressed exception. If the two exceptions are of the same severity, the one thrown first is re-thrown, and the one thrown second is added to it as a suppressed exception. If an exception is a `ControlThrowable`, or if it does not support suppression (see `Throwable`'s constructor with an `enableSuppression` parameter), an exception that would have been suppressed is instead discarded.
Exceptions are ranked from highest to lowest severity as follows:
java.lang.VirtualMachineErrorjava.lang.LinkageErrorjava.lang.InterruptedExceptionandjava.lang.ThreadDeath- fatal exceptions, excluding
scala.util.control.ControlThrowable - all other exceptions, excluding
scala.util.control.ControlThrowable scala.util.control.ControlThrowable
When more than two exceptions are thrown, the first two are combined and re-thrown as described above, and each successive exception thrown is combined as it is thrown.
Attributes
- Graph
-
- Supertypes
- Self type
-
Using.type