Skip to content

Instantly share code, notes, and snippets.

@djspiewak
Last active March 6, 2020 16:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save djspiewak/d587d309930e65549430898a16f82749 to your computer and use it in GitHub Desktop.
Save djspiewak/d587d309930e65549430898a16f82749 to your computer and use it in GitHub Desktop.
def interruptable[F[_]: Concurrent: ContextShift](force: Boolean)(thunk: => A): F[A] = {
val fa: F[A] = Concurrent[F] cancelable { cb =>
val t = new Thread(() => cb(Right(thunk)))
t.setDaemon(true)
t.setName("interruptable-thingy-todo")
t setUncaughtExceptionHandler {
case (t, NonFatal(e)) =>
cb(Left(e))
case (_, _: InterruptedException) =>
()
case (_, e) =>
e.printStackTrace()
sys.exit(-1)
}
t.start()
val interruptF = Sync[F].delay(t.interrupt())
val aliveF = Syncp[F].delay(t.isAlive())
// we need to busy-wait, but ensure thread yields between attempts
lazy val loopF: F[Unit] = aliveF.ifM(
(if (force) interruptF else ().pure[F]) >> ContextShift[F].shift >> loopF,
().pure[F])
aliveF.ifM(
interruptF >> ContextShift[F].shift >> loopF,
().pure[F])
}
fa.guarantee(ContextShift[F].shift)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment