Can someone help me understand the code in NoStackTrace.scala
?
There is a trait defined named NoStackTrace
which I’m using in my code as follows.
def block[A](body:(A=>Nothing)=>A):A = {
// CL like block/return, the name of the return() function is provided
// by the caller.
// Usage: block{ ret => ... ret(someValue) ...}
// extending Exception with NoStackTrace prevents throwing the
// exception from computing the stacktrace and storing the information.
// We don't need a stacktrace because the purpose of this exception
// is simply to perform a non-local exit.
import scala.util.control.NoStackTrace
class NonLocalExit(val data:A) extends Exception with NoStackTrace {}
def ret(data:A):Nothing = {
throw new NonLocalExit(data)
}
try{
body(ret)
}
catch{
case nonLocalExit: NonLocalExit => nonLocalExit.data
}
}
The purpose is to prevent the java fillInStackTrace
method from begin called when a particular exception is constructed. However, the code in the trait definition has some exception to this rule (no pun intended) based on sys.SystemProperties.noTraceSupression
.
What’s the idea behind scala.sys.SystemProperties
and why is that built into this trait as a backdoor?
Here is the code I see in NoStackTrace.scala
when I jump to there in IntelliJ.
/** A trait for exceptions which, for efficiency reasons, do not
* fill in the stack trace. Stack trace suppression can be disabled
* on a global basis via a system property wrapper in
* [[scala.sys.SystemProperties]].
*
* @note Since JDK 1.7, a similar effect can be achieved with `class Ex extends Throwable(..., writableStackTrace = false)`
*
* @author Paul Phillips
* @since 2.8
*/
trait NoStackTrace extends Throwable {
override def fillInStackTrace(): Throwable =
if (NoStackTrace.noSuppression) super.fillInStackTrace()
else this
}
object NoStackTrace {
final def noSuppression = _noSuppression
// two-stage init to make checkinit happy, since sys.SystemProperties.noTraceSuppression.value calls back into NoStackTrace.noSuppression
final private var _noSuppression = false
_noSuppression = sys.SystemProperties.noTraceSuppression.value
}