All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gapt.utils.timeout.scala Maven / Gradle / Ivy

The newest version!
package gapt.utils

import scala.concurrent._
import scala.concurrent.duration._
import scala.util.DynamicVariable

class TimeOutException(cause: Throwable, val duration: Duration)
    extends Exception(s"Timeout of $duration exceeded.", cause)

/**
 * runs f with timeout to
 *
 * If f does terminate within to milliseconds returns its result. If not
 * throw a TimeOutException. If f throws an exception it is propagated to
 * the caller of withTimeout.
 *
 * @example
 * {{{
 * try { withTimeout( 1234 ) {
 *   /* ... your code ... */
 * } } catch {
 *   case e: TimeOutException /* ... */
 *   /* other exceptions */
 * }
 * }}}
 */
object withTimeout {
  val logger = Logger("withTimeout")

  @deprecated("Use Durations as argument", "2015-05-15")
  def apply[T](to: Long)(f: => T): T = apply(to millis)(f)

  def apply[T](duration: Duration)(f: => T): T = if (!duration.isFinite) f
  else {
    var result: Either[Throwable, T] = Left(new TimeOutException(null, duration))

    val t = new Thread {
      override def run(): Unit = {
        result =
          try Right(f)
          catch {
            case e: InterruptedException => Left(new TimeOutException(e, duration))
            case t: Throwable            => Left(t)
          }
      }
    }

    t.setDaemon(true)
    t.start()
    blocking { t.join(duration toMillis) }
    t.interrupt()

    val nLine = sys.props("line.separator")

    // wait until variable result has been written
    t.join(1.second toMillis)
    if (t.isAlive) {
      logger.warn("Worker thread still alive; stacktrace:" + nLine + t.getStackTrace.mkString(nLine))
    }

    result match {
      case Left(ex)     => throw ex
      case Right(value) => value
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy